xref: /netbsd-src/games/hack/hack.steal.c (revision d710132b4b8ce7f7cccaaf660cb16aa16b4077a0)
1 /*	$NetBSD: hack.steal.c,v 1.5 2003/04/02 18:36:40 jsm 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 <sys/cdefs.h>
65 #ifndef lint
66 __RCSID("$NetBSD: hack.steal.c,v 1.5 2003/04/02 18:36:40 jsm Exp $");
67 #endif				/* not lint */
68 
69 #include <stdlib.h>
70 #include "hack.h"
71 #include "extern.h"
72 
73 long				/* actually returns something that fits in an
74 				 * int */
75 somegold()
76 {
77 	return ((u.ugold < 100) ? u.ugold :
78 		(u.ugold > 10000) ? rnd(10000) : rnd((int) u.ugold));
79 }
80 
81 void
82 stealgold(mtmp)
83 	struct monst   *mtmp;
84 {
85 	struct gold    *gold = g_at(u.ux, u.uy);
86 	long            tmp;
87 	if (gold && (!u.ugold || gold->amount > u.ugold || !rn2(5))) {
88 		mtmp->mgold += gold->amount;
89 		freegold(gold);
90 		if (Invisible)
91 			newsym(u.ux, u.uy);
92 		pline("%s quickly snatches some gold from between your feet!",
93 		      Monnam(mtmp));
94 		if (!u.ugold || !rn2(5)) {
95 			rloc(mtmp);
96 			mtmp->mflee = 1;
97 		}
98 	} else if (u.ugold) {
99 		u.ugold -= (tmp = somegold());
100 		pline("Your purse feels lighter.");
101 		mtmp->mgold += tmp;
102 		rloc(mtmp);
103 		mtmp->mflee = 1;
104 		flags.botl = 1;
105 	}
106 }
107 
108 /* steal armor after he finishes taking it off */
109 unsigned        stealoid;	/* object to be stolen */
110 unsigned        stealmid;	/* monster doing the stealing */
111 int
112 stealarm()
113 {
114 	struct monst   *mtmp;
115 	struct obj     *otmp;
116 
117 	for (otmp = invent; otmp; otmp = otmp->nobj)
118 		if (otmp->o_id == stealoid) {
119 			for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
120 				if (mtmp->m_id == stealmid) {
121 					if (dist(mtmp->mx, mtmp->my) < 3) {
122 						freeinv(otmp);
123 						pline("%s steals %s!", Monnam(mtmp), doname(otmp));
124 						mpickobj(mtmp, otmp);
125 						mtmp->mflee = 1;
126 						rloc(mtmp);
127 					}
128 					break;
129 				}
130 			break;
131 		}
132 	stealoid = 0;
133 	return 0;
134 }
135 
136 /* returns 1 when something was stolen */
137 /* (or at least, when N should flee now) */
138 /* avoid stealing the object stealoid */
139 int
140 steal(mtmp)
141 	struct monst   *mtmp;
142 {
143 	struct obj     *otmp;
144 	int		tmp;
145 	int		named = 0;
146 
147 	if (!invent) {
148 		if (Blind)
149 			pline("Somebody tries to rob you, but finds nothing to steal.");
150 		else
151 			pline("%s tries to rob you, but she finds nothing to steal!",
152 			      Monnam(mtmp));
153 		return (1);	/* let her flee */
154 	}
155 	tmp = 0;
156 	for (otmp = invent; otmp; otmp = otmp->nobj)
157 		if (otmp != uarm2)
158 			tmp += ((otmp->owornmask & (W_ARMOR | W_RING)) ? 5 : 1);
159 	tmp = rn2(tmp);
160 	for (otmp = invent; otmp; otmp = otmp->nobj)
161 		if (otmp != uarm2)
162 			if ((tmp -= ((otmp->owornmask & (W_ARMOR | W_RING)) ? 5 : 1))
163 			    < 0)
164 				break;
165 	if (!otmp) {
166 		impossible("Steal fails!");
167 		return (0);
168 	}
169 	if (otmp->o_id == stealoid)
170 		return (0);
171 	if ((otmp->owornmask & (W_ARMOR | W_RING))) {
172 		switch (otmp->olet) {
173 		case RING_SYM:
174 			ringoff(otmp);
175 			break;
176 		case ARMOR_SYM:
177 			if (multi < 0 || otmp == uarms) {
178 				setworn((struct obj *) 0, otmp->owornmask & W_ARMOR);
179 				break;
180 			} {
181 				int             curssv = otmp->cursed;
182 				otmp->cursed = 0;
183 				stop_occupation();
184 				pline("%s seduces you and %s off your %s.",
185 				      Amonnam(mtmp, Blind ? "gentle" : "beautiful"),
186 				      otmp->cursed ? "helps you to take"
187 				      : "you start taking",
188 				      (otmp == uarmg) ? "gloves" :
189 				      (otmp == uarmh) ? "helmet" : "armor");
190 				named++;
191 				(void) armoroff(otmp);
192 				otmp->cursed = curssv;
193 				if (multi < 0) {
194 					/*
195 					multi = 0;
196 					nomovemsg = 0;
197 					afternmv = 0;
198 					*/
199 					stealoid = otmp->o_id;
200 					stealmid = mtmp->m_id;
201 					afternmv = stealarm;
202 					return (0);
203 				}
204 				break;
205 			}
206 		default:
207 			impossible("Tried to steal a strange worn thing.");
208 		}
209 	} else if (otmp == uwep)
210 		setuwep((struct obj *) 0);
211 	if (otmp->olet == CHAIN_SYM) {
212 		impossible("How come you are carrying that chain?");
213 	}
214 	if (Punished && otmp == uball) {
215 		Punished = 0;
216 		freeobj(uchain);
217 		free((char *) uchain);
218 		uchain = (struct obj *) 0;
219 		uball->spe = 0;
220 		uball = (struct obj *) 0;	/* superfluous */
221 	}
222 	freeinv(otmp);
223 	pline("%s stole %s.", named ? "She" : Monnam(mtmp), doname(otmp));
224 	mpickobj(mtmp, otmp);
225 	return ((multi < 0) ? 0 : 1);
226 }
227 
228 void
229 mpickobj(mtmp, otmp)
230 	struct monst   *mtmp;
231 	struct obj     *otmp;
232 {
233 	otmp->nobj = mtmp->minvent;
234 	mtmp->minvent = otmp;
235 }
236 
237 int
238 stealamulet(mtmp)
239 	struct monst   *mtmp;
240 {
241 	struct obj     *otmp;
242 
243 	for (otmp = invent; otmp; otmp = otmp->nobj) {
244 		if (otmp->olet == AMULET_SYM) {
245 			/* might be an imitation one */
246 			if (otmp == uwep)
247 				setuwep((struct obj *) 0);
248 			freeinv(otmp);
249 			mpickobj(mtmp, otmp);
250 			pline("%s stole %s!", Monnam(mtmp), doname(otmp));
251 			return (1);
252 		}
253 	}
254 	return (0);
255 }
256 
257 /* release the objects the killed animal has stolen */
258 void
259 relobj(mtmp, show)
260 	struct monst   *mtmp;
261 	int show;
262 {
263 	struct obj     *otmp, *otmp2;
264 
265 	for (otmp = mtmp->minvent; otmp; otmp = otmp2) {
266 		otmp->ox = mtmp->mx;
267 		otmp->oy = mtmp->my;
268 		otmp2 = otmp->nobj;
269 		otmp->nobj = fobj;
270 		fobj = otmp;
271 		stackobj(fobj);
272 		if (show & cansee(mtmp->mx, mtmp->my))
273 			atl(otmp->ox, otmp->oy, otmp->olet);
274 	}
275 	mtmp->minvent = (struct obj *) 0;
276 	if (mtmp->mgold || mtmp->data->mlet == 'L') {
277 		long            tmp;
278 
279 		tmp = (mtmp->mgold > 10000) ? 10000 : mtmp->mgold;
280 		mkgold((long) (tmp + d(dlevel, 30)), mtmp->mx, mtmp->my);
281 		if (show & cansee(mtmp->mx, mtmp->my))
282 			atl(mtmp->mx, mtmp->my, '$');
283 	}
284 }
285