#include #include #include #include #include "attack.h" #include "defs.h" #include "flag.h" #include "io.h" #include "lf.h" #include "map.h" #include "move.h" #include "nexus.h" #include "objects.h" #include "text.h" extern lifeform_t *player; extern int statdirty; extern int needredraw; extern int gamestarted; extern enum ERROR reason; extern void *rdata; int canandwillmove(lifeform_t *lf, int dir, enum ERROR *error) { if (isplayer(lf)) { if (canmove(lf, dir, error)) { return B_TRUE; } } else { if (canmove(lf, dir, error) && willmove(lf, dir, error)) { return B_TRUE; } } return B_FALSE; } int canmove(lifeform_t *lf, int dir, enum ERROR *error) { cell_t *cell; flag_t *f; // default if (error) { *error = E_OK; rdata = NULL; } if (lfhasflag(lf, F_GRAVBOOSTED)) { if (error) *error = E_GRAVBOOSTED; return B_FALSE; } if (isburdened(lf) >= BR_OVERLOADED) { if (error) *error = E_TOOHEAVY; return B_FALSE; } // check if we are paralyzed, frozen, etc if (isimmobile(lf)) { if (error) *error = E_CANTMOVE; return B_FALSE; } cell = getcellindir(lf->cell, dir); f = lfhasflag(lf, F_GRABBEDBY); if (f) { lifeform_t *lf2; lf2 = findlf(NULL, f->val[0]); if (lf2 && (lf2 != cell->lf)) { if (error) { rdata = lf2; *error = E_GRABBEDBY; } return B_FALSE; } } return cellwalkable(lf, cell, error); } // will populate rdata int celldangerous(lifeform_t *lf, cell_t *cell, enum ERROR *error) { enum IQBRACKET iq; // default if (error) { *error = E_OK; rdata = NULL; } // check for _known_ dangerous objects iq = getiqname(getattr(lf, A_IQ), NULL); if ((iq >= IQ_AVERAGE) && !isblind(lf)) { flag_t *f; object_t *o; for (o = cell->obpile->first ; o ; o = o->next) { // don't walk on sharp objects without boots if (hasflag(o->flags, F_SHARP)) { if (!getequippedob(lf->pack, BP_FEET)) { if (error) { *error = E_AVOIDOB; rdata = o; } return B_TRUE; } } f = hasflag(o->flags, F_WALKDAM); if (f) { // are we immune to this? if (!lfhasflagval(lf, F_DTIMMUNE, f->val[1], NA, NA, NULL)) { if (error) { *error = E_AVOIDOB; rdata = o; } return B_TRUE; } } } } return B_FALSE; } int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error) { object_t *o; // default if (error) { *error = E_OK; rdata = NULL; } if (!cell) { if (error) *error = E_WALLINWAY; return B_FALSE; } if (cell->type->solid) { if (lf && lfhasflag(lf, F_NONCORPOREAL)) { // ok } else { if (error) *error = E_WALLINWAY; return B_FALSE; } } // must check for lf before checking for impassable objects, // so that we are able to attack monsters embedded in walls. if (cell->lf && (cell->lf != lf)) { if (error) *error = E_LFINWAY; return B_FALSE; } for (o = cell->obpile->first ; o ; o = o->next) { if (isimpassableob(o, lf)) { if (lf) { if ((lf->race->material->id == MT_GAS) || (lf->race->material->id == MT_SLIME)) { // ok } else if (lfhasflag(lf, F_NONCORPOREAL)) { // ok } else { rdata = o; if (error) *error = E_OBINWAY; return B_FALSE; } } else { rdata = o; if (error) *error = E_OBINWAY; return B_FALSE; } } } return B_TRUE; } int diropposite(int dir) { switch (dir) { case D_N: return D_S; case D_E: return D_W; case D_S: return D_N; case D_W: return D_E; case DC_N: return DC_S; case DC_NE: return DC_SW; case DC_E: return DC_W; case DC_SE: return DC_NW; case DC_S: return DC_N; case DC_SW: return DC_NE; case DC_W: return DC_E; case DC_NW: return DC_SE; } // should never happen! return dir; } void dorandommove(lifeform_t *lf, int badmovesok) { int dir; int tries = 0; int moveok; enum ERROR why; // find a valid direction dir = getrandomdir(DT_COMPASS); moveok = canandwillmove(lf, dir, &why); if (!moveok && badmovesok) { switch (why) { // actually okay to move into someone case E_WALLINWAY: case E_LFINWAY: moveok = B_TRUE; break; default: break; } } while (!moveok) { // try next direction... if (++dir > DC_NW) dir = DC_N; if (++tries >= MAXDIR_COMPASS) { rest(lf, B_TRUE); return; } // check this direction... moveok = canandwillmove(lf, dir, &why); if (!moveok && badmovesok) { switch (why) { case E_WALLINWAY: case E_LFINWAY: moveok = B_TRUE; break; default: break; } } } trymove(lf, dir); } int getdiraway(cell_t *src, cell_t *dst, int wantcheck) { int d; cell_t *c; int maxdist=-1,bestdir=D_NONE; for (d = DC_N; d <= DC_NW; d++) { int thisdist = -1; int ok = B_FALSE; c = getcellindir(src, d); if (!c) continue; if (c == dst) { // destination is the thing we're fleeing from! thisdist = -1; } else { if (wantcheck) { if (src->lf && canandwillmove(src->lf, d, NULL)) { ok = B_TRUE; } else if (!src->lf) { ok = B_TRUE; } } else { if (src->lf && cellwalkable(src->lf, c, NULL)) { ok = B_TRUE; } else if (!src->lf) { ok = B_TRUE; } } if (ok) { thisdist = getcelldistorth(c, dst); } else { thisdist = -1; } if (thisdist > maxdist) { maxdist = thisdist; bestdir = d; } } } // TODO: handle ties if (bestdir != D_NONE) { reason = E_OK; } return bestdir; } int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck) { int d; cell_t *c; int mindist=9999,bestdir=D_NONE; for (d = DC_N; d <= DC_NW; d++) { int ok = B_FALSE; c = getcellindir(src, d); if (!c) continue; if (c == dst) { // destination is adjacent! bestdir = d; break; } if (wantcheck) { if (srclf && canandwillmove(srclf, d, NULL)) { ok = B_TRUE; } else if (!srclf) { ok = B_TRUE; } } else { if (srclf && cellwalkable(srclf, c, NULL)) { ok = B_TRUE; } else if (!srclf) { ok = B_TRUE; } } if (ok) { int thisdist; thisdist = getcelldistorth(c, dst); if (thisdist < mindist) { mindist = thisdist; bestdir = d; } } } // TODO: handle ties return bestdir; } int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher) { int i; char lfname[BUFLEN]; int seen; getlfname(lf,lfname); if (cansee(player, lf)) { seen = B_TRUE; } else { seen = B_FALSE; } if (dir == D_NONE) { // failed! return B_TRUE; } // if levitating (not flying), knocked back further. if (lfhasflag(lf, F_LEVITATING)) { howfar *= 2; } for (i = 0; i < howfar; i++) { if (canmove(lf, dir, &reason)) { if ((i == 0) && seen) { msg("%s %s knocked backwards!",lfname,isplayer(lf) ? "are" : "is"); } trymove(lf, dir); } if (reason != E_OK) { // failed to move switch (reason) { case E_WALLINWAY: msg("%s slam%s into a wall!",lfname,isplayer(lf) ? "" : "s"); losehp(lf, rnd(1,6), DT_BASH, pusher, "slamming into a wall"); // stop moving i = howfar; break; default: break; } } } return B_FALSE; } int moveawayfrom(lifeform_t *lf, cell_t *dst ) { int dir; int rv = B_TRUE; if (isblind(lf)) { dorandommove(lf, B_TRUE); return B_FALSE; } // move towards them dir = getdiraway(lf->cell, dst, B_TRUE); if (dir == D_NONE) { rv = B_TRUE; } else { rv = trymove(lf, dir); } return rv; } // returns TRUE if something happened int movelf(lifeform_t *lf, cell_t *newcell) { object_t *o,*nexto; char obname[BUFLEN],lfname[BUFLEN],buf[BUFLEN]; lifeform_t *l; int didmsg = B_FALSE; flag_t *f; getlfname(lf, lfname); // update current cell lf->cell->lf = NULL; // if required, relink lifeform to new map if (newcell->map != lf->cell->map) { if (isplayer(lf)) { statdirty = B_TRUE; } relinklf(lf, newcell->map); } // update lifeform lf->cell = newcell; // nothing should be in new cell.. assert(!newcell->lf); // update new cell newcell->lf = lf; if (isbleeding(lf)) { if (rnd(1,2) == 1) { bleed(lf); } } if (lfhasflag(lf, F_PAIN)) { losehp(lf, rolldie(2,4)+2, DT_DIRECT, NULL, "extreme pain"); if (isplayer(lf)) { msg("Your body is wracked with pain!"); } else if (cansee(player, lf)) { msg("%s convulses in pain!",lfname); } } // remove grabs f = lfhasflag(lf, F_GRABBING); if (f) { lifeform_t *grabee; grabee = findlf(NULL, f->val[0]); assert(grabee); killflagsofid(grabee->flags, F_GRABBEDBY); killflagsofid(lf->flags, F_GRABBING); } // check ground objects if (!isairborne(lf)) { for (o = newcell->obpile->first ; o ; o = nexto ) { nexto = o->next; f = hasflag(o->flags, F_SHARP); if (f) { object_t *boots; // has boots on? boots = getequippedob(lf->pack, BP_FEET); if (!boots) { // take damage getobname(o, obname, 1); if (lf->controller == C_PLAYER) { msg("Ow - you step on %s!",obname); didmsg = B_TRUE; } else if (haslos(player, newcell)) { msg("%s steps on %s!",lfname, obname); didmsg = B_TRUE; } sprintf(buf, "stepping on %s", obname); losehp(lf, rnd(f->val[0],f->val[1]), DT_SLASH, NULL, buf); } } f = hasflag(o->flags, F_CRUSHABLE); if (f) { enum LFSIZE crushsize; crushsize = f->val[0]; if (getlfsize(lf) >= crushsize) { // crunch it broken glass getobname(o, obname, 1); // special case if (o->type->id == OT_BROKENGLASS) { if (o->amt > 1) { char *newname; // we want 'xx steps on some pieces of broken glass' // not 'xx steps on 5 pieces of broken glass' newname = makeplural(obname); newname = strrep(newname, "a ", "some ", NULL); strcpy(obname, newname); free(newname); } } if (isplayer(lf)) { msg("You crush %s underfoot.",obname); didmsg = B_TRUE; } else if (haslos(player, newcell)) { msg("%s crushes %s.",lfname, obname); didmsg = B_TRUE; } // kill object removeob(o, o->amt); } } // end if crushable } // end foreach object in cell } // end if !flying // update where player knows // (but without a map you will then slowly forget it) if (isplayer(lf)) { updateknowncells(); } // does anyone else see you? if (gamestarted) { for (l = newcell->map->lf ; l ; l = l->next) { if (l != lf) { if (haslos(l, newcell)) { interrupt(l); if (isplayer(l)) { if (lfhasflag(l, F_RUNNING) || lfhasflag(l, F_RESTING)) { char lfname2[BUFLEN]; getlfname(lf, lfname); sprintf(lfname2, "%s",noprefix(lfname)); msg("%s %s comes into view.",isvowel(lfname2[0]) ? "An" : "A", lfname2); } } } } } } return didmsg; } // basically this is a warpper for 'movelf' which // does other game things like telling the player // what is here. int moveto(lifeform_t *lf, cell_t *newcell) { return real_moveto(lf,newcell,B_FALSE); } int real_moveto(lifeform_t *lf, cell_t *newcell, int dontclearmsg) { char lfname[BUFLEN]; int didmsg; getlfname(lf, lfname); // actually do the move didmsg = movelf(lf, newcell); if (dontclearmsg) { didmsg = B_TRUE; } // tell player about things if (!isdead(lf)) { // some lifeforms can go through things if (lf->race->material->id == MT_GAS) { object_t *o; char obname[BUFLEN]; for (o = newcell->obpile->first ; o ; o = o->next) { if (isimpassableob(o, lf)) { getobname(o, obname, o->amt); if (isplayer(lf)) { msg("You seep around %s.", obname); } else if (haslos(player, newcell)) { msg("%s seeps around %s.", lfname, obname); } } } } else if (lf->race->material->id == MT_SLIME) { object_t *o; char obname[BUFLEN]; for (o = newcell->obpile->first ; o ; o = o->next) { if (isimpassableob(o, lf)) { getobname(o, obname, o->amt); if (isplayer(lf)) { msg("You seep under %s.", obname); } else if (haslos(player, newcell)) { msg("%s seeps under %s.", lfname, obname); } } } } // see objects on ground if (isplayer(lf)) { int numobs; numobs = countobs(newcell->obpile); if ((numobs == 0) && !newcell->writing) { // just clear the message buffer if (!didmsg) clearmsg(); } else { // tell player what is here dolook(newcell); } } } return B_FALSE; } int movetowards(lifeform_t *lf, cell_t *dst) { int dir; int rv = B_TRUE; if (isblind(lf)) { dorandommove(lf, B_TRUE); return B_FALSE; } // move towards them dir = getdirtowards(lf->cell, dst, lf, B_TRUE); if (dir != D_NONE) { rv = trymove(lf, dir); } return rv; } int opendoorat(lifeform_t *lf, cell_t *c) { object_t *o; int rv; o = hasobwithflag(c->obpile, F_DOOR); if (o) { rv = opendoor(lf, o); } else { rv = B_TRUE; } return rv; } int opendoor(lifeform_t *lf, object_t *o) { cell_t *doorcell; char buf[BUFLEN]; char obname[BUFLEN]; flag_t *f; doorcell = o->pile->where; assert(doorcell); getobname(o, obname, 1); if (!isdoor(o, NULL)) { return B_TRUE; } if (lf && lfhasflagval(lf, F_NOBODYPART, BP_HANDS, NA, NA, NULL)) { if (isplayer(lf)) { msg("You have no hands with which to open the door!"); } return B_TRUE; } f = hasflag(o->flags, F_OPEN); if (f) { if (lf && isplayer(lf)) { msg("It is already open!"); } return B_TRUE; } else { if (lf) { taketime(lf, getactspeed(lf)); touch(lf, o); } // locked? if (hasflag(o->flags, F_LOCKED)) { if (lf && isplayer(lf)) { msg("The door is locked."); } return B_TRUE; } else { int openit = B_TRUE; f = hasflag(o->flags, F_JAMMED); if (f) { f->val[0] --; // loosen a bit if (lf && isplayer(lf)) { msg("You yank on the door but it holds fast."); } if (f->val[0] <= 0) { killflag(f); } openit = B_FALSE; // don't open the door } if (openit) { cell_t *where; // open it addflag(o->flags, F_OPEN, B_TRUE, NA, NA, NULL); f = hasflag(o->flags, F_IMPASSABLE); if (f) killflag(f); f = hasflag(o->flags, F_BLOCKSVIEW); if (f) killflag(f); if (lf) { if (lf->controller == C_PLAYER) { msg("You open %s.",obname); } else { if (cansee(player, lf) && isadjacent(lf->cell, doorcell)) { getlfname(lf, buf); capitalise(buf); msg("%s opens %s.",buf, obname); } else if (haslos(player, doorcell)) { capitalise(obname); msg("%s opens.",obname); } } } where = getoblocation(o); if (player && haslos(player, where)) { needredraw = B_TRUE; drawscreen(); } } return B_FALSE; } } return B_FALSE; } int closedoorat(lifeform_t *lf, cell_t *c) { object_t *o; int rv; o = hasobwithflag(c->obpile, F_DOOR); if (o) { rv = closedoor(lf, o); } else { rv = B_TRUE; } return rv; } int closedoor(lifeform_t *lf, object_t *o) { cell_t *cell; char buf[BUFLEN]; char obname[BUFLEN]; object_t *oo; flag_t *f; cell = getoblocation(o); getobname(o, obname, 1); if (!isdoor(o, NULL)) { if (isplayer(lf)) { msg("There is nothing to close there!"); } return B_TRUE; } if (lf && lfhasflagval(lf, F_NOBODYPART, BP_HANDS, NA, NA, NULL)) { if (isplayer(lf)) { msg("You have no hands with which to close the door!"); } return B_TRUE; } if (cell->lf) { if (lf && isplayer(lf)) { char inwayname[BUFLEN]; getlfname(cell->lf, inwayname); msg("%s is in the way!", haslos(lf, cell) ? inwayname : "Something"); } return B_TRUE; } // any object other than the door? for (oo = cell->obpile->first ; oo ; oo = oo->next) { if (oo != o) { if (lf && isplayer(lf)) { char inwayname[BUFLEN]; getobname(oo, inwayname, oo->amt); msg("%s is in the way!", haslos(lf, cell) ? inwayname : "Something"); } return B_TRUE; } } f = hasflag(o->flags, F_OPEN); if (!f) { if (lf && (lf->controller == C_PLAYER)) { msg("It is already closed!"); } return B_TRUE; } else { // close it killflag(f); addflag(o->flags, F_IMPASSABLE, B_TRUE, NA, NA, NULL); addflag(o->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL); if (lf) { if (lf->controller == C_PLAYER) { msg("You close %s.", obname); } else { if (cansee(player, lf) && isadjacent(lf->cell, cell)) { getlfname(lf, buf); capitalise(buf); msg("%s closes %s.",buf, obname); } else if (haslos(player, cell)) { capitalise(obname); msg("%s closes.",obname); } } taketime(lf, getactspeed(lf)); touch(lf, o); } } return B_FALSE; } int tryrun(lifeform_t *lf, int dir) { if (!trymove(lf, dir)) { addflag(lf->flags, F_RUNNING, dir, NA, NA, NULL); } return B_FALSE; } // try to pull lifeform towards cell c (or next to it) int pullnextto(lifeform_t *lf, cell_t *c) { int dir; cell_t *dst = NULL; dst = c; while (dst->lf) { dir = getdirtowards(dst, lf->cell, lf, B_FALSE); if (dir == D_NONE) { return B_TRUE; } else { dst = getcellindir(dst, dir); if (dst == lf->cell) { return B_TRUE; } } } // is the path clear? if (!dst || !haslof(lf, dst)) { return B_TRUE; } if (isplayer(lf) || cansee(player, lf)) { char buf[BUFLEN]; getlfname(lf, buf); msg("%s %s pulled %s!", buf, isplayer(lf) ? "are" : "is", isairborne(lf) ? "through the air" : "along the ground"); } movelf(lf, dst); return B_FALSE; } // teleport somewhere, along with puffs of smoke etc int teleportto(lifeform_t *lf, cell_t *c, int wantsmoke) { char buf[BUFLEN]; // can't teleport on top of something else if (c->lf) { if (isplayer(lf)) { msg("You feel a wrenching sensation."); } return B_TRUE; } if (!isplayer(lf) && cansee(player, lf)) { getlfname(lf, buf); if (wantsmoke) { msg("%s disappears in a cloud of smoke!", buf); } else { msg("%s vanishes!", buf); } } if (wantsmoke) { addob(lf->cell->obpile, "cloud of smoke"); } movelf(lf, c); // addob(lf->cell->obpile, "cloud of smoke"); if (isplayer(lf)) { msg("Suddenly, your surroundings appear different!"); } else if (cansee(player, lf)) { getlfname(lf, buf); msg("%s appears!", buf); } // show any objects here, just like if we moved. // BUT don't let dolook() clear the msg bar if there are // no objects here. if (isplayer(lf) && countobs(lf->cell->obpile)) { dolook(lf->cell); } return B_FALSE; } int trymove(lifeform_t *lf, int dir) { cell_t *cell; enum ERROR errcode; char buf[BUFLEN]; cell = getcellindir(lf->cell, dir); if (canandwillmove(lf, dir, &errcode)) { object_t *o,*slipob; int slip; // check for cursed objects + animals for (o = cell->obpile->first ; o ; o = o->next) { if (!isplayer(lf)) { if (o->blessed == B_CURSED) { if (lfhasflag(lf, F_ANIMAL)) { if (!isairborne(lf)) { if (cansee(player, lf)) { char lfname[BUFLEN]; getlfname(lf,lfname); getobname(o, buf, o->amt); msg("%s %s away from %s!", lfname, isplayer(lf) ? "shy" : "shies", buf); o->blessknown = B_TRUE; } taketime(lf, getmovespeed(lf)); reason = E_OK; return B_FALSE; } } } } } // slipping on blood before moving? slip = getslipperyness(lf->cell, &slipob); if (slip && !skillcheck(lf, SC_SLIP, slip, 0)) { slipon(lf, slipob); // don't move reason = E_OK; return B_FALSE; } // move to new cell reason = E_OK; moveto(lf, cell); taketime(lf, getmovespeed(lf)); // slip on blood in new cell? slip = getslipperyness(cell, &slipob); if (slip && !skillcheck(lf, SC_SLIP, slip, 0)) { slipon(lf, slipob); // don't move reason = E_OK; return B_FALSE; } } else { object_t *inway; int door, dooropen; reason = errcode; switch (errcode) { case E_WALLINWAY: if (isplayer(lf)) { msg("Ouch! You %s into a wall.", getmoveverb(lf)); } else if (cansee(player, lf)) { getlfname(lf, buf); msg("%s %ss into a wall.", buf, getmoveverb(lf)); } if (isblind(lf)) { if (isplayer(lf)) { // only take damage if we didn't know about this if (!cell->known) { sprintf(buf, "%sing into a wall", getmoveverb(lf)); losehp(lf, 1, DT_BASH, NULL, buf); cell->known = B_TRUE; taketime(lf, getmovespeed(lf)); } } else { sprintf(buf, "%sing into a wall", getmoveverb(lf)); losehp(lf, 1, DT_BASH, NULL, buf); taketime(lf, getmovespeed(lf)); } } break; case E_OBINWAY: inway = (object_t *)rdata; door = isdoor(inway, &dooropen); if (door && !dooropen) { if (isblind(lf)) { // run into it if (isplayer(lf)) { if (cell->known) { // try to open it opendoor(lf, inway); } else { msg("Ouch! You %s into a door.", getmoveverb(lf)); cell->known = B_TRUE; sprintf(buf, "%sing into a door", getmoveverb(lf)); losehp(lf, 1, DT_BASH, NULL, buf); taketime(lf, getmovespeed(lf)); } } else { if (cansee(player, lf)) { getlfname(lf, buf); msg("%s %ss into a wall.", buf, getmoveverb(lf)); } sprintf(buf, "%sing into a door", getmoveverb(lf)); losehp(lf, 1, DT_BASH, NULL, buf); taketime(lf, getmovespeed(lf)); } } else { // try to open it if (!opendoor(lf, inway)) { // opening a door counts as a successful move. reason = E_OK; } } } else { // can we push this? if (ispushable(inway)) { if (canpush(lf, inway, dir)) { // push it! push(lf, inway, dir); } else { if (lf->controller == C_PLAYER) { char obname[BUFLEN]; getobname(inway, obname, 1); switch (reason) { case E_TOOHEAVY: msg("The %s is too heavy to move.",strchr(obname, ' ')+1); break; case E_INSUBSTANTIAL: msg("You cannot push %s without a physical body!",strchr(obname, ' ')+1); break; default: msg("The %s won't move for some reason.",strchr(obname, ' ')+1); break; } } } } else { // object is in the way if (lf->controller == C_PLAYER) { char obname[BUFLEN]; getobname(inway, obname, 1); msg("There is %s in your way.",obname); } } } break; case E_LFINWAY: // attack! return attacklf(lf, cell->lf); case E_GRAVBOOSTED: if (isplayer(lf)) { msg("You try to move but are unable to lift your feet!"); } else if (cansee(player, lf)) { char lfname[BUFLEN]; getlfname(lf, lfname); msg("%s tries to move but is unable to lift its feet!",lfname); } taketime(lf, getmovespeed(lf)); break; case E_CANTMOVE: if (isplayer(lf)) { msg("You cannot move!"); } taketime(lf, getmovespeed(lf)); break; case E_GRABBEDBY: if (rdata) { lifeform_t *grabbedby; char gbname[BUFLEN]; // skill check to escape. grabbedby = (lifeform_t *)rdata; getlfname(grabbedby, gbname); if (!cell->lf && skillcheckvs(lf, SC_STR, 0, grabbedby, SC_STR, 0)) { // broke free killflagsofid(lf->flags, F_GRABBEDBY); killflagsofid(grabbedby->flags, F_GRABBING); // move - don't clear the 'you break free from' msg real_moveto(lf, cell, B_TRUE); } else { if (isplayer(lf)) { msg("You cannot get away from %s!",gbname); } } } else { if (isplayer(lf)) { msg("You cannot get away from whatever is holding you!"); } } taketime(lf, getmovespeed(lf)); break; case E_TOOHEAVY: if (isplayer(lf)) { msg("Your load is too heavy to move with!"); } taketime(lf, getmovespeed(lf)); break; default: break; } if (reason == E_OK) { return B_FALSE; } else { return B_TRUE; } } return B_FALSE; } int willmove(lifeform_t *lf, int dir, enum ERROR *error) { cell_t *cell; //object_t *o; // default if (error) { *error = E_OK; rdata = NULL; } cell = getcellindir(lf->cell, dir); if (celldangerous(lf, cell, error)) { return B_FALSE; } // don't attack other monsters if (cell->lf) { if (!isplayer(lf)) { if (!isplayer(cell->lf) && !isfriendly(cell->lf)) { return B_FALSE; } } } return B_TRUE; }