#include #include #include "attack.h" #include "defs.h" #include "lf.h" #include "map.h" #include "objects.h" #include "text.h" extern lifeform_t *player; int canmove(lifeform_t *lf, int dir, enum ERROR *error) { cell_t *cell; cell = getcellindir(lf->cell, dir); if (!cell || cell->type->solid) { if (error) *error = E_WALLINWAY; return B_FALSE; } if (cell->lf) { if (error) *error = E_LFINWAY; return B_FALSE; } return B_TRUE; } 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 = canmove(lf, dir, &why); if (!moveok && badmovesok) { switch (why) { case E_WALLINWAY: case E_LFINWAY: moveok = B_TRUE; break; } } while (!moveok) { // try next direction... if (++dir > DC_NW) dir = DC_N; if (++tries >= MAXDIR_COMPASS) { dowait(lf); return; } // check this direction... moveok = canmove(lf, dir, &why); if (!moveok && badmovesok) { switch (why) { case E_WALLINWAY: case E_LFINWAY: moveok = B_TRUE; break; } } } trymove(lf, dir); } int dowait(lifeform_t *lf) { taketime(lf, SPEED_WAIT); if (lf->controller == C_PLAYER) { // clear msg bar clearmsg(); } return B_FALSE; } void movelf(lifeform_t *lf, cell_t *newcell) { object_t *o,*nexto; char obname[BUFLEN],lfname[BUFLEN],buf[BUFLEN]; // update current cell lf->cell->lf = NULL; // update lifeform lf->cell = newcell; // update new cell newcell->lf = lf; // check ground objects if (!hasflag(lf->flags, F_FLYING)) { for (o = newcell->obpile->first ; o ; o = nexto ) { nexto = o->next; if (hasflag(o->flags, F_SHARP)) { object_t *boots; // has boots on? boots = getequippedob(lf->pack, BP_FEET); if (boots) { // crunch the broken glass getobname(o, obname, 1); 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); strrep(newname, "a ", "some "); strcpy(obname, newname); free(newname); } if (lf->controller == C_PLAYER) { msg("You crush %s underfoot.",obname); } else if (haslos(player, newcell)) { getlfname(lf, lfname); capitalise(lfname); msg("%s crushes %s.",lfname, obname); } // kill object removeob(o, o->amt); } else { // take damage getobname(o, obname, 1); if (lf->controller == C_PLAYER) { msg("Ow - you step on %s!",obname); } else if (haslos(player, newcell)) { getlfname(lf, lfname); capitalise(lfname); msg("%s steps on %s!",lfname, obname); } sprintf(buf, "stepping on %s", obname); losehp(lf, rnd(1,2), DT_SLASH, NULL, buf); } } } // end foreach object in cell } // end if !flying // update where player knows // (but without a map you will then slowly forget it) if (lf->controller == C_PLAYER) { updateknowncells(); } } // 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) { // actually do the move movelf(lf, newcell); // tell player about things if (!isdead(lf) && (lf->controller == C_PLAYER)) { int numobs; char buf[BUFLEN]; numobs = countobs(newcell->obpile); if (numobs == 1) { getobname(newcell->obpile->first, buf, newcell->obpile->first->amt); msg("You see %s here.", buf); } else if ((numobs > 1) && (numobs <= 3)) { msg("You see a few objects here."); } else if ((numobs > 3) && (numobs <= 6)) { msg("You see some objects here."); } else if (numobs > 6) { msg("You see many objects here."); } else { // just clear the message buffer clearmsg(); } } } int opendoor(lifeform_t *lf, cell_t *cell) { char buf[BUFLEN]; if (cell->type->id == CT_DOORCLOSED) { // open it setcelltype(cell, CT_DOOROPEN); if (lf->controller == C_PLAYER) { msg("You open a door."); } else { // TODO: only announce if player can see it if (haslos(player, cell)) { getlfname(lf, buf); capitalise(buf); msg("%s opens a door.",buf); } } taketime(lf, getmovespeed(lf)); } else { return B_TRUE; } return B_FALSE; } int tryrun(lifeform_t *lf, int dir) { // continue moving until we fail while (canmove(lf, dir, NULL)) { trymove(lf,dir); } } int trymove(lifeform_t *lf, int dir) { cell_t *cell; enum ERROR errcode; char buf[BUFLEN], buf2[BUFLEN]; cell = getcellindir(lf->cell, dir); if (canmove(lf, dir, &errcode)) { moveto(lf, cell); taketime(lf, getmovespeed(lf)); } else { switch (errcode) { case E_WALLINWAY: // is it a door in the way? if (cell->type->id == CT_DOORCLOSED) { // try to open it opendoor(lf, cell); } else { if (lf->controller == C_PLAYER) { msg("Ouch! You walk into a wall."); } } break; case E_LFINWAY: // attack! doattack(lf, cell->lf); break; } return B_TRUE; } return B_FALSE; }