1 /*	SCCS Id: @(#)sit.c	3.4	2002/09/21	*/
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed.  See license for details. */
4 
5 #include "hack.h"
6 #include "artifact.h"
7 
8 STATIC_DCL void FDECL(curse_objects, (struct obj *, int, boolean));
9 
10 void
take_gold()11 take_gold()
12 {
13 #ifndef GOLDOBJ
14 	if (u.ugold <= 0)  {
15 		You_feel("a strange sensation.");
16 	} else {
17 		You("notice you have no gold!");
18 		u.ugold = 0;
19 		flags.botl = 1;
20 	}
21 #else
22         struct obj *otmp, *nobj;
23 	int lost_money = 0;
24 	for (otmp = invent; otmp; otmp = nobj) {
25 		nobj = otmp->nobj;
26 		if (otmp->oclass == COIN_CLASS) {
27 			lost_money = 1;
28 			delobj(otmp);
29 		}
30 	}
31 	if (!lost_money)  {
32 		You_feel("a strange sensation.");
33 	} else {
34 		You("notice you have no money!");
35 		flags.botl = 1;
36 	}
37 #endif
38 }
39 
40 int
dosit()41 dosit()
42 {
43 	static const char sit_message[] = "sit on the %s.";
44 	register struct trap *trap;
45 	register int typ = levl[u.ux][u.uy].typ;
46 
47 
48 #ifdef STEED
49 	if (u.usteed) {
50 	    You("are already sitting on %s.", mon_nam(u.usteed));
51 	    return (0);
52 	}
53 #endif
54 
55 	if(!can_reach_floor())	{
56 	    if (Levitation)
57 		You("tumble in place.");
58 	    else
59 		You("are sitting on air.");
60 	    return 0;
61 	} else if (is_pool(u.ux, u.uy) && !Underwater) {  /* water walking */
62 	    goto in_water;
63 	}
64 
65 	if(OBJ_AT(u.ux, u.uy)) {
66 	    register struct obj *obj;
67 
68 	    obj = level.objects[u.ux][u.uy];
69 	    You("sit on %s.", the(xname(obj)));
70 	    if (!(Is_box(obj) || objects[obj->otyp].oc_material == CLOTH))
71 		pline("It's not very comfortable...");
72 
73 	} else if ((trap = t_at(u.ux, u.uy)) != 0 ||
74 		   (u.utrap && (u.utraptype >= TT_LAVA))) {
75 
76 	    if (u.utrap) {
77 		exercise(A_WIS, FALSE);	/* you're getting stuck longer */
78 		if(u.utraptype == TT_BEARTRAP) {
79 		    You_cant("sit down with your %s in the bear trap.", body_part(FOOT));
80 		    u.utrap++;
81 	        } else if(u.utraptype == TT_PIT) {
82 		    if(trap->ttyp == SPIKED_PIT) {
83 			You("sit down on a spike.  Ouch!");
84 			losehp(1, "sitting on an iron spike", KILLED_BY);
85 			exercise(A_STR, FALSE);
86 		    } else
87 			You("sit down in the pit.");
88 		    u.utrap += rn2(5);
89 		} else if(u.utraptype == TT_WEB) {
90 		    You("sit in the spider web and get entangled further!");
91 		    u.utrap += rn1(10, 5);
92 		} else if(u.utraptype == TT_LAVA) {
93 		    /* Must have fire resistance or they'd be dead already */
94 		    You("sit in the lava!");
95 		    u.utrap += rnd(4);
96 		    losehp(d(2,10), "sitting in lava", KILLED_BY);
97 		} else if(u.utraptype == TT_INFLOOR) {
98 		    You_cant("maneuver to sit!");
99 		    u.utrap++;
100 		}
101 	    } else {
102 	        You("sit down.");
103 		dotrap(trap, 0);
104 	    }
105 	} else if(Underwater || Is_waterlevel(&u.uz)) {
106 	    if (Is_waterlevel(&u.uz))
107 		There("are no cushions floating nearby.");
108 	    else
109 		You("sit down on the muddy bottom.");
110 	} else if(is_pool(u.ux, u.uy)) {
111  in_water:
112 	    You("sit in the water.");
113 	    if (!rn2(10) && uarm)
114 		(void) rust_dmg(uarm, "armor", 1, TRUE, &youmonst);
115 	    if (!rn2(10) && uarmf && uarmf->otyp != WATER_WALKING_BOOTS)
116 		(void) rust_dmg(uarm, "armor", 1, TRUE, &youmonst);
117 #ifdef SINKS
118 	} else if(IS_SINK(typ)) {
119 
120 	    You(sit_message, defsyms[S_sink].explanation);
121 	    Your("%s gets wet.", humanoid(youmonst.data) ? "rump" : "underside");
122 #endif
123 	} else if(IS_ALTAR(typ)) {
124 
125 	    You(sit_message, defsyms[S_altar].explanation);
126 	    altar_wrath(u.ux, u.uy);
127 
128 	} else if(IS_GRAVE(typ)) {
129 
130 	    You(sit_message, defsyms[S_grave].explanation);
131 
132 	} else if(typ == STAIRS) {
133 
134 	    You(sit_message, "stairs");
135 
136 	} else if(typ == LADDER) {
137 
138 	    You(sit_message, "ladder");
139 
140 	} else if (is_lava(u.ux, u.uy)) {
141 
142 	    /* must be WWalking */
143 	    You(sit_message, "lava");
144 	    burn_away_slime();
145 	    if (likes_lava(youmonst.data)) {
146 		pline_The("lava feels warm.");
147 		return 1;
148 	    }
149 	    pline_The("lava burns you!");
150 	    losehp(d((Fire_resistance ? 2 : 10), 10),
151 		   "sitting on lava", KILLED_BY);
152 
153 	} else if (is_ice(u.ux, u.uy)) {
154 
155 	    You(sit_message, defsyms[S_ice].explanation);
156 	    if (!Cold_resistance) pline_The("ice feels cold.");
157 
158 	} else if (typ == DRAWBRIDGE_DOWN) {
159 
160 	    You(sit_message, "drawbridge");
161 
162 	} else if(IS_THRONE(typ)) {
163 
164 	    You(sit_message, defsyms[S_throne].explanation);
165 	    if (rnd(6) > 4)  {
166 		switch (rnd(13))  {
167 		    case 1:
168 			(void) adjattrib(rn2(A_MAX), -rn1(4,3), FALSE);
169 			losehp(rnd(10), "cursed throne", KILLED_BY_AN);
170 			break;
171 		    case 2:
172 			(void) adjattrib(rn2(A_MAX), 1, FALSE);
173 			break;
174 		    case 3:
175 			pline("A%s electric shock shoots through your body!",
176 			      (Shock_resistance) ? "n" : " massive");
177 			losehp(Shock_resistance ? rnd(6) : rnd(30),
178 			       "electric chair", KILLED_BY_AN);
179 			exercise(A_CON, FALSE);
180 			break;
181 		    case 4:
182 			You_feel("much, much better!");
183 			if (Upolyd) {
184 			    if (u.mh >= (u.mhmax - 5))  u.mhmax += 4;
185 			    u.mh = u.mhmax;
186 			}
187 			if(u.uhp >= (u.uhpmax - 5))  u.uhpmax += 4;
188 			u.uhp = u.uhpmax;
189 			make_blinded(0L,TRUE);
190 			make_sick(0L, (char *) 0, FALSE, SICK_ALL);
191 			heal_legs();
192 			flags.botl = 1;
193 			break;
194 		    case 5:
195 			take_gold();
196 			break;
197 		    case 6:
198 			if (u.uluck + rn2(5) < 0) {
199 				You_feel("your luck is changing.");
200 				change_luck(1);
201 			} else {
202 				fix_attributes_and_properties((struct obj *)0, 6);
203 			}
204 			break;
205 		    case 7:
206 			{
207 			register int cnt = rnd(10);
208 
209 			pline("A voice echoes:");
210 			verbalize("Thy audience hath been summoned, %s!",
211 				  flags.female ? "Dame" : "Sire");
212 			while(cnt--)
213 			    (void) makemon(courtmon(), u.ux, u.uy, NO_MM_FLAGS);
214 			break;
215 			}
216 		    case 8:
217 			pline("A voice echoes:");
218 			verbalize("By thy Imperious order, %s...",
219 				  flags.female ? "Dame" : "Sire");
220 			do_genocide(5, FALSE);	/* REALLY|ONTHRONE, see do_genocide() */
221 			break;
222 		    case 9:
223 			pline("A voice echoes:");
224 	verbalize("A curse upon thee for sitting upon this most holy throne!");
225 			if (Luck > 0)  {
226 			    make_blinded(Blinded + rn1(100,250),TRUE);
227 			} else	    rndcurse();
228 			break;
229 		    case 10:
230 			if (Luck < 0 || (HSee_invisible & INTRINSIC))  {
231 				if (level.flags.nommap) {
232 					pline(
233 					"A terrible drone fills your head!");
234 					make_confused(HConfusion + rnd(30),
235 									FALSE);
236 				} else {
237 					pline("An image forms in your mind.");
238 					do_mapping();
239 				}
240 			} else  {
241 				Your("vision becomes clear.");
242 				HSee_invisible |= FROMOUTSIDE;
243 				newsym(u.ux, u.uy);
244 			}
245 			break;
246 		    case 11:
247 			if (Luck < 0)  {
248 			    You_feel("threatened.");
249 			    aggravate();
250 			} else  {
251 
252 			    You_feel("a wrenching sensation.");
253 			    tele();		/* teleport him */
254 			}
255 			break;
256 		    case 12:
257 			You("are granted an insight!");
258 			if (invent) {
259 			    /* rn2(5) agrees w/seffects() */
260 			    identify_pack(rn2(5));
261 			}
262 			break;
263 		    case 13:
264 			Your("mind turns into a pretzel!");
265 			make_confused(HConfusion + rn1(7,16),FALSE);
266 			break;
267 		    default:	impossible("throne effect");
268 				break;
269 		}
270 	    } else {
271 		if (is_prince(youmonst.data))
272 		    You_feel("very comfortable here.");
273 		else
274 		    You_feel("somehow out of place...");
275 	    }
276 
277 	    if (!rn2(3) && IS_THRONE(levl[u.ux][u.uy].typ)) {
278 		/* may have teleported */
279 		levl[u.ux][u.uy].typ = ROOM;
280 		pline_The("throne vanishes in a puff of logic.");
281 		newsym(u.ux,u.uy);
282 	    }
283 
284 	} else if (lays_eggs(youmonst.data)) {
285 		struct obj *uegg;
286 
287 		if (!flags.female) {
288 			pline("Males can't lay eggs!");
289 			return 0;
290 		}
291 
292 		if (u.uhunger < (int)objects[EGG].oc_nutrition) {
293 			You("don't have enough energy to lay an egg.");
294 			return 0;
295 		}
296 
297 		uegg = mksobj(EGG, FALSE, FALSE);
298 		uegg->spe = 1;
299 		uegg->quan = 1;
300 		uegg->owt = weight(uegg);
301 		uegg->corpsenm = egg_type_from_parent(u.umonnum, FALSE);
302 		uegg->known = uegg->dknown = 1;
303 		attach_egg_hatch_timeout(uegg);
304 		You("lay an egg.");
305 		dropy(uegg);
306 		stackobj(uegg);
307 		morehungry((int)objects[EGG].oc_nutrition);
308 	} else if (u.uswallow)
309 		There("are no seats in here!");
310 	else
311 		pline("Having fun sitting on the %s?", surface(u.ux,u.uy));
312 	return(1);
313 }
314 
315 void
rndcurse()316 rndcurse()			/* curse a few inventory items at random! */
317 {
318 	struct	obj	*otmp;
319 	static const char mal_aura[] = "feel a malignant aura surround %s.";
320 
321 	if (uwep && (uwep->oartifact == ART_MAGICBANE) && rn2(20)) {
322 	    You(mal_aura, "the magic-absorbing blade");
323 	    return;
324 	}
325 
326 	if(Antimagic) {
327 	    shieldeff(u.ux, u.uy);
328 	    You(mal_aura, "you");
329 	}
330 
331 	curse_objects(invent,
332 		rnd(6/((!!Antimagic) + (!!Half_spell_damage) + 1)), TRUE);
333 
334 #ifdef STEED
335 	/* treat steed's saddle as extended part of hero's inventory */
336 	if (u.usteed && !rn2(4) &&
337 		(otmp = which_armor(u.usteed, W_SADDLE)) != 0 &&
338 		!otmp->cursed) {	/* skip if already cursed */
339 	    if (otmp->blessed)
340 		unbless(otmp);
341 	    else
342 		curse(otmp);
343 	    if (!Blind) {
344 		pline("%s %s %s.",
345 		      s_suffix(upstart(y_monnam(u.usteed))),
346 		      aobjnam(otmp, "glow"),
347 		      hcolor(otmp->cursed ? NH_BLACK : (const char *)"brown"));
348 		otmp->bknown = TRUE;
349 	    }
350 	}
351 #endif	/*STEED*/
352 }
353 
354 void
curse_objects(firstobj,ncurse,showmsg)355 curse_objects(firstobj, ncurse, showmsg)
356 struct obj *firstobj;
357 int ncurse;
358 boolean showmsg;
359 {
360     struct obj *otmp;
361     int cnt, onum;
362     int nobj = 0;
363 
364     for (otmp = firstobj; otmp; otmp = otmp->nobj) {
365 #ifdef GOLDOBJ
366 	/* gold isn't subject to being cursed or blessed */
367 	if (otmp->oclass == COIN_CLASS) continue;
368 #endif
369 	nobj++;
370     }
371     if (nobj) {
372 	for (cnt = ncurse; cnt > 0; cnt--)  {
373 	    onum = rnd(nobj);
374 	    for (otmp = firstobj; otmp; otmp = otmp->nobj) {
375 #ifdef GOLDOBJ
376 		/* as above */
377 		if (otmp->oclass == COIN_CLASS) continue;
378 #endif
379 		if (--onum == 0) break;	/* found the target */
380 	    }
381 	    /* the !otmp case should never happen; picking an already
382 	       cursed item happens--avoid "resists" message in that case */
383 	    if (!otmp) continue;	/* next target */
384 	    else if (otmp->cursed) {
385 		if (Is_container(otmp))
386 		    curse_objects(otmp->cobj, 1, FALSE);
387 		continue;
388 	    }
389 
390 	    if(otmp->oartifact && spec_ability(otmp, SPFX_INTEL) &&
391 	       rn2(10) < 8) {
392 		if (showmsg)
393 		    pline("%s!", Tobjnam(otmp, "resist"));
394 		continue;
395 	    }
396 
397 	    if(otmp->blessed)
398 		unbless(otmp);
399 	    else
400 		curse(otmp);
401 	}
402 	update_inventory();
403     }
404 }
405 
406 void
attrcurse()407 attrcurse()			/* remove a random INTRINSIC ability */
408 {
409 	switch(rnd(11)) {
410 	case 1 : if (HFire_resistance & INTRINSIC) {
411 			HFire_resistance &= ~INTRINSIC;
412 			You_feel("warmer.");
413 			break;
414 		}
415 	case 2 : if (HTeleportation & INTRINSIC) {
416 			HTeleportation &= ~INTRINSIC;
417 			You_feel("less jumpy.");
418 			break;
419 		}
420 	case 3 : if (HPoison_resistance & INTRINSIC) {
421 			HPoison_resistance &= ~INTRINSIC;
422 			You_feel("a little sick!");
423 			break;
424 		}
425 	case 4 : if (HTelepat & INTRINSIC) {
426 			HTelepat &= ~INTRINSIC;
427 			if (Blind && !Blind_telepat)
428 			    see_monsters();	/* Can't sense mons anymore! */
429 			Your("senses fail!");
430 			break;
431 		}
432 	case 5 : if (HCold_resistance & INTRINSIC) {
433 			HCold_resistance &= ~INTRINSIC;
434 			You_feel("cooler.");
435 			break;
436 		}
437 	case 6 : if (HInvis & INTRINSIC) {
438 			HInvis &= ~INTRINSIC;
439 			You_feel("paranoid.");
440 			break;
441 		}
442 	case 7 : if (HSee_invisible & INTRINSIC) {
443 			HSee_invisible &= ~INTRINSIC;
444 			You("%s!", Hallucination ? "tawt you taw a puttie tat"
445 						: "thought you saw something");
446 			break;
447 		}
448 	case 8 : if (HFast & INTRINSIC) {
449 			HFast &= ~INTRINSIC;
450 			You_feel("slower.");
451 			break;
452 		}
453 	case 9 : if (HStealth & INTRINSIC) {
454 			HStealth &= ~INTRINSIC;
455 			You_feel("clumsy.");
456 			break;
457 		}
458 	case 10: if (HProtection & INTRINSIC) {
459 			HProtection &= ~INTRINSIC;
460 			You_feel("vulnerable.");
461 			u.ublessed = 0; /* fix for C343-189 */
462 			break;
463 		}
464 	case 11: if (HAggravate_monster & INTRINSIC) {
465 			HAggravate_monster &= ~INTRINSIC;
466 			You_feel("less attractive.");
467 			break;
468 		}
469 	default: break;
470 	}
471 }
472 
473 /*sit.c*/
474