/** * Light or Darken the town */ void cave_illuminate(struct chunk *c, bool daytime) { int y, x, i; /* Apply light or darkness */ for (y = 0; y < c->height; y++) { for (x = 0; x < c->width; x++) { int d; bool light = false; /* Skip grids with no surrounding floors or stairs */ for (d = 0; d < 9; d++) { /* Extract adjacent (legal) location */ int yy = y + ddy_ddd[d]; int xx = x + ddx_ddd[d]; /* Paranoia */ if (!square_in_bounds_fully(c, yy, xx)) continue; /* Test */ if (square_isfloor(c, yy, xx) || square_isstairs(c, yy, xx)) light = true; } if (!light) continue; /* Only interesting grids at night */ if (daytime || !square_isfloor(c, y, x)) { sqinfo_on(c->squares[y][x].info, SQUARE_GLOW); square_memorize(c, y, x); } else if (!square_isbright(c, y, x)) { sqinfo_off(c->squares[y][x].info, SQUARE_GLOW); square_forget(c, y, x); } } } /* Light shop doorways */ for (y = 0; y < c->height; y++) { for (x = 0; x < c->width; x++) { if (!square_isshop(c, y, x)) continue; for (i = 0; i < 8; i++) { int yy = y + ddy_ddd[i]; int xx = x + ddx_ddd[i]; sqinfo_on(c->squares[yy][xx].info, SQUARE_GLOW); square_memorize(c, yy, xx); } } } /* Fully update the visuals */ player->upkeep->update |= (PU_UPDATE_VIEW | PU_MONSTERS); /* Redraw map, monster list */ player->upkeep->redraw |= (PR_MAP | PR_MONLIST | PR_ITEMLIST); }
/** * Reveal some of the player traps in a square */ bool square_reveal_trap(struct chunk *c, int y, int x, bool always, bool domsg) { int found_trap = 0; struct trap *trap = square_trap(c, y, x); /* Check there is a player trap */ if (!square_isplayertrap(c, y, x)) return false; /* Scan the grid */ while (trap) { /* Skip non-player traps */ if (!trf_has(trap->flags, TRF_TRAP)) { trap = trap->next; continue; } /* Skip traps the player doesn't notice */ if (!always && player->state.skills[SKILL_SEARCH] < trap->power) { trap = trap->next; continue; } /* Trap is invisible */ if (!trf_has(trap->flags, TRF_VISIBLE)) { /* See the trap */ trf_on(trap->flags, TRF_VISIBLE); square_memorize(c, y, x); /* We found a trap */ found_trap++; } trap = trap->next; } /* We found at least one trap */ if (found_trap) { /* We want to talk about it */ if (domsg) { if (found_trap == 1) msg("You have found a trap."); else msg("You have found %d traps.", found_trap); } /* Memorize */ square_memorize(c, y, x); /* Redraw */ square_light_spot(c, y, x); } /* Return true if we found any traps */ return (found_trap != 0); }
/** * Reveal some of the player traps in a square */ bool square_reveal_trap(struct chunk *c, int y, int x, int chance, bool domsg) { int found_trap = 0; struct trap *trap = square_trap(c, y, x); /* Check there is a player trap */ if (!square_isplayertrap(c, y, x)) return false; /* Scan the grid */ while (trap) { /* Skip non-player traps */ if (!trf_has(trap->flags, TRF_TRAP)) { trap = trap->next; continue; } /* Trap is invisible */ if (!trf_has(trap->flags, TRF_VISIBLE)) { /* See the trap */ trf_on(trap->flags, TRF_VISIBLE); square_memorize(c, y, x); /* We found a trap */ found_trap++; /* If chance is < 100, check for further looking */ if ((chance < 100) && (randint1(100) > chance)) break; } trap = trap->next; } /* We found at least one trap */ if (found_trap) { /* We want to talk about it */ if (domsg) { if (found_trap == 1) msg("You have found a trap."); else msg("You have found %d traps.", found_trap); } /* Memorize */ square_memorize(c, y, x); /* Redraw */ square_light_spot(c, y, x); } /* Return true if we found any traps */ return (found_trap != 0); }
/** * Light up the dungeon using "claravoyance" * * This function "illuminates" every grid in the dungeon, memorizes all * "objects" (or notes the existence of an object "if" full is true), * and memorizes all grids as with magic mapping. */ void wiz_light(struct chunk *c, struct player *p, bool full) { int i, y, x; /* Scan all grids */ for (y = 1; y < c->height - 1; y++) { for (x = 1; x < c->width - 1; x++) { /* Process all non-walls */ if (!square_seemslikewall(c, y, x)) { if (!square_in_bounds_fully(c, y, x)) continue; /* Scan all neighbors */ for (i = 0; i < 9; i++) { int yy = y + ddy_ddd[i]; int xx = x + ddx_ddd[i]; /* Perma-light the grid */ sqinfo_on(c->squares[yy][xx].info, SQUARE_GLOW); /* Memorize normal features */ if (!square_isfloor(c, yy, xx) || square_isvisibletrap(c, yy, xx)) { square_memorize(c, yy, xx); square_mark(c, yy, xx); } } } /* Memorize objects */ if (full) { square_know_pile(c, y, x); } else { square_sense_pile(c, y, x); } /* Forget unprocessed, unknown grids in the mapping area */ if (!square_ismark(c, y, x) && square_isnotknown(c, y, x)) square_forget(c, y, x); } } /* Unmark grids */ for (y = 1; y < c->height - 1; y++) { for (x = 1; x < c->width - 1; x++) { if (!square_in_bounds(c, y, x)) continue; square_unmark(c, y, x); } } /* Fully update the visuals */ p->upkeep->update |= (PU_UPDATE_VIEW | PU_MONSTERS); /* Redraw whole map, monster list */ p->upkeep->redraw |= (PR_MAP | PR_MONLIST | PR_ITEMLIST); }
/** * Memorize interesting viewable object/features in the given grid * * This function should only be called on "legal" grids. * * This function will memorize the object and/or feature in the given grid, * if they are (1) see-able and (2) interesting. Note that all objects are * interesting, all terrain features except floors (and invisible traps) are * interesting, and floors (and invisible traps) are interesting sometimes * (depending on various options involving the illumination of floor grids). * * The automatic memorization of all objects and non-floor terrain features * as soon as they are displayed allows incredible amounts of optimization * in various places, especially "map_info()" and this function itself. * * Note that the memorization of objects is completely separate from the * memorization of terrain features, preventing annoying floor memorization * when a detected object is picked up from a dark floor, and object * memorization when an object is dropped into a floor grid which is * memorized but out-of-sight. * * This function should be called every time the "memorization" of a grid * (or the object in a grid) is called into question, such as when an object * is created in a grid, when a terrain feature "changes" from "floor" to * "non-floor", and when any grid becomes "see-able" for any reason. * * This function is called primarily from the "update_view()" function, for * each grid which becomes newly "see-able". */ void square_note_spot(struct chunk *c, int y, int x) { /* Require "seen" flag and the current level */ if (c != cave) return; if (!square_isseen(c, y, x)) return; /* Make the player know precisely what is on this grid */ square_know_pile(c, y, x); /* Notice traps */ if (square_issecrettrap(c, y, x)) { square_reveal_trap(c, y, x, false, true); } if (square_isknown(c, y, x)) return; /* Memorize this grid */ square_memorize(c, y, x); }
/** * Perform the basic "close" command * * Assume there is no monster blocking the destination * * Returns true if repeated commands may continue */ static bool do_cmd_close_aux(int y, int x) { bool more = false; /* Verify legality */ if (!do_cmd_close_test(y, x)) return (false); /* Broken door */ if (square_isbrokendoor(cave, y, x)) { msg("The door appears to be broken."); } else { /* Close door */ square_close_door(cave, y, x); square_memorize(cave, y, x); square_light_spot(cave, y, x); player->upkeep->update |= (PU_UPDATE_VIEW | PU_MONSTERS); sound(MSG_SHUTDOOR); } /* Result */ return (more); }
/** * Hit a trap. */ extern void hit_trap(int y, int x) { bool ident; struct trap *trap; struct effect *effect; /* Count the hidden traps here */ int num = num_traps(cave, y, x, -1); /* Oops. We've walked right into trouble. */ if (num == 1) msg("You stumble upon a trap!"); else if (num > 1) msg("You stumble upon some traps!"); /* Look at the traps in this grid */ for (trap = square_trap(cave, y, x); trap; trap = trap->next) { /* Require that trap be capable of affecting the character */ if (!trf_has(trap->kind->flags, TRF_TRAP)) continue; /* Disturb the player */ disturb(player, 0); /* Fire off the trap */ effect = trap->kind->effect; effect_do(effect, NULL, &ident, false, 0, 0, 0); /* Trap may have gone */ if (!square_trap(cave, y, x)) break; /* Trap becomes visible (always XXX) */ trf_on(trap->flags, TRF_VISIBLE); square_memorize(cave, y, x); } /* Verify traps (remove marker if appropriate) */ (void)square_verify_trap(cave, y, x, 0); }
/** * Move player in the given direction. * * This routine should only be called when energy has been expended. * * Note that this routine handles monsters in the destination grid, * and also handles attempting to move into walls/doors/rubble/etc. */ void move_player(int dir, bool disarm) { int y = player->py + ddy[dir]; int x = player->px + ddx[dir]; int m_idx = cave->squares[y][x].mon; struct monster *mon = cave_monster(cave, m_idx); bool alterable = (square_isknowntrap(cave, y, x) || square_iscloseddoor(cave, y, x)); /* Attack monsters, alter traps/doors on movement, hit obstacles or move */ if (m_idx > 0) { /* Mimics surprise the player */ if (is_mimicking(mon)) { become_aware(mon); /* Mimic wakes up */ mon_clear_timed(mon, MON_TMD_SLEEP, MON_TMD_FLG_NOMESSAGE, false); } else { py_attack(y, x); } } else if (disarm && square_isknown(cave, y, x) && alterable) { /* Auto-repeat if not already repeating */ if (cmd_get_nrepeats() == 0) cmd_set_repeat(99); do_cmd_alter_aux(dir); } else if (player->upkeep->running && square_isknowntrap(cave, y, x)) { /* Stop running before known traps */ disturb(player, 0); } else if (!square_ispassable(cave, y, x)) { disturb(player, 0); /* Notice unknown obstacles, mention known obstacles */ if (!square_isknown(cave, y, x)) { if (square_isrubble(cave, y, x)) { msgt(MSG_HITWALL, "You feel a pile of rubble blocking your way."); square_memorize(cave, y, x); square_light_spot(cave, y, x); } else if (square_iscloseddoor(cave, y, x)) { msgt(MSG_HITWALL, "You feel a door blocking your way."); square_memorize(cave, y, x); square_light_spot(cave, y, x); } else { msgt(MSG_HITWALL, "You feel a wall blocking your way."); square_memorize(cave, y, x); square_light_spot(cave, y, x); } } else { if (square_isrubble(cave, y, x)) msgt(MSG_HITWALL, "There is a pile of rubble blocking your way."); else if (square_iscloseddoor(cave, y, x)) msgt(MSG_HITWALL, "There is a door blocking your way."); else msgt(MSG_HITWALL, "There is a wall blocking your way."); } } else { /* Move player */ monster_swap(player->py, player->px, y, x); /* Handle store doors, or notice objects */ if (square_isshop(cave, y, x)) { disturb(player, 0); event_signal(EVENT_ENTER_STORE); event_remove_handler_type(EVENT_ENTER_STORE); event_signal(EVENT_USE_STORE); event_remove_handler_type(EVENT_USE_STORE); event_signal(EVENT_LEAVE_STORE); event_remove_handler_type(EVENT_LEAVE_STORE); } else { square_know_pile(cave, y, x); cmdq_push(CMD_AUTOPICKUP); } /* Discover invisible traps, set off visible ones */ if (square_issecrettrap(cave, y, x)) { disturb(player, 0); hit_trap(y, x); } else if (square_isknowntrap(cave, y, x)) { disturb(player, 0); hit_trap(y, x); } /* Update view and search */ update_view(cave, player); search(); } player->upkeep->running_firststep = false; }
/** * Perform the basic "open" command on doors * * Assume there is no monster blocking the destination * * Returns true if repeated commands may continue */ static bool do_cmd_open_aux(int y, int x) { int i, j; bool more = false; /* Verify legality */ if (!do_cmd_open_test(y, x)) return (false); /* Locked door */ if (square_islockeddoor(cave, y, x)) { /* Disarm factor */ i = player->state.skills[SKILL_DISARM_PHYS]; /* Penalize some conditions */ if (player->timed[TMD_BLIND] || no_light()) i = i / 10; if (player->timed[TMD_CONFUSED] || player->timed[TMD_IMAGE]) i = i / 10; /* Extract the lock power */ j = square_door_power(cave, y, x); /* Extract the difficulty XXX XXX XXX */ j = i - (j * 4); /* Always have a small chance of success */ if (j < 2) j = 2; if (randint0(100) < j) { /* Message */ msgt(MSG_LOCKPICK, "You have picked the lock."); /* Open the door */ square_open_door(cave, y, x); /* Update the visuals */ square_memorize(cave, y, x); square_light_spot(cave, y, x); player->upkeep->update |= (PU_UPDATE_VIEW | PU_MONSTERS); /* Experience */ /* Removed to avoid exploit by repeatedly locking and unlocking */ /* player_exp_gain(player, 1); */ } else { event_signal(EVENT_INPUT_FLUSH); /* Message */ msgt(MSG_LOCKPICK_FAIL, "You failed to pick the lock."); /* We may keep trying */ more = true; } } else { /* Closed door */ square_open_door(cave, y, x); square_memorize(cave, y, x); square_light_spot(cave, y, x); player->upkeep->update |= (PU_UPDATE_VIEW | PU_MONSTERS); sound(MSG_OPENDOOR); } /* Result */ return (more); }
/** * This function takes a grid location (x, y) and extracts information the * player is allowed to know about it, filling in the grid_data structure * passed in 'g'. * * The information filled in is as follows: * - g->f_idx is filled in with the terrain's feature type, or FEAT_NONE * if the player doesn't know anything about the grid. The function * makes use of the "mimic" field in terrain in order to allow one * feature to look like another (hiding secret doors, invisible traps, * etc). This will return the terrain type the player "Knows" about, * not necessarily the real terrain. * - g->m_idx is set to the monster index, or 0 if there is none (or the * player doesn't know it). * - g->first_kind is set to the object_kind of the first object in a grid * that the player knows about, or NULL for no objects. * - g->muliple_objects is true if there is more than one object in the * grid that the player knows and cares about (to facilitate any special * floor stack symbol that might be used). * - g->in_view is true if the player can currently see the grid - this can * be used to indicate field-of-view, such as through the * OPT(player, view_bright_light) option. * - g->lighting is set to indicate the lighting level for the grid: * LIGHTING_DARK for unlit grids, LIGHTING_LIT for inherently light * grids (lit rooms, etc), LIGHTING_TORCH for grids lit by the player's * light source, and LIGHTING_LOS for grids in the player's line of sight. * Note that lighting is always LIGHTING_LIT for known "interesting" grids * like walls. * - g->is_player is true if the player is on the given grid. * - g->hallucinate is true if the player is hallucinating something "strange" * for this grid - this should pick a random monster to show if the m_idx * is non-zero, and a random object if first_kind is non-zero. * * NOTES: * This is called pretty frequently, whenever a grid on the map display * needs updating, so don't overcomplicate it. * * Terrain is remembered separately from objects and monsters, so can be * shown even when the player can't "see" it. This leads to things like * doors out of the player's view still change from closed to open and so on. * * TODO: * Hallucination is currently disabled (it was a display-level hack before, * and we need it to be a knowledge-level hack). The idea is that objects * may turn into different objects, monsters into different monsters, and * terrain may be objects, monsters, or stay the same. */ void map_info(unsigned y, unsigned x, struct grid_data *g) { struct object *obj; assert(x < (unsigned) cave->width); assert(y < (unsigned) cave->height); /* Default "clear" values, others will be set later where appropriate. */ g->first_kind = NULL; g->trap = NULL; g->multiple_objects = false; g->lighting = LIGHTING_DARK; g->unseen_object = false; g->unseen_money = false; /* Use real feature (remove later) */ g->f_idx = cave->squares[y][x].feat; if (f_info[g->f_idx].mimic) g->f_idx = lookup_feat(f_info[g->f_idx].mimic); g->in_view = (square_isseen(cave, y, x)) ? true : false; g->is_player = (cave->squares[y][x].mon < 0) ? true : false; g->m_idx = (g->is_player) ? 0 : cave->squares[y][x].mon; g->hallucinate = player->timed[TMD_IMAGE] ? true : false; if (g->in_view) { g->lighting = LIGHTING_LOS; if (!square_isglow(cave, y, x) && OPT(player, view_yellow_light)) g->lighting = LIGHTING_TORCH; /* Remember seen feature */ square_memorize(cave, y, x); } else if (!square_isknown(cave, y, x)) { g->f_idx = FEAT_NONE; } else if (square_isglow(cave, y, x)) { g->lighting = LIGHTING_LIT; } /* Use known feature */ g->f_idx = player->cave->squares[y][x].feat; if (f_info[g->f_idx].mimic) g->f_idx = lookup_feat(f_info[g->f_idx].mimic); /* There is a trap in this square */ if (square_istrap(cave, y, x) && square_isknown(cave, y, x)) { struct trap *trap = cave->squares[y][x].trap; /* Scan the square trap list */ while (trap) { if (trf_has(trap->flags, TRF_TRAP) || trf_has(trap->flags, TRF_RUNE)) { /* Accept the trap - only if not disabled, maybe we need * a special graphic for this */ if (!trap->timeout) { g->trap = trap; break; } } trap = trap->next; } } /* Objects */ for (obj = square_object(player->cave, y, x); obj; obj = obj->next) { if (obj->kind == unknown_gold_kind) { g->unseen_money = true; } else if (obj->kind == unknown_item_kind) { g->unseen_object = true; } else if (ignore_known_item_ok(obj)) { /* Item stays hidden */ } else if (!g->first_kind) { g->first_kind = obj->kind; } else { g->multiple_objects = true; break; } } /* Monsters */ if (g->m_idx > 0) { /* If the monster isn't "visible", make sure we don't list it.*/ struct monster *mon = cave_monster(cave, g->m_idx); if (!monster_is_visible(mon)) g->m_idx = 0; } /* Rare random hallucination on non-outer walls */ if (g->hallucinate && g->m_idx == 0 && g->first_kind == 0) { if (one_in_(128) && (int) g->f_idx != FEAT_PERM) g->m_idx = 1; else if (one_in_(128) && (int) g->f_idx != FEAT_PERM) /* if hallucinating, we just need first_kind to not be NULL */ g->first_kind = k_info; else g->hallucinate = false; } assert((int) g->f_idx <= FEAT_PASS_RUBBLE); if (!g->hallucinate) assert((int)g->m_idx < cave->mon_max); /* All other g fields are 'flags', mostly booleans. */ }
/** * Move player in the given direction. * * This routine should only be called when energy has been expended. * * Note that this routine handles monsters in the destination grid, * and also handles attempting to move into walls/doors/rubble/etc. */ void move_player(int dir, bool disarm) { int py = player->py; int px = player->px; int y = py + ddy[dir]; int x = px + ddx[dir]; int m_idx = cave->squares[y][x].mon; struct monster *mon = cave_monster(cave, m_idx); bool alterable = (square_isknowntrap(cave, y, x) || square_iscloseddoor(cave, y, x)); /* Attack monsters, alter traps/doors on movement, hit obstacles or move */ if (m_idx > 0) { /* Mimics surprise the player */ if (is_mimicking(mon)) { become_aware(mon); /* Mimic wakes up */ mon_clear_timed(mon, MON_TMD_SLEEP, MON_TMD_FLG_NOMESSAGE, false); } else { py_attack(y, x); } } else if (disarm && square_isknown(cave, y, x) && alterable) { /* Auto-repeat if not already repeating */ if (cmd_get_nrepeats() == 0) cmd_set_repeat(99); do_cmd_alter_aux(dir); } else if (player->upkeep->running && square_isknowntrap(cave, y, x)) { /* Stop running before known traps */ disturb(player, 0); } else if (!square_ispassable(cave, y, x)) { /* Disturb the player */ disturb(player, 0); /* Notice unknown obstacles, mention known obstacles */ if (!square_isknown(cave, y, x)) { if (square_isrubble(cave, y, x)) { msgt(MSG_HITWALL, "You feel a pile of rubble blocking your way."); square_memorize(cave, y, x); square_light_spot(cave, y, x); } else if (square_iscloseddoor(cave, y, x)) { msgt(MSG_HITWALL, "You feel a door blocking your way."); square_memorize(cave, y, x); square_light_spot(cave, y, x); } else { msgt(MSG_HITWALL, "You feel a wall blocking your way."); square_memorize(cave, y, x); square_light_spot(cave, y, x); } } else { if (square_isrubble(cave, y, x)) msgt(MSG_HITWALL, "There is a pile of rubble blocking your way."); else if (square_iscloseddoor(cave, y, x)) msgt(MSG_HITWALL, "There is a door blocking your way."); else msgt(MSG_HITWALL, "There is a wall blocking your way."); } } else { /* See if trap detection status will change */ bool old_dtrap = square_isdtrap(cave, py, px); bool new_dtrap = square_isdtrap(cave, y, x); /* Note the change in the detect status */ if (old_dtrap != new_dtrap) player->upkeep->redraw |= (PR_DTRAP); /* Disturb player if the player is about to leave the area */ if (player->upkeep->running && !player->upkeep->running_firststep && old_dtrap && !new_dtrap) { disturb(player, 0); return; } /* Move player */ monster_swap(py, px, y, x); /* New location */ y = py = player->py; x = px = player->px; /* Searching */ if (player->searching || (player->state.skills[SKILL_SEARCH_FREQUENCY] >= 50) || one_in_(50 - player->state.skills[SKILL_SEARCH_FREQUENCY])) search(false); /* Handle store doors, or notice objects */ if (square_isshop(cave, player->py, player->px)) { /* Disturb */ disturb(player, 0); event_signal(EVENT_ENTER_STORE); event_remove_handler_type(EVENT_ENTER_STORE); event_signal(EVENT_USE_STORE); event_remove_handler_type(EVENT_USE_STORE); event_signal(EVENT_LEAVE_STORE); event_remove_handler_type(EVENT_LEAVE_STORE); } else { /* Know objects, queue autopickup */ floor_pile_know(cave, player->py, player->px); cmdq_push(CMD_AUTOPICKUP); } /* Discover invisible traps, set off visible ones */ if (square_issecrettrap(cave, y, x)) { /* Disturb */ disturb(player, 0); /* Hit the trap. */ hit_trap(y, x); } else if (square_isknowntrap(cave, y, x)) { /* Disturb */ disturb(player, 0); /* Hit the trap */ hit_trap(y, x); } } player->upkeep->running_firststep = false; }
/** * Hit a trap. */ extern void hit_trap(int y, int x) { bool ident = false; struct trap *trap; struct effect *effect; /* Count the hidden traps here */ int num = num_traps(cave, y, x, -1); /* The player is safe from all traps */ if (player_is_trapsafe(player)) return; /* Oops. We've walked right into trouble. */ if (num == 1) msg("You stumble upon a trap!"); else if (num > 1) msg("You stumble upon some traps!"); /* Look at the traps in this grid */ for (trap = square_trap(cave, y, x); trap; trap = trap->next) { int flag; bool saved = false; /* Require that trap be capable of affecting the character */ if (!trf_has(trap->kind->flags, TRF_TRAP)) continue; if (trap->timeout) continue; /* Disturb the player */ disturb(player, 0); /* Give a message */ if (trap->kind->msg) msg(trap->kind->msg); /* Test for save due to flag */ for (flag = of_next(trap->kind->save_flags, FLAG_START); flag != FLAG_END; flag = of_next(trap->kind->save_flags, flag + 1)) if (player_of_has(player, flag)) { saved = true; equip_learn_flag(player, flag); } /* Test for save due to armor */ if (trf_has(trap->kind->flags, TRF_SAVE_ARMOR) && !trap_check_hit(125)) saved = true; /* Test for save due to saving throw */ if (trf_has(trap->kind->flags, TRF_SAVE_THROW) && (randint0(100) < player->state.skills[SKILL_SAVE])) saved = true; /* Save, or fire off the trap */ if (saved) { if (trap->kind->msg_good) msg(trap->kind->msg_good); } else { if (trap->kind->msg_bad) msg(trap->kind->msg_bad); effect = trap->kind->effect; effect_do(effect, source_trap(trap), NULL, &ident, false, 0, 0, 0); /* Do any extra effects */ if (trap->kind->effect_xtra && one_in_(2)) { if (trap->kind->msg_xtra) msg(trap->kind->msg_xtra); effect = trap->kind->effect_xtra; effect_do(effect, source_trap(trap), NULL, &ident, false, 0, 0, 0); } } /* Some traps drop you a dungeon level */ if (trf_has(trap->kind->flags, TRF_DOWN)) dungeon_change_level(player, dungeon_get_next_level(player->depth, 1)); /* Some traps drop you onto them */ if (trf_has(trap->kind->flags, TRF_PIT)) monster_swap(player->py, player->px, trap->fy, trap->fx); /* Some traps disappear after activating, all have a chance to */ if (trf_has(trap->kind->flags, TRF_ONETIME) || one_in_(3)) { square_destroy_trap(cave, y, x); square_forget(cave, y, x); } /* Trap may have gone */ if (!square_trap(cave, y, x)) break; /* Trap becomes visible (always XXX) */ trf_on(trap->flags, TRF_VISIBLE); square_memorize(cave, y, x); } /* Verify traps (remove marker if appropriate) */ (void)square_verify_trap(cave, y, x, 0); }