xref: /dragonfly/games/hack/hack.steal.c (revision e6d22e9b)
1 /*	$NetBSD: hack.steal.c,v 1.8 2011/08/06 20:29:37 dholland Exp $	*/
2 
3 /*
4  * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
5  * Amsterdam
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are
10  * met:
11  *
12  * - Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * - Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  *
19  * - Neither the name of the Stichting Centrum voor Wiskunde en
20  * Informatica, nor the names of its contributors may be used to endorse or
21  * promote products derived from this software without specific prior
22  * written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 /*
38  * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39  * All rights reserved.
40  *
41  * Redistribution and use in source and binary forms, with or without
42  * modification, are permitted provided that the following conditions
43  * are met:
44  * 1. Redistributions of source code must retain the above copyright
45  *    notice, this list of conditions and the following disclaimer.
46  * 2. Redistributions in binary form must reproduce the above copyright
47  *    notice, this list of conditions and the following disclaimer in the
48  *    documentation and/or other materials provided with the distribution.
49  * 3. The name of the author may not be used to endorse or promote products
50  *    derived from this software without specific prior written permission.
51  *
52  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
55  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62  */
63 
64 #include <stdlib.h>
65 #include "hack.h"
66 #include "extern.h"
67 
68 static int stealarm(void);
69 
70 /*
71  * actually returns something that fits in an int
72  */
73 long
74 somegold(void)
75 {
76 	return ((u.ugold < 100) ? u.ugold :
77 		(u.ugold > 10000) ? rnd(10000) : rnd((int) u.ugold));
78 }
79 
80 void
81 stealgold(struct monst *mtmp)
82 {
83 	struct gold    *gold = g_at(u.ux, u.uy);
84 	long            tmp;
85 	if (gold && (!u.ugold || gold->amount > u.ugold || !rn2(5))) {
86 		mtmp->mgold += gold->amount;
87 		freegold(gold);
88 		if (Invisible)
89 			newsym(u.ux, u.uy);
90 		pline("%s quickly snatches some gold from between your feet!",
91 		      Monnam(mtmp));
92 		if (!u.ugold || !rn2(5)) {
93 			rloc(mtmp);
94 			mtmp->mflee = 1;
95 		}
96 	} else if (u.ugold) {
97 		u.ugold -= (tmp = somegold());
98 		pline("Your purse feels lighter.");
99 		mtmp->mgold += tmp;
100 		rloc(mtmp);
101 		mtmp->mflee = 1;
102 		flags.botl = 1;
103 	}
104 }
105 
106 /* steal armor after he finishes taking it off */
107 static unsigned stealoid;	/* object to be stolen */
108 static unsigned stealmid;	/* monster doing the stealing */
109 static int
110 stealarm(void)
111 {
112 	struct monst   *mtmp;
113 	struct obj     *otmp;
114 
115 	for (otmp = invent; otmp; otmp = otmp->nobj)
116 		if (otmp->o_id == stealoid) {
117 			for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
118 				if (mtmp->m_id == stealmid) {
119 					if (dist(mtmp->mx, mtmp->my) < 3) {
120 						freeinv(otmp);
121 						pline("%s steals %s!", Monnam(mtmp), doname(otmp));
122 						mpickobj(mtmp, otmp);
123 						mtmp->mflee = 1;
124 						rloc(mtmp);
125 					}
126 					break;
127 				}
128 			break;
129 		}
130 	stealoid = 0;
131 	return 0;
132 }
133 
134 /* returns 1 when something was stolen */
135 /* (or at least, when N should flee now) */
136 /* avoid stealing the object stealoid */
137 int
138 steal(struct monst *mtmp)
139 {
140 	struct obj     *otmp;
141 	int		tmp;
142 	int		named = 0;
143 
144 	if (!invent) {
145 		if (Blind)
146 			pline("Somebody tries to rob you, but finds nothing to steal.");
147 		else
148 			pline("%s tries to rob you, but she finds nothing to steal!",
149 			      Monnam(mtmp));
150 		return (1);	/* let her flee */
151 	}
152 	tmp = 0;
153 	for (otmp = invent; otmp; otmp = otmp->nobj)
154 		if (otmp != uarm2)
155 			tmp += ((otmp->owornmask & (W_ARMOR | W_RING)) ? 5 : 1);
156 	tmp = rn2(tmp);
157 	for (otmp = invent; otmp; otmp = otmp->nobj)
158 		if (otmp != uarm2)
159 			if ((tmp -= ((otmp->owornmask & (W_ARMOR | W_RING)) ? 5 : 1))
160 			    < 0)
161 				break;
162 	if (!otmp) {
163 		impossible("Steal fails!");
164 		return (0);
165 	}
166 	if (otmp->o_id == stealoid)
167 		return (0);
168 	if ((otmp->owornmask & (W_ARMOR | W_RING))) {
169 		switch (otmp->olet) {
170 		case RING_SYM:
171 			ringoff(otmp);
172 			break;
173 		case ARMOR_SYM:
174 			if (multi < 0 || otmp == uarms) {
175 				setworn((struct obj *) 0, otmp->owornmask & W_ARMOR);
176 				break;
177 			} {
178 				int             curssv = otmp->cursed;
179 				otmp->cursed = 0;
180 				stop_occupation();
181 				pline("%s seduces you and %s off your %s.",
182 				      Amonnam(mtmp, Blind ? "gentle" : "beautiful"),
183 				      otmp->cursed ? "helps you to take"
184 				      : "you start taking",
185 				      (otmp == uarmg) ? "gloves" :
186 				      (otmp == uarmh) ? "helmet" : "armor");
187 				named++;
188 				(void) armoroff(otmp);
189 				otmp->cursed = curssv;
190 				if (multi < 0) {
191 					/*
192 					multi = 0;
193 					nomovemsg = 0;
194 					afternmv = 0;
195 					*/
196 					stealoid = otmp->o_id;
197 					stealmid = mtmp->m_id;
198 					afternmv = stealarm;
199 					return (0);
200 				}
201 				break;
202 			}
203 		default:
204 			impossible("Tried to steal a strange worn thing.");
205 		}
206 	} else if (otmp == uwep)
207 		setuwep((struct obj *) 0);
208 	if (otmp->olet == CHAIN_SYM) {
209 		impossible("How come you are carrying that chain?");
210 	}
211 	if (Punished && otmp == uball) {
212 		Punished = 0;
213 		freeobj(uchain);
214 		free(uchain);
215 		uchain = (struct obj *) 0;
216 		uball->spe = 0;
217 		uball = (struct obj *) 0;	/* superfluous */
218 	}
219 	freeinv(otmp);
220 	pline("%s stole %s.", named ? "She" : Monnam(mtmp), doname(otmp));
221 	mpickobj(mtmp, otmp);
222 	return ((multi < 0) ? 0 : 1);
223 }
224 
225 void
226 mpickobj(struct monst *mtmp, struct obj *otmp)
227 {
228 	otmp->nobj = mtmp->minvent;
229 	mtmp->minvent = otmp;
230 }
231 
232 int
233 stealamulet(struct monst *mtmp)
234 {
235 	struct obj     *otmp;
236 
237 	for (otmp = invent; otmp; otmp = otmp->nobj) {
238 		if (otmp->olet == AMULET_SYM) {
239 			/* might be an imitation one */
240 			if (otmp == uwep)
241 				setuwep((struct obj *) 0);
242 			freeinv(otmp);
243 			mpickobj(mtmp, otmp);
244 			pline("%s stole %s!", Monnam(mtmp), doname(otmp));
245 			return (1);
246 		}
247 	}
248 	return (0);
249 }
250 
251 /* release the objects the killed animal has stolen */
252 void
253 relobj(struct monst *mtmp, int show)
254 {
255 	struct obj     *otmp, *otmp2;
256 
257 	for (otmp = mtmp->minvent; otmp; otmp = otmp2) {
258 		otmp->ox = mtmp->mx;
259 		otmp->oy = mtmp->my;
260 		otmp2 = otmp->nobj;
261 		otmp->nobj = fobj;
262 		fobj = otmp;
263 		stackobj(fobj);
264 		if (show & cansee(mtmp->mx, mtmp->my))
265 			atl(otmp->ox, otmp->oy, otmp->olet);
266 	}
267 	mtmp->minvent = (struct obj *) 0;
268 	if (mtmp->mgold || mtmp->data->mlet == 'L') {
269 		long            tmp;
270 
271 		tmp = (mtmp->mgold > 10000) ? 10000 : mtmp->mgold;
272 		mkgold((long) (tmp + d(dlevel, 30)), mtmp->mx, mtmp->my);
273 		if (show & cansee(mtmp->mx, mtmp->my))
274 			atl(mtmp->mx, mtmp->my, '$');
275 	}
276 }
277