/* look for gold, on the floor or in monsters' possession */ int gold_detect(struct obj *sobj, boolean *scr_known) { struct obj *obj; struct monst *mtmp; int uw = u.uinwater; struct obj *temp; boolean stale; *scr_known = stale = clear_stale_map(COIN_CLASS, sobj->blessed ? GOLD : 0); /* look for gold carried by monsters (might be in a container) */ for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) { if (DEADMONSTER(mtmp)) continue; /* probably not needed in this case but... */ if (findgold(mtmp->minvent) || monsndx(mtmp->data) == PM_GOLD_GOLEM) { *scr_known = TRUE; goto outgoldmap; /* skip further searching */ } else for (obj = mtmp->minvent; obj; obj = obj->nobj) if (sobj->blessed && o_material(obj, GOLD)) { *scr_known = TRUE; goto outgoldmap; } else if (o_in(obj, COIN_CLASS)) { *scr_known = TRUE; goto outgoldmap; /* skip further searching */ } } /* look for gold objects */ for (obj = level->objlist; obj; obj = obj->nobj) { if (sobj->blessed && o_material(obj, GOLD)) { *scr_known = TRUE; if (obj->ox != u.ux || obj->oy != u.uy) goto outgoldmap; } else if (o_in(obj, COIN_CLASS)) { *scr_known = TRUE; if (obj->ox != u.ux || obj->oy != u.uy) goto outgoldmap; } } if (!*scr_known) { /* no gold found on floor or monster's inventory. adjust message if you have gold in your inventory */ char buf[BUFSZ]; if (youmonst.data == &mons[PM_GOLD_GOLEM]) { sprintf(buf, "You feel like a million %s!", currency(2L)); } else if (hidden_gold() || money_cnt(invent)) strcpy(buf, "You feel worried about your future financial situation."); else strcpy(buf, "You feel materially poor."); strange_feeling(sobj, buf); return 1; } /* only under me - no separate display required */ if (stale) doredraw(); pline("You notice some gold between your %s.", makeplural(body_part(FOOT))); return 0; outgoldmap: cls(); u.uinwater = 0; /* Discover gold locations. */ for (obj = level->objlist; obj; obj = obj->nobj) { if (sobj->blessed && (temp = o_material(obj, GOLD))) { if (temp != obj) { temp->ox = obj->ox; temp->oy = obj->oy; } map_object(temp,1); } else if ((temp = o_in(obj, COIN_CLASS))) { if (temp != obj) { temp->ox = obj->ox; temp->oy = obj->oy; } map_object(temp,1); } } for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) { if (DEADMONSTER(mtmp)) continue; /* probably overkill here */ if (findgold(mtmp->minvent) || monsndx(mtmp->data) == PM_GOLD_GOLEM) { struct obj gold; gold.otyp = GOLD_PIECE; gold.ox = mtmp->mx; gold.oy = mtmp->my; map_object(&gold,1); } else for (obj = mtmp->minvent; obj; obj = obj->nobj) if (sobj->blessed && (temp = o_material(obj, GOLD))) { temp->ox = mtmp->mx; temp->oy = mtmp->my; map_object(temp,1); break; } else if ((temp = o_in(obj, COIN_CLASS))) { temp->ox = mtmp->mx; temp->oy = mtmp->my; map_object(temp,1); break; } } newsym(u.ux,u.uy); pline("You feel very greedy, and sense gold!"); exercise(A_WIS, TRUE); win_pause_output(P_MAP); doredraw(); u.uinwater = uw; if (Underwater) under_water(2); if (u.uburied) under_ground(2); return 0; }
/* returns 0 if something was detected */ int food_detect(struct obj *sobj, boolean *scr_known) { struct obj *obj; struct monst *mtmp; int ct = 0, ctu = 0; boolean confused = (Confusion || (sobj && sobj->cursed)), stale; char oclass = confused ? POTION_CLASS : FOOD_CLASS; const char *what = confused ? "something" : "food"; int uw = u.uinwater; stale = clear_stale_map(oclass, 0); for (obj = level->objlist; obj; obj = obj->nobj) if (o_in(obj, oclass)) { if (obj->ox == u.ux && obj->oy == u.uy) ctu++; else ct++; } for (mtmp = level->monlist; mtmp && !ct; mtmp = mtmp->nmon) { /* no DEADMONSTER(mtmp) check needed since dmons never have inventory */ for (obj = mtmp->minvent; obj; obj = obj->nobj) if (o_in(obj, oclass)) { ct++; break; } } if (!ct && !ctu) { *scr_known = stale && !confused; if (stale) { doredraw(); pline("You sense a lack of %s nearby.", what); if (sobj && sobj->blessed) { if (!u.uedibility) pline("Your %s starts to tingle.", body_part(NOSE)); u.uedibility = 1; } } else if (sobj) { char buf[BUFSZ]; sprintf(buf, "Your %s twitches%s.", body_part(NOSE), (sobj->blessed && !u.uedibility) ? " then starts to tingle" : ""); if (sobj->blessed && !u.uedibility) { boolean savebeginner = flags.beginner; /* prevent non-delivery of */ flags.beginner = FALSE; /* message */ strange_feeling(sobj, buf); flags.beginner = savebeginner; u.uedibility = 1; } else strange_feeling(sobj, buf); } return !stale; } else if (!ct) { *scr_known = TRUE; pline("You %s %s nearby.", sobj ? "smell" : "sense", what); if (sobj && sobj->blessed) { if (!u.uedibility) pline("Your %s starts to tingle.", body_part(NOSE)); u.uedibility = 1; } } else { struct obj *temp; *scr_known = TRUE; cls(); u.uinwater = 0; for (obj = level->objlist; obj; obj = obj->nobj) if ((temp = o_in(obj, oclass)) != 0) { if (temp != obj) { temp->ox = obj->ox; temp->oy = obj->oy; } map_object(temp,1); } for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) /* no DEADMONSTER(mtmp) check needed since dmons never have inventory */ for (obj = mtmp->minvent; obj; obj = obj->nobj) if ((temp = o_in(obj, oclass)) != 0) { temp->ox = mtmp->mx; temp->oy = mtmp->my; map_object(temp,1); break; /* skip rest of this monster's inventory */ } newsym(u.ux,u.uy); if (sobj) { if (sobj->blessed) { pline("Your %s %s to tingle and you smell %s.", body_part(NOSE), u.uedibility ? "continues" : "starts", what); u.uedibility = 1; } else pline("Your %s tingles and you smell %s.", body_part(NOSE), what); } else pline("You sense %s.", what); win_pause_output(P_MAP); exercise(A_WIS, TRUE); doredraw(); u.uinwater = uw; if (Underwater) under_water(2); if (u.uburied) under_ground(2); } return 0; }
/* * move_bc() * * Move the ball and chain. This is called twice for every move. The first * time to pick up the ball and chain before the move, the second time to * place the ball and chain after the move. If the ball is carried, this * function should never have BC_BALL as part of its control. * * Should not be called while swallowed. */ void move_bc(int before, int control, xchar ballx, xchar bally, xchar chainx, xchar chainy) { if (Blind) { /* * The hero is blind. Time to work hard. The ball and chain that * are attached to the hero are very special. The hero knows that * they are attached, so when they move, the hero knows that they * aren't at the last position remembered. This is complicated * by the fact that the hero can "feel" the surrounding locations * at any time, hence, making one or both of them show up again. * So, we have to keep track of which is felt at any one time and * act accordingly. */ if (!before) { if ((control & BC_CHAIN) && (control & BC_BALL)) { /* * Both ball and chain moved. If felt, drop glyph. */ if (u.bc_felt & BC_BALL) level->locations[uball->ox][uball->oy].mem_obj = u.bglyph; if (u.bc_felt & BC_CHAIN) level->locations[uchain->ox][uchain->oy].mem_obj = u.cglyph; u.bc_felt = 0; /* Pick up mem_obj at new location. */ u.bglyph = level->locations[ballx][bally].mem_obj; u.cglyph = level->locations[chainx][chainy].mem_obj; movobj(uball, ballx, bally); movobj(uchain, chainx, chainy); } else if (control & BC_BALL) { if (u.bc_felt & BC_BALL) { if (u.bc_order == BCPOS_DIFFER) { /* ball by itself */ level->locations[uball->ox][uball->oy].mem_obj = u.bglyph; } else if (u.bc_order == BCPOS_BALL) { if (u.bc_felt & BC_CHAIN) { /* know chain is there */ map_object(uchain, 0, TRUE); } else { level->locations[uball->ox][uball->oy].mem_obj = u.bglyph; } } u.bc_felt &= ~BC_BALL; /* no longer feel the ball */ } /* Pick up mem_obj at new position. */ u.bglyph = (ballx != chainx || bally != chainy) ? level->locations[ballx][bally].mem_obj : u.cglyph; movobj(uball, ballx, bally); } else if (control & BC_CHAIN) { if (u.bc_felt & BC_CHAIN) { if (u.bc_order == BCPOS_DIFFER) { level->locations[uchain->ox][uchain->oy].mem_obj = u.cglyph; } else if (u.bc_order == BCPOS_CHAIN) { if (u.bc_felt & BC_BALL) { map_object(uball, 0, TRUE); } else { level->locations[uchain->ox][uchain->oy].mem_obj = u.cglyph; } } u.bc_felt &= ~BC_CHAIN; } /* Pick up mem_obj at new position. */ u.cglyph = (ballx != chainx || bally != chainy) ? level->locations[chainx][chainy].mem_obj : u.bglyph; movobj(uchain, chainx, chainy); } u.bc_order = bc_order(); /* reset the order */ } } else { /* * The hero is not blind. To make this work correctly, we need to * pick up the ball and chain before the hero moves, then put them * in their new positions after the hero moves. */ if (before) { if (!control) { /* * Neither ball nor chain is moving, so remember which was * on top until !before. Use the variable u.bc_order * since it is only valid when blind. */ u.bc_order = bc_order(); } remove_object(uchain); newsym(uchain->ox, uchain->oy); if (!carried(uball)) { remove_object(uball); newsym(uball->ox, uball->oy); } } else { int on_floor = !carried(uball); if ((control & BC_CHAIN) || (!control && u.bc_order == BCPOS_CHAIN)) { /* If the chain moved or nothing moved & chain on top. */ if (on_floor) place_object(uball, level, ballx, bally); place_object(uchain, level, chainx, chainy); /* chain on top */ } else { place_object(uchain, level, chainx, chainy); if (on_floor) place_object(uball, level, ballx, bally); /* ball on top */ } newsym(chainx, chainy); if (on_floor) newsym(ballx, bally); } } }