Commit | Line | Data |
---|---|---|
984263bc MD |
1 | /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ |
2 | /* hack.apply.c - version 1.0.3 */ | |
3 | /* $FreeBSD: src/games/hack/hack.apply.c,v 1.4.2.1 2001/02/18 02:20:07 kris Exp $ */ | |
c7106d58 | 4 | /* $DragonFly: src/games/hack/hack.apply.c,v 1.4 2006/08/21 19:45:32 pavalos Exp $ */ |
984263bc | 5 | |
6693db17 SW |
6 | #include "hack.h" |
7 | #include "def.edog.h" | |
984263bc | 8 | extern char quitchars[]; |
984263bc | 9 | |
c7106d58 PA |
10 | static void use_camera(struct obj *); |
11 | static bool in_ice_box(struct obj *); | |
12 | static bool ck_ice_box(struct obj *); | |
13 | static int out_ice_box(struct obj *); | |
14 | static void use_ice_box(struct obj *); | |
15 | static struct monst *bchit(int, int, int, char); | |
16 | static void use_whistle(struct obj *); | |
17 | static void use_magic_whistle(struct obj *); | |
18 | static bool dig(void); | |
19 | static int use_pick_axe(struct obj *); | |
984263bc | 20 | |
c7106d58 PA |
21 | int |
22 | doapply(void) | |
23 | { | |
984263bc MD |
24 | struct obj *obj; |
25 | int res = 1; | |
26 | ||
27 | obj = getobj("(", "use or apply"); | |
6693db17 SW |
28 | if (!obj) |
29 | return (0); | |
984263bc | 30 | |
6693db17 | 31 | switch (obj->otyp) { |
984263bc | 32 | case EXPENSIVE_CAMERA: |
6693db17 SW |
33 | use_camera(obj); |
34 | break; | |
984263bc | 35 | case ICE_BOX: |
6693db17 SW |
36 | use_ice_box(obj); |
37 | break; | |
984263bc MD |
38 | case PICK_AXE: |
39 | res = use_pick_axe(obj); | |
40 | break; | |
41 | ||
42 | case MAGIC_WHISTLE: | |
6693db17 | 43 | if (pl_character[0] == 'W' || u.ulevel > 9) { |
984263bc MD |
44 | use_magic_whistle(obj); |
45 | break; | |
46 | } | |
47 | /* fall into next case */ | |
48 | case WHISTLE: | |
49 | use_whistle(obj); | |
50 | break; | |
51 | ||
52 | case CAN_OPENER: | |
6693db17 | 53 | if (!carrying(TIN)) { |
984263bc MD |
54 | pline("You have no can to open."); |
55 | goto xit; | |
56 | } | |
57 | pline("You cannot open a tin without eating its contents."); | |
58 | pline("In order to eat, use the 'e' command."); | |
6693db17 SW |
59 | if (obj != uwep) |
60 | pline("Opening the tin will be much easier if you wield the can-opener."); | |
984263bc MD |
61 | goto xit; |
62 | ||
63 | default: | |
64 | pline("Sorry, I don't know how to use that."); | |
6693db17 | 65 | xit: |
984263bc | 66 | nomul(0); |
6693db17 | 67 | return (0); |
984263bc MD |
68 | } |
69 | nomul(0); | |
6693db17 | 70 | return (res); |
984263bc MD |
71 | } |
72 | ||
984263bc | 73 | static void |
6693db17 | 74 | use_camera(struct obj *obj __unused) |
c7106d58 | 75 | { |
6693db17 SW |
76 | struct monst *mtmp; |
77 | ||
78 | if (!getdir(1)) { /* ask: in what direction? */ | |
984263bc MD |
79 | flags.move = multi = 0; |
80 | return; | |
81 | } | |
6693db17 | 82 | if (u.uswallow) { |
984263bc MD |
83 | pline("You take a picture of %s's stomach.", monnam(u.ustuck)); |
84 | return; | |
85 | } | |
6693db17 | 86 | if (u.dz) { |
984263bc | 87 | pline("You take a picture of the %s.", |
6693db17 | 88 | (u.dz > 0) ? "floor" : "ceiling"); |
984263bc MD |
89 | return; |
90 | } | |
6693db17 SW |
91 | if ((mtmp = bchit(u.dx, u.dy, COLNO, '!')) != NULL) { |
92 | if (mtmp->msleep) { | |
984263bc | 93 | mtmp->msleep = 0; |
6693db17 SW |
94 | pline("The flash awakens %s.", monnam(mtmp)); /* a3 */ |
95 | } else if (mtmp->data->mlet != 'y') | |
96 | if (mtmp->mcansee || mtmp->mblinded) { | |
97 | int tmp = dist(mtmp->mx, mtmp->my); | |
98 | int tmp2; | |
99 | if (cansee(mtmp->mx, mtmp->my)) | |
100 | pline("%s is blinded by the flash!", Monnam(mtmp)); | |
101 | setmangry(mtmp); | |
102 | if (tmp < 9 && !mtmp->isshk && rn2(4)) { | |
103 | mtmp->mflee = 1; | |
104 | if (rn2(4)) | |
105 | mtmp->mfleetim = rnd(100); | |
106 | } | |
107 | if (tmp < 3) | |
108 | mtmp->mcansee = mtmp->mblinded = 0; | |
109 | else { | |
110 | tmp2 = mtmp->mblinded; | |
111 | tmp2 += rnd(1 + 50 / tmp); | |
112 | if (tmp2 > 127) | |
113 | tmp2 = 127; | |
114 | mtmp->mblinded = tmp2; | |
115 | mtmp->mcansee = 0; | |
116 | } | |
984263bc | 117 | } |
984263bc MD |
118 | } |
119 | } | |
120 | ||
121 | static | |
122 | struct obj *current_ice_box; /* a local variable of use_ice_box, to be | |
123 | used by its local procedures in/ck_ice_box */ | |
c7106d58 PA |
124 | static bool |
125 | in_ice_box(struct obj *obj) | |
126 | { | |
6693db17 SW |
127 | if (obj == current_ice_box || |
128 | (Punished && (obj == uball || obj == uchain))) { | |
984263bc | 129 | pline("You must be kidding."); |
6693db17 | 130 | return (0); |
984263bc | 131 | } |
6693db17 | 132 | if (obj->owornmask & (W_ARMOR | W_RING)) { |
984263bc | 133 | pline("You cannot refrigerate something you are wearing."); |
6693db17 | 134 | return (0); |
984263bc | 135 | } |
6693db17 | 136 | if (obj->owt + current_ice_box->owt > 70) { |
984263bc | 137 | pline("It won't fit."); |
6693db17 | 138 | return (1); /* be careful! */ |
984263bc | 139 | } |
6693db17 SW |
140 | if (obj == uwep) { |
141 | if (uwep->cursed) { | |
984263bc | 142 | pline("Your weapon is welded to your hand!"); |
6693db17 | 143 | return (0); |
984263bc | 144 | } |
902ec341 | 145 | setuwep(NULL); |
984263bc MD |
146 | } |
147 | current_ice_box->owt += obj->owt; | |
148 | freeinv(obj); | |
149 | obj->o_cnt_id = current_ice_box->o_id; | |
150 | obj->nobj = fcobj; | |
151 | fcobj = obj; | |
152 | obj->age = moves - obj->age; /* actual age */ | |
6693db17 | 153 | return (1); |
984263bc MD |
154 | } |
155 | ||
c7106d58 PA |
156 | static bool |
157 | ck_ice_box(struct obj *obj) | |
158 | { | |
6693db17 | 159 | return (obj->o_cnt_id == current_ice_box->o_id); |
984263bc MD |
160 | } |
161 | ||
c7106d58 PA |
162 | static int |
163 | out_ice_box(struct obj *obj) | |
164 | { | |
6693db17 SW |
165 | struct obj *otmp; |
166 | ||
167 | if (obj == fcobj) | |
168 | fcobj = fcobj->nobj; | |
984263bc | 169 | else { |
6693db17 SW |
170 | for (otmp = fcobj; otmp->nobj != obj; otmp = otmp->nobj) |
171 | if (!otmp->nobj) | |
172 | panic("out_ice_box"); | |
984263bc MD |
173 | otmp->nobj = obj->nobj; |
174 | } | |
175 | current_ice_box->owt -= obj->owt; | |
176 | obj->age = moves - obj->age; /* simulated point of time */ | |
c7106d58 | 177 | addinv(obj); |
6693db17 | 178 | return (0); |
984263bc MD |
179 | } |
180 | ||
181 | static void | |
c7106d58 PA |
182 | use_ice_box(struct obj *obj) |
183 | { | |
6693db17 SW |
184 | int cnt = 0; |
185 | struct obj *otmp; | |
186 | ||
984263bc | 187 | current_ice_box = obj; /* for use by in/out_ice_box */ |
6693db17 SW |
188 | for (otmp = fcobj; otmp; otmp = otmp->nobj) |
189 | if (otmp->o_cnt_id == obj->o_id) | |
984263bc | 190 | cnt++; |
6693db17 SW |
191 | if (!cnt) |
192 | pline("Your ice-box is empty."); | |
984263bc | 193 | else { |
6693db17 SW |
194 | pline("Do you want to take something out of the ice-box? [yn] "); |
195 | if (readchar() == 'y') | |
196 | if (askchain(fcobj, NULL, 0, out_ice_box, ck_ice_box, 0)) | |
197 | return; | |
984263bc | 198 | pline("That was all. Do you wish to put something in? [yn] "); |
6693db17 SW |
199 | if (readchar() != 'y') |
200 | return; | |
984263bc MD |
201 | } |
202 | /* call getobj: 0: allow cnt; #: allow all types; %: expect food */ | |
203 | otmp = getobj("0#%", "put in"); | |
6693db17 | 204 | if (!otmp || !in_ice_box(otmp)) |
984263bc MD |
205 | flags.move = multi = 0; |
206 | } | |
207 | ||
6693db17 SW |
208 | static |
209 | struct monst * | |
c7106d58 PA |
210 | bchit(int ddx, int ddy, int range, char sym) |
211 | { | |
902ec341 | 212 | struct monst *mtmp = NULL; |
984263bc MD |
213 | int bchx = u.ux, bchy = u.uy; |
214 | ||
6693db17 SW |
215 | if (sym) |
216 | Tmp_at(-1, sym); /* open call */ | |
217 | while (range--) { | |
984263bc MD |
218 | bchx += ddx; |
219 | bchy += ddy; | |
6693db17 | 220 | if ((mtmp = m_at(bchx, bchy))) |
984263bc | 221 | break; |
6693db17 | 222 | if (!ZAP_POS(levl[bchx][bchy].typ)) { |
984263bc MD |
223 | bchx -= ddx; |
224 | bchy -= ddy; | |
225 | break; | |
226 | } | |
6693db17 SW |
227 | if (sym) |
228 | Tmp_at(bchx, bchy); | |
984263bc | 229 | } |
6693db17 SW |
230 | if (sym) |
231 | Tmp_at(-1, -1); | |
232 | return (mtmp); | |
984263bc MD |
233 | } |
234 | ||
984263bc | 235 | static void |
6693db17 | 236 | use_whistle(struct obj *obj __unused) |
c7106d58 | 237 | { |
6693db17 SW |
238 | struct monst *mtmp = fmon; |
239 | ||
984263bc | 240 | pline("You produce a high whistling sound."); |
6693db17 SW |
241 | while (mtmp) { |
242 | if (dist(mtmp->mx, mtmp->my) < u.ulevel * 20) { | |
243 | if (mtmp->msleep) | |
984263bc | 244 | mtmp->msleep = 0; |
6693db17 | 245 | if (mtmp->mtame) |
984263bc MD |
246 | EDOG(mtmp)->whistletime = moves; |
247 | } | |
248 | mtmp = mtmp->nmon; | |
249 | } | |
250 | } | |
251 | ||
984263bc | 252 | static void |
6693db17 | 253 | use_magic_whistle(struct obj *obj __unused) |
c7106d58 | 254 | { |
6693db17 SW |
255 | struct monst *mtmp = fmon; |
256 | ||
984263bc | 257 | pline("You produce a strange whistling sound."); |
6693db17 SW |
258 | while (mtmp) { |
259 | if (mtmp->mtame) | |
260 | mnexto(mtmp); | |
984263bc MD |
261 | mtmp = mtmp->nmon; |
262 | } | |
263 | } | |
264 | ||
265 | static int dig_effort; /* effort expended on current pos */ | |
266 | static uchar dig_level; | |
267 | static coord dig_pos; | |
268 | static boolean dig_down; | |
269 | ||
6693db17 SW |
270 | static |
271 | bool | |
c7106d58 PA |
272 | dig(void) |
273 | { | |
984263bc MD |
274 | struct rm *lev; |
275 | int dpx = dig_pos.x, dpy = dig_pos.y; | |
276 | ||
277 | /* perhaps a nymph stole his pick-axe while he was busy digging */ | |
278 | /* or perhaps he teleported away */ | |
6693db17 | 279 | if (u.uswallow || !uwep || uwep->otyp != PICK_AXE || |
984263bc MD |
280 | dig_level != dlevel || |
281 | ((dig_down && (dpx != u.ux || dpy != u.uy)) || | |
6693db17 SW |
282 | (!dig_down && dist(dpx, dpy) > 2))) |
283 | return (0); | |
984263bc MD |
284 | |
285 | dig_effort += 10 + abon() + uwep->spe + rn2(5); | |
6693db17 SW |
286 | if (dig_down) { |
287 | if (!xdnstair) { | |
984263bc | 288 | pline("The floor here seems too hard to dig in."); |
6693db17 | 289 | return (0); |
984263bc | 290 | } |
6693db17 | 291 | if (dig_effort > 250) { |
984263bc | 292 | dighole(); |
6693db17 | 293 | return (0); /* done with digging */ |
984263bc | 294 | } |
6693db17 SW |
295 | if (dig_effort > 50) { |
296 | struct trap *ttmp = t_at(dpx, dpy); | |
984263bc | 297 | |
6693db17 SW |
298 | if (!ttmp) { |
299 | ttmp = maketrap(dpx, dpy, PIT); | |
984263bc MD |
300 | ttmp->tseen = 1; |
301 | pline("You have dug a pit."); | |
6693db17 | 302 | u.utrap = rn1(4, 2); |
984263bc | 303 | u.utraptype = TT_PIT; |
6693db17 | 304 | return (0); |
984263bc MD |
305 | } |
306 | } | |
6693db17 | 307 | } else if (dig_effort > 100) { |
fd2d026f | 308 | const char *digtxt; |
984263bc MD |
309 | struct obj *obj; |
310 | ||
311 | lev = &levl[dpx][dpy]; | |
6693db17 | 312 | if ((obj = sobj_at(ENORMOUS_ROCK, dpx, dpy)) != NULL) { |
984263bc MD |
313 | fracture_rock(obj); |
314 | digtxt = "The rock falls apart."; | |
6693db17 | 315 | } else if (!lev->typ || lev->typ == SCORR) { |
984263bc MD |
316 | lev->typ = CORR; |
317 | digtxt = "You succeeded in cutting away some rock."; | |
6693db17 SW |
318 | } else if (lev->typ == HWALL || lev->typ == VWALL |
319 | || lev->typ == SDOOR) { | |
984263bc MD |
320 | lev->typ = xdnstair ? DOOR : ROOM; |
321 | digtxt = "You just made an opening in the wall."; | |
322 | } else | |
6693db17 | 323 | digtxt = "Now what exactly was it that you were digging in?"; |
984263bc MD |
324 | mnewsym(dpx, dpy); |
325 | prl(dpx, dpy); | |
6693db17 SW |
326 | pline("%s", digtxt); /* after mnewsym & prl */ |
327 | return (0); | |
984263bc | 328 | } else { |
6693db17 SW |
329 | if (IS_WALL(levl[dpx][dpy].typ)) { |
330 | int rno = inroom(dpx, dpy); | |
984263bc | 331 | |
6693db17 SW |
332 | if (rno >= 0 && rooms[rno].rtype >= 8) { |
333 | pline("This wall seems too hard to dig into."); | |
334 | return (0); | |
984263bc MD |
335 | } |
336 | } | |
337 | pline("You hit the rock with all your might."); | |
338 | } | |
6693db17 | 339 | return (1); |
984263bc MD |
340 | } |
341 | ||
342 | /* When will hole be finished? Very rough indication used by shopkeeper. */ | |
c7106d58 PA |
343 | int |
344 | holetime(void) | |
345 | { | |
6693db17 | 346 | return ((occupation == dig) ? (250 - dig_effort) / 20 : -1); |
984263bc MD |
347 | } |
348 | ||
c7106d58 PA |
349 | void |
350 | dighole(void) | |
984263bc MD |
351 | { |
352 | struct trap *ttmp = t_at(u.ux, u.uy); | |
353 | ||
6693db17 | 354 | if (!xdnstair) { |
984263bc MD |
355 | pline("The floor here seems too hard to dig in."); |
356 | } else { | |
6693db17 | 357 | if (ttmp) |
984263bc MD |
358 | ttmp->ttyp = TRAPDOOR; |
359 | else | |
360 | ttmp = maketrap(u.ux, u.uy, TRAPDOOR); | |
361 | ttmp->tseen = 1; | |
362 | pline("You've made a hole in the floor."); | |
6693db17 SW |
363 | if (!u.ustuck) { |
364 | if (inshop()) | |
984263bc MD |
365 | shopdig(1); |
366 | pline("You fall through ..."); | |
6693db17 | 367 | if (u.utraptype == TT_PIT) { |
984263bc MD |
368 | u.utrap = 0; |
369 | u.utraptype = 0; | |
370 | } | |
6693db17 | 371 | goto_level(dlevel + 1, FALSE); |
984263bc MD |
372 | } |
373 | } | |
374 | } | |
375 | ||
c7106d58 PA |
376 | static int |
377 | use_pick_axe(struct obj *obj) | |
984263bc MD |
378 | { |
379 | char dirsyms[12]; | |
984263bc MD |
380 | char *dsp = dirsyms, *sdp = sdir; |
381 | struct monst *mtmp; | |
382 | struct rm *lev; | |
383 | int rx, ry, res = 0; | |
384 | ||
6693db17 SW |
385 | if (obj != uwep) { |
386 | if (uwep && uwep->cursed) { | |
984263bc MD |
387 | /* Andreas Bormann - ihnp4!decvax!mcvax!unido!ab */ |
388 | pline("Since your weapon is welded to your hand,"); | |
389 | pline("you cannot use that pick-axe."); | |
6693db17 | 390 | return (0); |
984263bc MD |
391 | } |
392 | pline("You now wield %s.", doname(obj)); | |
393 | setuwep(obj); | |
394 | res = 1; | |
395 | } | |
6693db17 | 396 | while (*sdp) { |
c7106d58 | 397 | movecmd(*sdp); /* sets u.dx and u.dy and u.dz */ |
984263bc MD |
398 | rx = u.ux + u.dx; |
399 | ry = u.uy + u.dy; | |
6693db17 | 400 | if (u.dz > 0 || (u.dz == 0 && isok(rx, ry) && |
984263bc MD |
401 | (IS_ROCK(levl[rx][ry].typ) |
402 | || sobj_at(ENORMOUS_ROCK, rx, ry)))) | |
403 | *dsp++ = *sdp; | |
404 | sdp++; | |
405 | } | |
406 | *dsp = 0; | |
407 | pline("In what direction do you want to dig? [%s] ", dirsyms); | |
6693db17 SW |
408 | if (!getdir(0)) /* no txt */ |
409 | return (res); | |
410 | if (u.uswallow && attack(u.ustuck)) /* return(1) */ | |
411 | ; | |
412 | else if (u.dz < 0) | |
984263bc | 413 | pline("You cannot reach the ceiling."); |
6693db17 SW |
414 | else if (u.dz == 0) { |
415 | if (Confusion) | |
984263bc MD |
416 | confdir(); |
417 | rx = u.ux + u.dx; | |
418 | ry = u.uy + u.dy; | |
6693db17 SW |
419 | if ((mtmp = m_at(rx, ry)) && attack(mtmp)) |
420 | return (1); | |
421 | if (!isok(rx, ry)) { | |
984263bc | 422 | pline("Clash!"); |
6693db17 | 423 | return (1); |
984263bc MD |
424 | } |
425 | lev = &levl[rx][ry]; | |
6693db17 | 426 | if (lev->typ == DOOR) |
984263bc | 427 | pline("Your %s against the door.", |
6693db17 SW |
428 | aobjnam(obj, "clang")); |
429 | else if (!IS_ROCK(lev->typ) | |
430 | && !sobj_at(ENORMOUS_ROCK, rx, ry)) { | |
984263bc MD |
431 | /* ACCESSIBLE or POOL */ |
432 | pline("You swing your %s through thin air.", | |
6693db17 | 433 | aobjnam(obj, NULL)); |
984263bc | 434 | } else { |
6693db17 | 435 | if (dig_pos.x != rx || dig_pos.y != ry |
984263bc MD |
436 | || dig_level != dlevel || dig_down) { |
437 | dig_down = FALSE; | |
438 | dig_pos.x = rx; | |
439 | dig_pos.y = ry; | |
440 | dig_level = dlevel; | |
441 | dig_effort = 0; | |
442 | pline("You start digging."); | |
443 | } else | |
444 | pline("You continue digging."); | |
445 | occupation = dig; | |
446 | occtxt = "digging"; | |
447 | } | |
6693db17 | 448 | } else if (Levitation) { |
984263bc MD |
449 | pline("You cannot reach the floor."); |
450 | } else { | |
6693db17 | 451 | if (dig_pos.x != u.ux || dig_pos.y != u.uy |
984263bc MD |
452 | || dig_level != dlevel || !dig_down) { |
453 | dig_down = TRUE; | |
454 | dig_pos.x = u.ux; | |
455 | dig_pos.y = u.uy; | |
456 | dig_level = dlevel; | |
457 | dig_effort = 0; | |
458 | pline("You start digging in the floor."); | |
6693db17 | 459 | if (inshop()) |
984263bc MD |
460 | shopdig(0); |
461 | } else | |
462 | pline("You continue digging in the floor."); | |
463 | occupation = dig; | |
464 | occtxt = "digging"; | |
465 | } | |
6693db17 | 466 | return (1); |
984263bc | 467 | } |