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