]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - hack/hack.do.c
Don't use <sys/cdefs.h> __COPYRIGHT/__RCSID macros for host programs -
[bsdgames-darwin.git] / hack / hack.do.c
1 /* $NetBSD: hack.do.c,v 1.4 1997/10/19 16:57:41 christos Exp $ */
2
3 /*
4 * Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985.
5 */
6
7 #include <sys/cdefs.h>
8 #ifndef lint
9 __RCSID("$NetBSD: hack.do.c,v 1.4 1997/10/19 16:57:41 christos Exp $");
10 #endif /* not lint */
11
12 /* Contains code for 'd', 'D' (drop), '>', '<' (up, down) and 't' (throw) */
13
14 #include "hack.h"
15 #include "extern.h"
16 #include <fcntl.h>
17 #include <unistd.h>
18 #include <stdlib.h>
19
20
21 static int drop __P((struct obj *));
22
23 int
24 dodrop()
25 {
26 return (drop(getobj("0$#", "drop")));
27 }
28
29 static int
30 drop(obj)
31 struct obj *obj;
32 {
33 if (!obj)
34 return (0);
35 if (obj->olet == '$') { /* pseudo object */
36 long amount = OGOLD(obj);
37
38 if (amount == 0)
39 pline("You didn't drop any gold pieces.");
40 else {
41 mkgold(amount, u.ux, u.uy);
42 pline("You dropped %ld gold piece%s.",
43 amount, plur(amount));
44 if (Invisible)
45 newsym(u.ux, u.uy);
46 }
47 free((char *) obj);
48 return (1);
49 }
50 if (obj->owornmask & (W_ARMOR | W_RING)) {
51 pline("You cannot drop something you are wearing.");
52 return (0);
53 }
54 if (obj == uwep) {
55 if (uwep->cursed) {
56 pline("Your weapon is welded to your hand!");
57 return (0);
58 }
59 setuwep((struct obj *) 0);
60 }
61 pline("You dropped %s.", doname(obj));
62 dropx(obj);
63 return (1);
64 }
65
66 /* Called in several places - should not produce texts */
67 void
68 dropx(obj)
69 struct obj *obj;
70 {
71 freeinv(obj);
72 dropy(obj);
73 }
74
75 void
76 dropy(obj)
77 struct obj *obj;
78 {
79 if (obj->otyp == CRYSKNIFE)
80 obj->otyp = WORM_TOOTH;
81 obj->ox = u.ux;
82 obj->oy = u.uy;
83 obj->nobj = fobj;
84 fobj = obj;
85 if (Invisible)
86 newsym(u.ux, u.uy);
87 subfrombill(obj);
88 stackobj(obj);
89 }
90
91 /* drop several things */
92 int
93 doddrop()
94 {
95 return (ggetobj("drop", drop, 0));
96 }
97
98 int
99 dodown()
100 {
101 if (u.ux != xdnstair || u.uy != ydnstair) {
102 pline("You can't go down here.");
103 return (0);
104 }
105 if (u.ustuck) {
106 pline("You are being held, and cannot go down.");
107 return (1);
108 }
109 if (Levitation) {
110 pline("You're floating high above the stairs.");
111 return (0);
112 }
113 goto_level(dlevel + 1, TRUE);
114 return (1);
115 }
116
117 int
118 doup()
119 {
120 if (u.ux != xupstair || u.uy != yupstair) {
121 pline("You can't go up here.");
122 return (0);
123 }
124 if (u.ustuck) {
125 pline("You are being held, and cannot go up.");
126 return (1);
127 }
128 if (!Levitation && inv_weight() + 5 > 0) {
129 pline("Your load is too heavy to climb the stairs.");
130 return (1);
131 }
132 goto_level(dlevel - 1, TRUE);
133 return (1);
134 }
135
136 void
137 goto_level(newlevel, at_stairs)
138 int newlevel;
139 boolean at_stairs;
140 {
141 int fd;
142 boolean up = (newlevel < dlevel);
143
144 if (newlevel <= 0)
145 done("escaped");/* in fact < 0 is impossible */
146 if (newlevel > MAXLEVEL)
147 newlevel = MAXLEVEL; /* strange ... */
148 if (newlevel == dlevel)
149 return; /* this can happen */
150
151 glo(dlevel);
152 fd = creat(lock, FMASK);
153 if (fd < 0) {
154 /*
155 * This is not quite impossible: e.g., we may have
156 * exceeded our quota. If that is the case then we
157 * cannot leave this level, and cannot save either.
158 * Another possibility is that the directory was not
159 * writable.
160 */
161 pline("A mysterious force prevents you from going %s.",
162 up ? "up" : "down");
163 return;
164 }
165 if (Punished)
166 unplacebc();
167 u.utrap = 0; /* needed in level_tele */
168 u.ustuck = 0; /* idem */
169 keepdogs();
170 seeoff(1);
171 if (u.uswallow) /* idem */
172 u.uswldtim = u.uswallow = 0;
173 flags.nscrinh = 1;
174 u.ux = FAR; /* hack */
175 (void) inshop(); /* probably was a trapdoor */
176
177 savelev(fd, dlevel);
178 (void) close(fd);
179
180 dlevel = newlevel;
181 if (maxdlevel < dlevel)
182 maxdlevel = dlevel;
183 glo(dlevel);
184
185 if (!level_exists[dlevel])
186 mklev();
187 else {
188 if ((fd = open(lock, 0)) < 0) {
189 pline("Cannot open %s .", lock);
190 pline("Probably someone removed it.");
191 done("tricked");
192 }
193 getlev(fd, hackpid, dlevel);
194 (void) close(fd);
195 }
196
197 if (at_stairs) {
198 if (up) {
199 u.ux = xdnstair;
200 u.uy = ydnstair;
201 if (!u.ux) { /* entering a maze from below? */
202 u.ux = xupstair; /* this will confuse the
203 * player! */
204 u.uy = yupstair;
205 }
206 if (Punished && !Levitation) {
207 pline("With great effort you climb the stairs.");
208 placebc(1);
209 }
210 } else {
211 u.ux = xupstair;
212 u.uy = yupstair;
213 if (inv_weight() + 5 > 0 || Punished) {
214 pline("You fall down the stairs."); /* %% */
215 losehp(rnd(3), "fall");
216 if (Punished) {
217 if (uwep != uball && rn2(3)) {
218 pline("... and are hit by the iron ball.");
219 losehp(rnd(20), "iron ball");
220 }
221 placebc(1);
222 }
223 selftouch("Falling, you");
224 }
225 }
226 {
227 struct monst *mtmp = m_at(u.ux, u.uy);
228 if (mtmp)
229 mnexto(mtmp);
230 }
231 } else { /* trapdoor or level_tele */
232 do {
233 u.ux = rnd(COLNO - 1);
234 u.uy = rn2(ROWNO);
235 } while (levl[u.ux][u.uy].typ != ROOM ||
236 m_at(u.ux, u.uy));
237 if (Punished) {
238 if (uwep != uball && !up /* %% */ && rn2(5)) {
239 pline("The iron ball falls on your head.");
240 losehp(rnd(25), "iron ball");
241 }
242 placebc(1);
243 }
244 selftouch("Falling, you");
245 }
246 (void) inshop();
247 initrack();
248
249 losedogs();
250 {
251 struct monst *mtmp;
252 if ((mtmp = m_at(u.ux, u.uy)) != NULL)
253 mnexto(mtmp); /* riv05!a3 */
254 }
255 flags.nscrinh = 0;
256 setsee();
257 seeobjs(); /* make old cadavers disappear - riv05!a3 */
258 docrt();
259 pickup(1);
260 read_engr_at(u.ux, u.uy);
261 }
262
263 int
264 donull()
265 {
266 return (1); /* Do nothing, but let other things happen */
267 }
268
269 int
270 dopray()
271 {
272 nomovemsg = "You finished your prayer.";
273 nomul(-3);
274 return (1);
275 }
276
277 int
278 dothrow()
279 {
280 struct obj *obj;
281 struct monst *mon;
282 int tmp;
283
284 obj = getobj("#)", "throw"); /* it is also possible to throw food */
285 /* (or jewels, or iron balls ... ) */
286 if (!obj || !getdir(1)) /* ask "in what direction?" */
287 return (0);
288 if (obj->owornmask & (W_ARMOR | W_RING)) {
289 pline("You can't throw something you are wearing.");
290 return (0);
291 }
292 u_wipe_engr(2);
293
294 if (obj == uwep) {
295 if (obj->cursed) {
296 pline("Your weapon is welded to your hand.");
297 return (1);
298 }
299 if (obj->quan > 1)
300 setuwep(splitobj(obj, 1));
301 else
302 setuwep((struct obj *) 0);
303 } else if (obj->quan > 1)
304 (void) splitobj(obj, 1);
305 freeinv(obj);
306 if (u.uswallow) {
307 mon = u.ustuck;
308 bhitpos.x = mon->mx;
309 bhitpos.y = mon->my;
310 } else if (u.dz) {
311 if (u.dz < 0) {
312 pline("%s hits the ceiling, then falls back on top of your head.",
313 Doname(obj)); /* note: obj->quan == 1 */
314 if (obj->olet == POTION_SYM)
315 potionhit(&youmonst, obj);
316 else {
317 if (uarmh)
318 pline("Fortunately, you are wearing a helmet!");
319 losehp(uarmh ? 1 : rnd((int) (obj->owt)), "falling object");
320 dropy(obj);
321 }
322 } else {
323 pline("%s hits the floor.", Doname(obj));
324 if (obj->otyp == EXPENSIVE_CAMERA) {
325 pline("It is shattered in a thousand pieces!");
326 obfree(obj, Null(obj));
327 } else if (obj->otyp == EGG) {
328 pline("\"Splash!\"");
329 obfree(obj, Null(obj));
330 } else if (obj->olet == POTION_SYM) {
331 pline("The flask breaks, and you smell a peculiar odor ...");
332 potionbreathe(obj);
333 obfree(obj, Null(obj));
334 } else {
335 dropy(obj);
336 }
337 }
338 return (1);
339 } else if (obj->otyp == BOOMERANG) {
340 mon = boomhit(u.dx, u.dy);
341 if (mon == &youmonst) { /* the thing was caught */
342 (void) addinv(obj);
343 return (1);
344 }
345 } else {
346 if (obj->otyp == PICK_AXE && shkcatch(obj))
347 return (1);
348
349 mon = bhit(u.dx, u.dy, (obj->otyp == ICE_BOX) ? 1 :
350 (!Punished || obj != uball) ? 8 : !u.ustuck ? 5 : 1,
351 obj->olet,
352 (void (*) __P((struct monst *, struct obj *))) 0,
353 (int (*) __P((struct obj *, struct obj *))) 0, obj);
354 }
355 if (mon) {
356 /* awake monster if sleeping */
357 wakeup(mon);
358
359 if (obj->olet == WEAPON_SYM) {
360 tmp = -1 + u.ulevel + mon->data->ac + abon();
361 if (obj->otyp < ROCK) {
362 if (!uwep ||
363 uwep->otyp != obj->otyp + (BOW - ARROW))
364 tmp -= 4;
365 else {
366 tmp += uwep->spe;
367 }
368 } else if (obj->otyp == BOOMERANG)
369 tmp += 4;
370 tmp += obj->spe;
371 if (u.uswallow || tmp >= rnd(20)) {
372 if (hmon(mon, obj, 1) == TRUE) {
373 /* mon still alive */
374 #ifndef NOWORM
375 cutworm(mon, bhitpos.x, bhitpos.y, obj->otyp);
376 #endif /* NOWORM */
377 } else
378 mon = 0;
379 /* weapons thrown disappear sometimes */
380 if (obj->otyp < BOOMERANG && rn2(3)) {
381 /* check bill; free */
382 obfree(obj, (struct obj *) 0);
383 return (1);
384 }
385 } else
386 miss(objects[obj->otyp].oc_name, mon);
387 } else if (obj->otyp == HEAVY_IRON_BALL) {
388 tmp = -1 + u.ulevel + mon->data->ac + abon();
389 if (!Punished || obj != uball)
390 tmp += 2;
391 if (u.utrap)
392 tmp -= 2;
393 if (u.uswallow || tmp >= rnd(20)) {
394 if (hmon(mon, obj, 1) == FALSE)
395 mon = 0; /* he died */
396 } else
397 miss("iron ball", mon);
398 } else if (obj->olet == POTION_SYM && u.ulevel > rn2(15)) {
399 potionhit(mon, obj);
400 return (1);
401 } else {
402 if (cansee(bhitpos.x, bhitpos.y))
403 pline("You miss %s.", monnam(mon));
404 else
405 pline("You miss it.");
406 if (obj->olet == FOOD_SYM && mon->data->mlet == 'd')
407 if (tamedog(mon, obj))
408 return (1);
409 if (obj->olet == GEM_SYM && mon->data->mlet == 'u' &&
410 !mon->mtame) {
411 if (obj->dknown && objects[obj->otyp].oc_name_known) {
412 if (objects[obj->otyp].g_val > 0) {
413 u.uluck += 5;
414 goto valuable;
415 } else {
416 pline("%s is not interested in your junk.",
417 Monnam(mon));
418 }
419 } else { /* value unknown to @ */
420 u.uluck++;
421 valuable:
422 if (u.uluck > LUCKMAX) /* dan@ut-ngp */
423 u.uluck = LUCKMAX;
424 pline("%s graciously accepts your gift.",
425 Monnam(mon));
426 mpickobj(mon, obj);
427 rloc(mon);
428 return (1);
429 }
430 }
431 }
432 }
433 /* the code following might become part of dropy() */
434 if (obj->otyp == CRYSKNIFE)
435 obj->otyp = WORM_TOOTH;
436 obj->ox = bhitpos.x;
437 obj->oy = bhitpos.y;
438 obj->nobj = fobj;
439 fobj = obj;
440 /* prevent him from throwing articles to the exit and escaping */
441 /* subfrombill(obj); */
442 stackobj(obj);
443 if (Punished && obj == uball &&
444 (bhitpos.x != u.ux || bhitpos.y != u.uy)) {
445 freeobj(uchain);
446 unpobj(uchain);
447 if (u.utrap) {
448 if (u.utraptype == TT_PIT)
449 pline("The ball pulls you out of the pit!");
450 else {
451 long side =
452 rn2(3) ? LEFT_SIDE : RIGHT_SIDE;
453 pline("The ball pulls you out of the bear trap.");
454 pline("Your %s leg is severely damaged.",
455 (side == LEFT_SIDE) ? "left" : "right");
456 set_wounded_legs(side, 500 + rn2(1000));
457 losehp(2, "thrown ball");
458 }
459 u.utrap = 0;
460 }
461 unsee();
462 uchain->nobj = fobj;
463 fobj = uchain;
464 u.ux = uchain->ox = bhitpos.x - u.dx;
465 u.uy = uchain->oy = bhitpos.y - u.dy;
466 setsee();
467 (void) inshop();
468 }
469 if (cansee(bhitpos.x, bhitpos.y))
470 prl(bhitpos.x, bhitpos.y);
471 return (1);
472 }
473
474 /* split obj so that it gets size num */
475 /* remainder is put in the object structure delivered by this call */
476 struct obj *
477 splitobj(obj, num)
478 struct obj *obj;
479 int num;
480 {
481 struct obj *otmp;
482 otmp = newobj(0);
483 *otmp = *obj; /* copies whole structure */
484 otmp->o_id = flags.ident++;
485 otmp->onamelth = 0;
486 obj->quan = num;
487 obj->owt = weight(obj);
488 otmp->quan -= num;
489 otmp->owt = weight(otmp); /* -= obj->owt ? */
490 obj->nobj = otmp;
491 if (obj->unpaid)
492 splitbill(obj, otmp);
493 return (otmp);
494 }
495
496 void
497 more_experienced(exp, rexp)
498 int exp, rexp;
499 {
500 u.uexp += exp;
501 u.urexp += 4 * exp + rexp;
502 if (exp)
503 flags.botl = 1;
504 if (u.urexp >= ((pl_character[0] == 'W') ? 1000 : 2000))
505 flags.beginner = 0;
506 }
507
508 void
509 set_wounded_legs(side, timex)
510 long side;
511 int timex;
512 {
513 if (!Wounded_legs || (Wounded_legs & TIMEOUT))
514 Wounded_legs |= side + timex;
515 else
516 Wounded_legs |= side;
517 }
518
519 void
520 heal_legs()
521 {
522 if (Wounded_legs) {
523 if ((Wounded_legs & BOTH_SIDES) == BOTH_SIDES)
524 pline("Your legs feel somewhat better.");
525 else
526 pline("Your leg feels somewhat better.");
527 Wounded_legs = 0;
528 }
529 }