/** * Perform the basic "tunnel" command * * Assumes that no monster is blocking the destination. * Uses twall() (above) to do all "terrain feature changing". * Returns true if repeated commands may continue. */ static bool do_cmd_tunnel_aux(int y, int x) { bool more = false; int digging_chances[DIGGING_MAX]; bool okay = false; bool gold = square_hasgoldvein(cave, y, x); bool rubble = square_isrubble(cave, y, x); /* Verify legality */ if (!do_cmd_tunnel_test(y, x)) return (false); calc_digging_chances(&player->state, digging_chances); /* Do we succeed? */ okay = (digging_chances[square_digging(cave, y, x) - 1] > randint0(1600)); /* Success */ if (okay && twall(y, x)) { /* Rubble is a special case - could be handled more generally NRM */ if (rubble) { /* Message */ msg("You have removed the rubble."); /* Place an object (except in town) */ if ((randint0(100) < 10) && player->depth) { /* Create a simple object */ place_object(cave, y, x, player->depth, false, false, ORIGIN_RUBBLE, 0); /* Observe the new object */ if (!ignore_item_ok(square_object(cave, y, x)) && square_isseen(cave, y, x)) msg("You have found something!"); } } else if (gold) { /* Found treasure */ place_gold(cave, y, x, player->depth, ORIGIN_FLOOR); msg("You have found something!"); } else { msg("You have finished the tunnel."); } } else { /* Failure, continue digging */ if (rubble) msg("You dig in the rubble."); else msg("You tunnel into the %s.", square_apparent_name(cave, player, y, x)); more = true; if (square_issecretdoor(cave, y, x)) /* Occasional Search XXX XXX */ if (randint0(100) < 25) search(false); } /* Result */ return (more); }
/** * Determine if a given grid may be "walked" */ static bool do_cmd_walk_test(int y, int x) { int m_idx = cave->squares[y][x].mon; struct monster *mon = cave_monster(cave, m_idx); /* Allow attack on visible monsters if unafraid */ if (m_idx > 0 && mflag_has(mon->mflag, MFLAG_VISIBLE) && !is_mimicking(mon)) { /* Handle player fear */ if (player_of_has(player, OF_AFRAID)) { /* Extract monster name (or "it") */ char m_name[80]; monster_desc(m_name, sizeof(m_name), mon, MDESC_DEFAULT); /* Message */ msgt(MSG_AFRAID, "You are too afraid to attack %s!", m_name); /* Nope */ return (false); } return (true); } /* If we don't know the grid, allow attempts to walk into it */ if (!square_isknown(cave, y, x)) return true; /* Require open space */ if (!square_ispassable(cave, y, x)) { if (square_isrubble(cave, y, x)) /* Rubble */ msgt(MSG_HITWALL, "There is a pile of rubble in the way!"); else if (square_iscloseddoor(cave, y, x)) /* Door */ return true; else if (square_isbright(cave, y, x)) /* Lava */ msgt(MSG_HITWALL, "The heat of the lava turns you away!"); else /* Wall */ msgt(MSG_HITWALL, "There is a wall in the way!"); /* Cancel repeat */ disturb(player, 0); /* Nope */ return (false); } /* Okay */ return (true); }
void square_destroy_rubble(struct chunk *c, int y, int x) { assert(square_isrubble(c, y, x)); square_set_feat(c, y, x, FEAT_FLOOR); }
/** * True if the square can be dug: this includes rubble and non-permanent walls. */ bool square_isdiggable(struct chunk *c, int y, int x) { return (square_ismineral(c, y, x) || square_issecretdoor(c, y, x) || square_isrubble(c, y, x)); }
/** * 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; }
/* Destroy walls (and doors) */ static void project_feature_handler_KILL_WALL(project_feature_handler_context_t *context) { const int x = context->x; const int y = context->y; /* Non-walls (etc) */ if (square_ispassable(cave, y, x)) return; /* Permanent walls */ if (square_isperm(cave, y, x)) return; /* Different treatment for different walls */ if (square_iswall(cave, y, x) && !square_hasgoldvein(cave, y, x)) { /* Message */ if (square_isseen(cave, y, x)) { msg("The wall turns into mud!"); context->obvious = true; /* Forget the wall */ square_forget(cave, y, x); } /* Destroy the wall */ square_destroy_wall(cave, y, x); } else if (square_iswall(cave, y, x) && square_hasgoldvein(cave, y, x)) { /* Message */ if (square_isseen(cave, y, x)) { msg("The vein turns into mud!"); msg("You have found something!"); context->obvious = true; /* Forget the wall */ square_forget(cave, y, x); } /* Destroy the wall */ square_destroy_wall(cave, y, x); /* Place some gold */ place_gold(cave, y, x, player->depth, ORIGIN_FLOOR); } else if (square_ismagma(cave, y, x) || square_isquartz(cave, y, x)) { /* Message */ if (square_isseen(cave, y, x)) { msg("The vein turns into mud!"); context->obvious = true; /* Forget the wall */ square_forget(cave, y, x); } /* Destroy the wall */ square_destroy_wall(cave, y, x); } else if (square_isrubble(cave, y, x)) { /* Message */ if (square_isseen(cave, y, x)) { msg("The rubble turns into mud!"); context->obvious = true; /* Forget the wall */ square_forget(cave, y, x); } /* Destroy the rubble */ square_destroy_rubble(cave, y, x); /* Hack -- place an object */ if (randint0(100) < 10){ if (square_isseen(cave, y, x)) { msg("There was something buried in the rubble!"); context->obvious = true; } place_object(cave, y, x, player->depth, false, false, ORIGIN_RUBBLE, 0); } } else if (square_isdoor(cave, y, x)) { /* Hack -- special message */ if (square_isseen(cave, y, x)) { msg("The door turns into mud!"); context->obvious = true; /* Forget the wall */ square_forget(cave, y, x); } /* Destroy the feature */ square_destroy_door(cave, y, x); } /* Update the visuals */ player->upkeep->update |= (PU_UPDATE_VIEW | PU_MONSTERS); /* Fully update the flow */ player->upkeep->update |= (PU_FORGET_FLOW | PU_UPDATE_FLOW); }
/** * 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; }