123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587 |
- /* $NetBSD: hack.do.c,v 1.7 2004/01/27 20:30:29 jsm Exp $ */
- /*
- * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
- * Amsterdam
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Stichting Centrum voor Wiskunde en
- * Informatica, nor the names of its contributors may be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- /*
- * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include <sys/cdefs.h>
- #ifndef lint
- __RCSID("$NetBSD: hack.do.c,v 1.7 2004/01/27 20:30:29 jsm Exp $");
- #endif /* not lint */
- /* Contains code for 'd', 'D' (drop), '>', '<' (up, down) and 't' (throw) */
- #include "hack.h"
- #include "extern.h"
- #include <fcntl.h>
- #include <unistd.h>
- #include <stdlib.h>
- static int drop(struct obj *);
- int
- dodrop()
- {
- return (drop(getobj("0$#", "drop")));
- }
- static int
- drop(obj)
- struct obj *obj;
- {
- if (!obj)
- return (0);
- if (obj->olet == '$') { /* pseudo object */
- long amount = OGOLD(obj);
- if (amount == 0)
- pline("You didn't drop any gold pieces.");
- else {
- mkgold(amount, u.ux, u.uy);
- pline("You dropped %ld gold piece%s.",
- amount, plur(amount));
- if (Invisible)
- newsym(u.ux, u.uy);
- }
- free((char *) obj);
- return (1);
- }
- if (obj->owornmask & (W_ARMOR | W_RING)) {
- pline("You cannot drop something you are wearing.");
- return (0);
- }
- if (obj == uwep) {
- if (uwep->cursed) {
- pline("Your weapon is welded to your hand!");
- return (0);
- }
- setuwep((struct obj *) 0);
- }
- pline("You dropped %s.", doname(obj));
- dropx(obj);
- return (1);
- }
- /* Called in several places - should not produce texts */
- void
- dropx(obj)
- struct obj *obj;
- {
- freeinv(obj);
- dropy(obj);
- }
- void
- dropy(obj)
- struct obj *obj;
- {
- if (obj->otyp == CRYSKNIFE)
- obj->otyp = WORM_TOOTH;
- obj->ox = u.ux;
- obj->oy = u.uy;
- obj->nobj = fobj;
- fobj = obj;
- if (Invisible)
- newsym(u.ux, u.uy);
- subfrombill(obj);
- stackobj(obj);
- }
- /* drop several things */
- int
- doddrop()
- {
- return (ggetobj("drop", drop, 0));
- }
- int
- dodown()
- {
- if (u.ux != xdnstair || u.uy != ydnstair) {
- pline("You can't go down here.");
- return (0);
- }
- if (u.ustuck) {
- pline("You are being held, and cannot go down.");
- return (1);
- }
- if (Levitation) {
- pline("You're floating high above the stairs.");
- return (0);
- }
- goto_level(dlevel + 1, TRUE);
- return (1);
- }
- int
- doup()
- {
- if (u.ux != xupstair || u.uy != yupstair) {
- pline("You can't go up here.");
- return (0);
- }
- if (u.ustuck) {
- pline("You are being held, and cannot go up.");
- return (1);
- }
- if (!Levitation && inv_weight() + 5 > 0) {
- pline("Your load is too heavy to climb the stairs.");
- return (1);
- }
- goto_level(dlevel - 1, TRUE);
- return (1);
- }
- void
- goto_level(newlevel, at_stairs)
- int newlevel;
- boolean at_stairs;
- {
- int fd;
- boolean up = (newlevel < dlevel);
- if (newlevel <= 0)
- done("escaped");/* in fact < 0 is impossible */
- if (newlevel > MAXLEVEL)
- newlevel = MAXLEVEL; /* strange ... */
- if (newlevel == dlevel)
- return; /* this can happen */
- glo(dlevel);
- fd = creat(lock, FMASK);
- if (fd < 0) {
- /*
- * This is not quite impossible: e.g., we may have
- * exceeded our quota. If that is the case then we
- * cannot leave this level, and cannot save either.
- * Another possibility is that the directory was not
- * writable.
- */
- pline("A mysterious force prevents you from going %s.",
- up ? "up" : "down");
- return;
- }
- if (Punished)
- unplacebc();
- u.utrap = 0; /* needed in level_tele */
- u.ustuck = 0; /* idem */
- keepdogs();
- seeoff(1);
- if (u.uswallow) /* idem */
- u.uswldtim = u.uswallow = 0;
- flags.nscrinh = 1;
- u.ux = FAR; /* hack */
- (void) inshop(); /* probably was a trapdoor */
- savelev(fd, dlevel);
- (void) close(fd);
- dlevel = newlevel;
- if (maxdlevel < dlevel)
- maxdlevel = dlevel;
- glo(dlevel);
- if (!level_exists[dlevel])
- mklev();
- else {
- if ((fd = open(lock, O_RDONLY)) < 0) {
- pline("Cannot open %s .", lock);
- pline("Probably someone removed it.");
- done("tricked");
- }
- getlev(fd, hackpid, dlevel);
- (void) close(fd);
- }
- if (at_stairs) {
- if (up) {
- u.ux = xdnstair;
- u.uy = ydnstair;
- if (!u.ux) { /* entering a maze from below? */
- u.ux = xupstair; /* this will confuse the
- * player! */
- u.uy = yupstair;
- }
- if (Punished && !Levitation) {
- pline("With great effort you climb the stairs.");
- placebc(1);
- }
- } else {
- u.ux = xupstair;
- u.uy = yupstair;
- if (inv_weight() + 5 > 0 || Punished) {
- pline("You fall down the stairs."); /* %% */
- losehp(rnd(3), "fall");
- if (Punished) {
- if (uwep != uball && rn2(3)) {
- pline("... and are hit by the iron ball.");
- losehp(rnd(20), "iron ball");
- }
- placebc(1);
- }
- selftouch("Falling, you");
- }
- }
- {
- struct monst *mtmp = m_at(u.ux, u.uy);
- if (mtmp)
- mnexto(mtmp);
- }
- } else { /* trapdoor or level_tele */
- do {
- u.ux = rnd(COLNO - 1);
- u.uy = rn2(ROWNO);
- } while (levl[u.ux][u.uy].typ != ROOM ||
- m_at(u.ux, u.uy));
- if (Punished) {
- if (uwep != uball && !up /* %% */ && rn2(5)) {
- pline("The iron ball falls on your head.");
- losehp(rnd(25), "iron ball");
- }
- placebc(1);
- }
- selftouch("Falling, you");
- }
- (void) inshop();
- initrack();
- losedogs();
- {
- struct monst *mtmp;
- if ((mtmp = m_at(u.ux, u.uy)) != NULL)
- mnexto(mtmp); /* riv05!a3 */
- }
- flags.nscrinh = 0;
- setsee();
- seeobjs(); /* make old cadavers disappear - riv05!a3 */
- docrt();
- pickup(1);
- read_engr_at(u.ux, u.uy);
- }
- int
- donull()
- {
- return (1); /* Do nothing, but let other things happen */
- }
- int
- dopray()
- {
- nomovemsg = "You finished your prayer.";
- nomul(-3);
- return (1);
- }
- int
- dothrow()
- {
- struct obj *obj;
- struct monst *mon;
- int tmp;
- obj = getobj("#)", "throw"); /* it is also possible to throw food */
- /* (or jewels, or iron balls ... ) */
- if (!obj || !getdir(1)) /* ask "in what direction?" */
- return (0);
- if (obj->owornmask & (W_ARMOR | W_RING)) {
- pline("You can't throw something you are wearing.");
- return (0);
- }
- u_wipe_engr(2);
- if (obj == uwep) {
- if (obj->cursed) {
- pline("Your weapon is welded to your hand.");
- return (1);
- }
- if (obj->quan > 1)
- setuwep(splitobj(obj, 1));
- else
- setuwep((struct obj *) 0);
- } else if (obj->quan > 1)
- (void) splitobj(obj, 1);
- freeinv(obj);
- if (u.uswallow) {
- mon = u.ustuck;
- bhitpos.x = mon->mx;
- bhitpos.y = mon->my;
- } else if (u.dz) {
- if (u.dz < 0) {
- pline("%s hits the ceiling, then falls back on top of your head.",
- Doname(obj)); /* note: obj->quan == 1 */
- if (obj->olet == POTION_SYM)
- potionhit(&youmonst, obj);
- else {
- if (uarmh)
- pline("Fortunately, you are wearing a helmet!");
- losehp(uarmh ? 1 : rnd((int) (obj->owt)), "falling object");
- dropy(obj);
- }
- } else {
- pline("%s hits the floor.", Doname(obj));
- if (obj->otyp == EXPENSIVE_CAMERA) {
- pline("It is shattered in a thousand pieces!");
- obfree(obj, Null(obj));
- } else if (obj->otyp == EGG) {
- pline("\"Splash!\"");
- obfree(obj, Null(obj));
- } else if (obj->olet == POTION_SYM) {
- pline("The flask breaks, and you smell a peculiar odor ...");
- potionbreathe(obj);
- obfree(obj, Null(obj));
- } else {
- dropy(obj);
- }
- }
- return (1);
- } else if (obj->otyp == BOOMERANG) {
- mon = boomhit(u.dx, u.dy);
- if (mon == &youmonst) { /* the thing was caught */
- (void) addinv(obj);
- return (1);
- }
- } else {
- if (obj->otyp == PICK_AXE && shkcatch(obj))
- return (1);
- mon = bhit(u.dx, u.dy, (obj->otyp == ICE_BOX) ? 1 :
- (!Punished || obj != uball) ? 8 : !u.ustuck ? 5 : 1,
- obj->olet,
- (void (*)(struct monst *, struct obj *)) 0,
- (int (*)(struct obj *, struct obj *)) 0, obj);
- }
- if (mon) {
- /* awake monster if sleeping */
- wakeup(mon);
- if (obj->olet == WEAPON_SYM) {
- tmp = -1 + u.ulevel + mon->data->ac + abon();
- if (obj->otyp < ROCK) {
- if (!uwep ||
- uwep->otyp != obj->otyp + (BOW - ARROW))
- tmp -= 4;
- else {
- tmp += uwep->spe;
- }
- } else if (obj->otyp == BOOMERANG)
- tmp += 4;
- tmp += obj->spe;
- if (u.uswallow || tmp >= rnd(20)) {
- if (hmon(mon, obj, 1) == TRUE) {
- /* mon still alive */
- #ifndef NOWORM
- cutworm(mon, bhitpos.x, bhitpos.y, obj->otyp);
- #endif /* NOWORM */
- } else
- mon = 0;
- /* weapons thrown disappear sometimes */
- if (obj->otyp < BOOMERANG && rn2(3)) {
- /* check bill; free */
- obfree(obj, (struct obj *) 0);
- return (1);
- }
- } else
- miss(objects[obj->otyp].oc_name, mon);
- } else if (obj->otyp == HEAVY_IRON_BALL) {
- tmp = -1 + u.ulevel + mon->data->ac + abon();
- if (!Punished || obj != uball)
- tmp += 2;
- if (u.utrap)
- tmp -= 2;
- if (u.uswallow || tmp >= rnd(20)) {
- if (hmon(mon, obj, 1) == FALSE)
- mon = 0; /* he died */
- } else
- miss("iron ball", mon);
- } else if (obj->olet == POTION_SYM && u.ulevel > rn2(15)) {
- potionhit(mon, obj);
- return (1);
- } else {
- if (cansee(bhitpos.x, bhitpos.y))
- pline("You miss %s.", monnam(mon));
- else
- pline("You miss it.");
- if (obj->olet == FOOD_SYM && mon->data->mlet == 'd')
- if (tamedog(mon, obj))
- return (1);
- if (obj->olet == GEM_SYM && mon->data->mlet == 'u' &&
- !mon->mtame) {
- if (obj->dknown && objects[obj->otyp].oc_name_known) {
- if (objects[obj->otyp].g_val > 0) {
- u.uluck += 5;
- goto valuable;
- } else {
- pline("%s is not interested in your junk.",
- Monnam(mon));
- }
- } else { /* value unknown to @ */
- u.uluck++;
- valuable:
- if (u.uluck > LUCKMAX) /* dan@ut-ngp */
- u.uluck = LUCKMAX;
- pline("%s graciously accepts your gift.",
- Monnam(mon));
- mpickobj(mon, obj);
- rloc(mon);
- return (1);
- }
- }
- }
- }
- /* the code following might become part of dropy() */
- if (obj->otyp == CRYSKNIFE)
- obj->otyp = WORM_TOOTH;
- obj->ox = bhitpos.x;
- obj->oy = bhitpos.y;
- obj->nobj = fobj;
- fobj = obj;
- /* prevent him from throwing articles to the exit and escaping */
- /* subfrombill(obj); */
- stackobj(obj);
- if (Punished && obj == uball &&
- (bhitpos.x != u.ux || bhitpos.y != u.uy)) {
- freeobj(uchain);
- unpobj(uchain);
- if (u.utrap) {
- if (u.utraptype == TT_PIT)
- pline("The ball pulls you out of the pit!");
- else {
- long side =
- rn2(3) ? LEFT_SIDE : RIGHT_SIDE;
- pline("The ball pulls you out of the bear trap.");
- pline("Your %s leg is severely damaged.",
- (side == LEFT_SIDE) ? "left" : "right");
- set_wounded_legs(side, 500 + rn2(1000));
- losehp(2, "thrown ball");
- }
- u.utrap = 0;
- }
- unsee();
- uchain->nobj = fobj;
- fobj = uchain;
- u.ux = uchain->ox = bhitpos.x - u.dx;
- u.uy = uchain->oy = bhitpos.y - u.dy;
- setsee();
- (void) inshop();
- }
- if (cansee(bhitpos.x, bhitpos.y))
- prl(bhitpos.x, bhitpos.y);
- return (1);
- }
- /* split obj so that it gets size num */
- /* remainder is put in the object structure delivered by this call */
- struct obj *
- splitobj(obj, num)
- struct obj *obj;
- int num;
- {
- struct obj *otmp;
- otmp = newobj(0);
- *otmp = *obj; /* copies whole structure */
- otmp->o_id = flags.ident++;
- otmp->onamelth = 0;
- obj->quan = num;
- obj->owt = weight(obj);
- otmp->quan -= num;
- otmp->owt = weight(otmp); /* -= obj->owt ? */
- obj->nobj = otmp;
- if (obj->unpaid)
- splitbill(obj, otmp);
- return (otmp);
- }
- void
- more_experienced(exp, rexp)
- int exp, rexp;
- {
- u.uexp += exp;
- u.urexp += 4 * exp + rexp;
- if (exp)
- flags.botl = 1;
- if (u.urexp >= ((pl_character[0] == 'W') ? 1000 : 2000))
- flags.beginner = 0;
- }
- void
- set_wounded_legs(side, timex)
- long side;
- int timex;
- {
- if (!Wounded_legs || (Wounded_legs & TIMEOUT))
- Wounded_legs |= side + timex;
- else
- Wounded_legs |= side;
- }
- void
- heal_legs()
- {
- if (Wounded_legs) {
- if ((Wounded_legs & BOTH_SIDES) == BOTH_SIDES)
- pline("Your legs feel somewhat better.");
- else
- pline("Your leg feels somewhat better.");
- Wounded_legs = 0;
- }
- }
|