/** * Perform the basic "disarm" command * * Assume there is no monster blocking the destination * * Returns true if repeated commands may continue */ static bool do_cmd_disarm_aux(int y, int x) { int skill, power, chance; struct trap *trap = cave->squares[y][x].trap; bool more = false; /* Verify legality */ if (!do_cmd_disarm_test(y, x)) return (false); /* Choose first player trap */ while (trap) { if (trf_has(trap->flags, TRF_TRAP)) break; trap = trap->next; } if (!trap) return false; /* Get the base disarming skill */ if (trf_has(trap->flags, TRF_MAGICAL)) skill = player->state.skills[SKILL_DISARM_MAGIC]; else skill = player->state.skills[SKILL_DISARM_PHYS]; /* Penalize some conditions */ if (player->timed[TMD_BLIND] || no_light() || player->timed[TMD_CONFUSED] || player->timed[TMD_IMAGE]) skill = skill / 10; /* Extract trap power */ power = cave->depth / 5; /* Extract the percentage success */ chance = skill - power; /* Always have a small chance of success */ if (chance < 2) chance = 2; /* Two chances - one to disarm, one not to set the trap off */ if (randint0(100) < chance) { msgt(MSG_DISARM, "You have disarmed the %s.", trap->kind->name); player_exp_gain(player, power); /* Trap is gone */ square_forget(cave, y, x); square_destroy_trap(cave, y, x); } else if (randint0(100) < chance) { event_signal(EVENT_INPUT_FLUSH); msg("You failed to disarm the %s.", trap->kind->name); /* Player can try again */ more = true; } else { msg("You set off the %s!", trap->kind->name); hit_trap(y, x); } /* Result */ return (more); }
/** * Set the terrain type for a square. * * This should be the only function that sets terrain, apart from the savefile * loading code. */ void square_set_feat(struct chunk *c, int y, int x, int feat) { int current_feat = c->squares[y][x].feat; assert(c); assert(y >= 0 && y < c->height); assert(x >= 0 && x < c->width); /* Track changes */ if (current_feat) c->feat_count[current_feat]--; if (feat) c->feat_count[feat]++; /* Make the change */ c->squares[y][x].feat = feat; /* Make the new terrain feel at home */ if (character_dungeon) { /* Remove traps if necessary */ if (!square_player_trap_allowed(c, y, x)) square_destroy_trap(c, y, x); square_note_spot(c, y, x); square_light_spot(c, y, x); } else { /* Make sure no incorrect wall flags set for dungeon generation */ sqinfo_off(c->squares[y][x].info, SQUARE_WALL_INNER); sqinfo_off(c->squares[y][x].info, SQUARE_WALL_OUTER); sqinfo_off(c->squares[y][x].info, SQUARE_WALL_SOLID); } }
/* Destroy Traps (and Locks) */ static void project_feature_handler_KILL_TRAP(project_feature_handler_context_t *context) { const int x = context->x; const int y = context->y; /* Reveal secret doors */ if (square_issecretdoor(cave, y, x)) { place_closed_door(cave, y, x); /* Check line of sight */ if (square_isseen(cave, y, x)) context->obvious = true; } /* Destroy traps, unlock doors */ if (square_istrap(cave, y, x)) { /* Check line of sight */ if (square_isview(cave, y, x)) { msg("There is a bright flash of light!"); context->obvious = true; } /* Destroy the trap */ square_destroy_trap(cave, y, x); } else if (square_islockeddoor(cave, y, x)) { /* Unlock the door */ square_unlock_door(cave, y, x); /* Check line of sound */ if (square_isview(cave, y, x)) { msg("Click!"); context->obvious = true; } } }
/* Destroy Doors (and traps) */ static void project_feature_handler_KILL_DOOR(project_feature_handler_context_t *context) { const int x = context->x; const int y = context->y; /* Destroy all doors and traps */ if (square_isplayertrap(cave, y, x) || square_isdoor(cave, y, x)) { /* Check line of sight */ if (square_isview(cave, y, x)) { /* Message */ msg("There is a bright flash of light!"); context->obvious = true; /* Visibility change */ if (square_isdoor(cave, y, x)) player->upkeep->update |= (PU_UPDATE_VIEW | PU_MONSTERS); /* Forget the door */ square_forget(cave, y, x); } /* Destroy the feature */ if (square_isdoor(cave, y, x)) square_destroy_door(cave, y, x); else square_destroy_trap(cave, y, x); } }
void square_add_stairs(struct chunk *c, int y, int x, int depth) { int down = randint0(100) < 50; if (depth == 0) down = 1; else if (is_quest(depth) || depth >= z_info->max_depth - 1) down = 0; /* Remove any traps */ square_destroy_trap(c, y, x); square_set_feat(c, y, x, down ? FEAT_MORE : FEAT_LESS); }
/** * Perform the basic "disarm" command * * Assume there is no monster blocking the destination * * Returns true if repeated commands may continue */ static bool do_cmd_disarm_aux(int y, int x) { int i, j, power; struct trap *trap = cave->squares[y][x].trap; bool more = false; /* Verify legality */ if (!do_cmd_disarm_test(y, x)) return (false); /* Choose first player trap */ while (trap) { if (trf_has(trap->flags, TRF_TRAP)) break; trap = trap->next; } if (!trap) return false; /* Get the "disarm" factor */ i = player->state.skills[SKILL_DISARM]; /* 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; /* XXX XXX XXX Variable power? */ /* Extract trap "power" */ power = 5; /* Extract the difficulty */ j = i - power; /* Always have a small chance of success */ if (j < 2) j = 2; /* Success */ if (randint0(100) < j) { /* Message */ msgt(MSG_DISARM, "You have disarmed the %s.", trap->kind->name); /* Reward */ player_exp_gain(player, power); /* Forget the trap */ square_forget(cave, y, x); /* Remove the trap */ square_destroy_trap(cave, y, x); } else if ((i > 5) && (randint1(i) > 5)) { /* Failure -- Keep trying */ event_signal(EVENT_INPUT_FLUSH); msg("You failed to disarm the %s.", trap->kind->name); more = true; } else { /* Failure -- Set off the trap */ msg("You set off the %s!", trap->kind->name); hit_trap(y, x); } /* Result */ return (more); }
/** * 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); }