/** * Places a random trap at the given location. * * The location must be a legal, naked, floor grid. * * Note that all traps start out as "invisible" and "untyped", and then * when they are "discovered" (by detecting them or setting them off), * the trap is "instantiated" as a visible, "typed", trap. */ extern void place_trap(int y, int x) { int d, grass = 0, floor = 0; feature_type *f_ptr = &f_info[cave_feat[y][x]]; /* Paranoia */ if (!in_bounds(y, x)) return; /* Hack - handle trees */ if ((tf_has(f_ptr->flags, TF_TREE)) && (cave_o_idx[y][x] == 0) && (cave_m_idx[y][x] >= 0)) { if (cave_feat[y][x] == FEAT_TREE) cave_set_feat(y, x, FEAT_TREE_INVIS); else if (cave_feat[y][x] == FEAT_TREE2) cave_set_feat(y, x, FEAT_TREE2_INVIS); return; } /* Require empty, clean, floor grid */ if (!cave_naked_bold(y, x)) return; /* Adjacent grids vote for grass or floor */ for (d = 0; d < 8; d++) { if (cave_feat[y + ddy_ddd[d]][x + ddx_ddd[d]] == FEAT_FLOOR) floor++; else if (cave_feat[y + ddy_ddd[d]][x + ddx_ddd[d]] == FEAT_GRASS) grass++; } /* Place an invisible trap */ if (grass > floor) cave_set_feat(y, x, FEAT_GRASS_INVIS); else cave_set_feat(y, x, FEAT_INVIS); }
/** * Bring up player actions */ void show_player(void) { int i, j, fy, fx; int adj_grid[9]; bool exist_rock = FALSE; bool exist_door = FALSE; bool exist_open_door = FALSE; bool exist_trap = FALSE; bool exist_mtrap = FALSE; bool exist_floor = FALSE; bool exist_monster = FALSE; feature_type *f_ptr; /* No commands yet */ poss = 0; /* Get surroundings */ get_feats(adj_grid); /* Analyze surroundings */ for (i = 0; i < 8; i++) { int yy = p_ptr->py + ddy_ddd[i]; int xx = p_ptr->px + ddx_ddd[i]; f_ptr = &f_info[adj_grid[i]]; if (cave_visible_trap(yy, xx)) exist_trap = TRUE; if (tf_has(f_ptr->flags, TF_DOOR_CLOSED)) exist_door = TRUE; if (tf_has(f_ptr->flags, TF_ROCK)) exist_rock = TRUE; if (cave_monster_trap(yy, xx)) exist_mtrap = TRUE; if (adj_grid[i] == FEAT_OPEN) exist_open_door = TRUE; if (cave_naked_bold(yy, xx)) exist_floor = TRUE; if (cave_m_idx[yy][xx] > 0) exist_monster = TRUE; } /* In a web? */ if (cave_web(p_ptr->py, p_ptr->px)) exist_trap = TRUE; /* Alter a grid */ if (exist_trap || exist_door || exist_rock || exist_mtrap || exist_open_door || count_chests(&fy, &fx, TRUE) || count_chests(&fy, &fx, FALSE) || (player_has(PF_TRAP) && exist_floor) || (player_has(PF_STEAL) && exist_monster && (!SCHANGE))) { comm[poss] = '+'; comm_code[poss] = CMD_ALTER; comm_descr[poss++] = "Alter"; } /* Dig a tunnel */ if (exist_door || exist_rock) { comm[poss] = 'T'; comm_code[poss] = CMD_TUNNEL; comm_descr[poss++] = "Tunnel"; } /* Begin Running -- Arg is Max Distance */ { comm[poss] = '.'; comm_code[poss] = CMD_RUN; comm_descr[poss++] = "Run"; } /* Hold still for a turn. Pickup objects if auto-pickup is true. */ { comm[poss] = ','; comm_code[poss] = CMD_HOLD; comm_descr[poss++] = "Stand still"; } /* Pick up objects. */ if (cave_o_idx[p_ptr->py][p_ptr->px]) { comm[poss] = 'g'; comm_code[poss] = CMD_PICKUP; comm_descr[poss++] = "Pick up"; } /* Rest -- Arg is time */ { comm[poss] = 'R'; comm_code[poss] = CMD_REST; comm_descr[poss++] = "Rest"; } /* Search for traps/doors */ { comm[poss] = 's'; comm_code[poss] = CMD_SEARCH; comm_descr[poss++] = "Search"; } /* Look around */ { comm[poss] = 'l'; comm_code[poss] = CMD_NULL; comm_descr[poss++] = "Look"; } /* Scroll the map */ { comm[poss] = 'L'; comm_code[poss] = CMD_NULL; comm_descr[poss++] = "Scroll map"; } /* Show the map */ { comm[poss] = 'M'; comm_code[poss] = CMD_NULL; comm_descr[poss++] = "Level map"; } /* Knowledge */ { comm[poss] = '~'; comm_code[poss] = CMD_NULL; comm_descr[poss++] = "Knowledge"; } /* Options */ { comm[poss] = '='; comm_code[poss] = CMD_NULL; comm_descr[poss++] = "Options"; } /* Toggle search mode */ { comm[poss] = 'S'; comm_code[poss] = CMD_TOGGLE_SEARCH; comm_descr[poss++] = "Toggle searching"; } /* Go up staircase */ if ((adj_grid[8] == FEAT_LESS) || ((adj_grid[8] >= FEAT_LESS_NORTH) && (!(adj_grid[8] % 2)))) { comm[poss] = '<'; comm_code[poss] = CMD_GO_UP; comm_descr[poss++] = "Take stair/path"; } /* Go down staircase */ if ((adj_grid[8] == FEAT_MORE) || ((adj_grid[8] >= FEAT_LESS_NORTH) && (adj_grid[8] % 2))) { comm[poss] = '>'; comm_code[poss] = CMD_GO_DOWN; comm_descr[poss++] = "Take stair/path"; } /* Open a door or chest */ if (exist_door || count_chests(&fy, &fx, TRUE) || count_chests(&fy, &fx, FALSE)) { comm[poss] = 'o'; comm_code[poss] = CMD_OPEN; comm_descr[poss++] = "Open"; } /* Close a door */ if (exist_open_door) { comm[poss] = 'c'; comm_code[poss] = CMD_CLOSE; comm_descr[poss++] = "Close"; } /* Jam a door with spikes */ if (exist_door) { comm[poss] = 'j'; comm_code[poss] = CMD_JAM; comm_descr[poss++] = "Jam"; } /* Bash a door */ if (exist_door) { comm[poss] = 'B'; comm_code[poss] = CMD_BASH; comm_descr[poss++] = "Bash"; } /* Disarm a trap or chest */ if (count_chests(&fy, &fx, TRUE) || exist_trap || exist_mtrap) { comm[poss] = 'D'; comm_code[poss] = CMD_DISARM; comm_descr[poss++] = "Disarm"; } /* Shapechange */ if ((SCHANGE) || (player_has(PF_BEARSKIN))) { comm[poss] = ']'; comm_code[poss] = CMD_NULL; comm_descr[poss++] = "Shapechange"; } /* Save screen */ screen_save(); /* Prompt */ put_str("Choose a command, or ESC:", 0, 0); /* Hack - delete exact graphics rows */ if (tile_height > 1) { j = poss + 1; while ((j % tile_height) && (j <= SCREEN_ROWS)) prt("", ++j, 0); } /* Get a choice */ (void) show_cmd_menu(FALSE); /* Load screen */ screen_load(); }
extern void get_chamber_monsters(int y1, int x1, int y2, int x2) { bool dummy; int i, y, x; s16b monsters_left, depth; char symbol; /* Description of monsters in room */ char *name; /* Get a legal depth. */ depth = p_ptr->danger + randint0(11) - 5; if (depth > 60) depth = 60; if (depth < 5) depth = 5; /* Choose a monster type, using that depth. */ symbol = mon_symbol_at_depth[depth / 5 - 1][randint0(13)]; /* Allow (slightly) tougher monsters. */ depth = p_ptr->danger + (p_ptr->danger < 60 ? p_ptr->danger / 12 : 5); /* Set monster generation restrictions. Describe the monsters. */ name = mon_restrict(symbol, (byte) depth, &dummy, TRUE); /* A default description probably means trouble, so stop. */ if (streq(name, "misc") || !name[0]) return; /* Build the monster probability table. */ if (!get_mon_num(depth)) return; /* No normal monsters. */ generate_mark(y1, x1, y2, x2, CAVE_TEMP); /* Usually, we want 35 monsters. */ monsters_left = 35; /* Fewer monsters near the surface. */ if (p_ptr->danger < 45) monsters_left = 5 + 2 * p_ptr->danger / 3; /* More monsters of kinds that tend to be weak. */ if (strstr("abciBCFKRS", d_char_req)) monsters_left += 15; /* Place the monsters. */ for (i = 0; i < 300; i++) { /* Check for early completion. */ if (!monsters_left) break; /* Pick a random in-room square. */ y = y1 + randint0(1 + ABS(y2 - y1)); x = x1 + randint0(1 + ABS(x2 - x1)); /* Require a floor square with no monster in it already. */ if (!cave_naked_bold(y, x)) continue; /* Place a single monster. Sleeping 2/3rds of the time. */ place_monster_aux(y, x, get_mon_num_quick(depth), (randint0(3) != 0), FALSE); /* One less monster to place. */ monsters_left--; } /* Remove our restrictions. */ (void) mon_restrict('\0', (byte) depth, &dummy, FALSE); /* Describe */ if (OPT(cheat_room)) { /* Room type */ msg("Room of chambers (%s)", name); } }
/** * Returns co-ordinates for the player. Player prefers to be near * walls, because large open spaces are dangerous. */ void new_player_spot(void) { int i = 0; int y, x; feature_type *f_ptr; /* * Check stored stair locations, then search at random. */ while (TRUE) { i++; /* Scan stored locations first. */ if (i < dun->stair_n) { /* Get location */ y = dun->stair[i].y; x = dun->stair[i].x; /* Require exactly three adjacent walls */ if (next_to_walls(y, x) != 3) continue; /* If character starts on stairs, ... */ if (!OPT(adult_no_stairs) || !p_ptr->depth) { /* Accept stairs going the right way or floors. */ if (p_ptr->create_stair) { /* Accept correct stairs */ if (cave_feat[y][x] == p_ptr->create_stair) break; /* Accept floors, build correct stairs. */ f_ptr = &f_info[cave_feat[y][x]]; if (cave_naked_bold(y, x) && tf_has(f_ptr->flags, TF_FLOOR)) { cave_set_feat(y, x, p_ptr->create_stair); break; } } } /* If character doesn't start on stairs, ... */ else { /* Accept only "naked" floor grids */ f_ptr = &f_info[cave_feat[y][x]]; if (cave_naked_bold(y, x) && tf_has(f_ptr->flags, TF_FLOOR)) break; } } /* Then, search at random */ else { /* Pick a random grid */ y = randint0(DUNGEON_HGT); x = randint0(DUNGEON_WID); /* Refuse to start on anti-teleport (vault) grids */ if (cave_has(cave_info[y][x], CAVE_ICKY)) continue; /* Must be a "naked" floor grid */ f_ptr = &f_info[cave_feat[y][x]]; if (!(cave_naked_bold(y, x) && tf_has(f_ptr->flags, TF_FLOOR))) continue; /* Player prefers to be near walls. */ if (i < 300 && (next_to_walls(y, x) < 2)) continue; else if (i < 600 && (next_to_walls(y, x) < 1)) continue; /* Success */ break; } } /* Place the player */ player_place(y, x); }
/** * Allocates some objects (using "place" and "type") */ void alloc_object(int set, int typ, int num) { int y, x, k; feature_type *f_ptr; /* Place some objects */ for (k = 0; k < num; k++) { /* Pick a "legal" spot */ while (TRUE) { bool room; /* Location */ y = randint0(DUNGEON_HGT); x = randint0(DUNGEON_WID); f_ptr = &f_info[cave_feat[y][x]]; /* Paranoia - keep objects out of the outer walls */ if (!in_bounds_fully(y, x)) continue; /* Require "naked" floor grid */ f_ptr = &f_info[cave_feat[y][x]]; if (!(cave_naked_bold(y, x) && tf_has(f_ptr->flags, TF_FLOOR))) continue; /* Check for "room" */ room = cave_has(cave_info[y][x], CAVE_ROOM) ? TRUE : FALSE; /* Require corridor? */ if ((set == ALLOC_SET_CORR) && room) continue; /* Require room? */ if ((set == ALLOC_SET_ROOM) && !room) continue; /* Accept it */ break; } /* Place something */ switch (typ) { case ALLOC_TYP_RUBBLE: { place_rubble(y, x); break; } case ALLOC_TYP_TRAP: { place_trap(y, x, -1, p_ptr->depth); break; } case ALLOC_TYP_GOLD: { place_gold(y, x); break; } case ALLOC_TYP_OBJECT: { place_object(y, x, FALSE, FALSE, FALSE); break; } } } }
/** * Places some staircases near walls */ void alloc_stairs(int feat, int num, int walls) { int y, x, i, j; feature_type *f_ptr; bool no_down_shaft = (!stage_map[stage_map[p_ptr->stage][DOWN]][DOWN] || is_quest(stage_map[p_ptr->stage][DOWN]) || is_quest(p_ptr->stage)); bool no_up_shaft = (!stage_map[stage_map[p_ptr->stage][UP]][UP]); bool morgy = is_quest(p_ptr->stage) && stage_map[p_ptr->stage][DEPTH] == 100; /* Place "num" stairs */ for (i = 0; i < num; i++) { /* Try hard to place the stair */ for (j = 0; j < 3000; j++) { /* Cut some slack if necessary. */ if ((j > dun->stair_n) && (walls > 2)) walls = 2; if ((j > 1000) && (walls > 1)) walls = 1; if (j > 2000) walls = 0; /* Use the stored stair locations first. */ if (j < dun->stair_n) { y = dun->stair[j].y; x = dun->stair[j].x; } /* Then, search at random. */ else { /* Pick a random grid */ y = randint0(DUNGEON_HGT); x = randint0(DUNGEON_WID); } /* Require "naked" floor grid */ f_ptr = &f_info[cave_feat[y][x]]; if (!(cave_naked_bold(y, x) && tf_has(f_ptr->flags, TF_FLOOR))) continue; /* Require a certain number of adjacent walls */ if (next_to_walls(y, x) < walls) continue; /* If we've asked for a shaft and they're forbidden, fail */ if (no_down_shaft && (feat == FEAT_MORE_SHAFT)) return; if (no_up_shaft && (feat == FEAT_LESS_SHAFT)) return; /* Town or no way up -- must go down */ if ((!p_ptr->depth) || (!stage_map[p_ptr->stage][UP])) { /* Clear previous contents, add down stairs */ if (feat != FEAT_MORE_SHAFT) cave_set_feat(y, x, FEAT_MORE); } /* Bottom of dungeon, Morgoth or underworld -- must go up */ else if ((!stage_map[p_ptr->stage][DOWN]) || underworld || morgy) { /* Clear previous contents, add up stairs */ if (feat != FEAT_LESS_SHAFT) cave_set_feat(y, x, FEAT_LESS); } /* Requested type */ else { /* Clear previous contents, add stairs */ cave_set_feat(y, x, feat); } /* Finished with this staircase. */ break; } } }
/* * Manipulate an adjacent grid in some way * * Attack monsters, tunnel through walls, disarm traps, open doors, * or, for rogues, set traps and steal money. * * This command must always take energy, to prevent free detection * of invisible monsters. * * The "semantics" of this command must be chosen before the player * is confused, and it must be verified against the new grid. */ void do_cmd_alter(void) { int py = p_ptr->py; int px = p_ptr->px; int y, x, dir; int feat; bool did_nothing = TRUE; bool more = FALSE; monster_type *m_ptr; /* Get a direction */ if (!get_rep_dir(&dir)) return; /* Get location */ y = py + ddy[dir]; x = px + ddx[dir]; /* Original feature */ feat = cave_feat[y][x]; /* Must have knowledge to know feature XXX XXX */ if (!(cave_info[y][x] & (CAVE_MARK))) feat = FEAT_NONE; /* Take a turn */ p_ptr->energy_use = 100; /* Apply confusion */ if (confuse_dir(&dir)) { /* Get location */ y = py + ddy[dir]; x = px + ddx[dir]; } /* Allow repeated command */ if (p_ptr->command_arg) { /* Set repeat count */ p_ptr->command_rep = p_ptr->command_arg - 1; /* Redraw the state */ p_ptr->redraw |= (PR_STATE); /* Cancel the arg */ p_ptr->command_arg = 0; } /* If a monster is present, and visible, Rogues may steal from it. * Otherwise, the player will simply attack. -LM- */ if (cave_m_idx[y][x] > 0) { if ((check_ability(SP_STEAL)) && (!SCHANGE)) { m_ptr = &m_list[cave_m_idx[y][x]]; if (m_ptr->ml) py_steal(y, x); else py_attack(y, x); } else py_attack(y, x); did_nothing = FALSE; } /* * Some players can set traps. Total number is checked in py_set_trap. */ else if ((check_ability(SP_TRAP)) && (cave_naked_bold(y, x))) { py_set_trap(y, x); did_nothing = FALSE; } /* Disarm advanced monster traps */ else if (feat > FEAT_MTRAP_HEAD) { /* Disarm */ more = do_cmd_disarm_aux(y, x); } /* Modify basic monster traps */ else if (feat == FEAT_MTRAP_HEAD) { /* Modify */ py_modify_trap(y, x); } /* Tunnel through walls */ else if (feat >= FEAT_SECRET) { /* Tunnel */ more = do_cmd_tunnel_aux(y, x); } /* Bash jammed doors */ else if (feat >= FEAT_DOOR_HEAD + 0x08) { /* Bash */ more = do_cmd_bash_aux(y, x); } /* Open closed doors */ else if (feat >= FEAT_DOOR_HEAD) { /* Close */ more = do_cmd_open_aux(y, x); } /* Disarm traps */ else if (feat >= FEAT_TRAP_HEAD) { /* Disarm */ more = do_cmd_disarm_aux(y, x); } /* Oops */ else if (did_nothing) { /* Oops */ msg_print("You spin around."); } /* Cancel repetition unless we can continue */ if (!more) disturb(0, 0); }
/** * Generate the "consistent" town features, and place the player * * Hack -- play with the R.N.G. to always yield the same town * layout, including the size and shape of the buildings, the * locations of the doorways, and the location of the stairs. */ static void town_gen_hack(void) { int i, y, x, k, n, py = 1, px = 1; int qy = DUNGEON_HGT / 3; int qx = DUNGEON_WID / 3; int stage = p_ptr->stage; int last_stage = p_ptr->last_stage; int rooms[MAX_STORES_BIG + 1]; bool place = FALSE; bool major = FALSE; /* Hack -- Use the "simple" RNG */ Rand_quick = TRUE; /* Hack -- Induce consistent town layout */ for (i = 0; i < 10; i++) if (stage == towns[i]) Rand_value = seed_town[i]; if (OPT(adult_dungeon)) Rand_value = seed_town[0]; /* Set major town flag if necessary */ if ((stage > 150) || OPT(adult_dungeon)) major = TRUE; /* Hack - reduce width for minor towns */ if (!major) qx /= 2; /* Prepare an Array of "remaining stores", and count them */ if (major) for (n = 0; n < MAX_STORES_BIG; n++) rooms[n] = n; else { rooms[0] = 9; rooms[1] = 3; rooms[2] = 4; rooms[3] = 7; n = 4; } if (OPT(adult_dungeon)) rooms[n++] = 9; /* No stores for ironmen away from home */ if ((!OPT(adult_ironman)) || (p_ptr->stage == p_ptr->home)) { /* Place two rows of stores */ for (y = 0; y < 2; y++) { /* Place two, four or five stores per row */ for (x = 0; x < (OPT(adult_dungeon) ? 5 : 4); x++) { /* Pick a random unplaced store */ k = ((n <= 1) ? 0 : randint0(n)); /* Build that store at the proper location */ build_store(rooms[k], y, x, stage); /* Shift the stores down, remove one store */ rooms[k] = rooms[--n]; /* Cut short if a minor town */ if ((x > 0) && !major) break; } } /* Hack -- Build the 9th store. Taken from Zangband */ if (major && !OPT(adult_dungeon)) build_store(rooms[0], randint0(2), 4, stage); } if (OPT(adult_dungeon)) { /* Place the stairs */ while (TRUE) { /* Pick a location at least "three" from the outer walls */ y = 1 + rand_range(3, DUNGEON_HGT / 3 - 4); x = 1 + rand_range(3, DUNGEON_WID / 3 - 4); /* Require a "naked" floor grid */ if (cave_naked_bold(y, x)) break; } /* Clear previous contents, add down stairs */ cave_set_feat(y, x, FEAT_MORE); /* Place the player */ player_place(y, x); } else { /* Place the paths */ for (n = 2; n < 6; n++) { /* Pick a path direction for the player if not obvious */ if (((!last_stage) || (last_stage == 255)) && (stage_map[stage][n])) last_stage = stage_map[stage][n]; /* Where did we come from? */ if ((last_stage) && (last_stage == stage_map[stage][n])) place = TRUE; /* Pick a location at least "three" from the corners */ y = 1 + rand_range(3, qy - 4); x = 1 + rand_range(3, qx - 4); /* Shove it to the wall, place the path */ switch (n) { case NORTH: { y = 1 + 1; if (stage_map[stage][n]) cave_set_feat(y, x, FEAT_MORE_NORTH); break; } case EAST: { x = 1 + qx - 2; if (stage_map[stage][n]) cave_set_feat(y, x, FEAT_MORE_EAST); break; } case SOUTH: { y = 1 + qy - 2; if (stage_map[stage][n]) cave_set_feat(y, x, FEAT_MORE_SOUTH); break; } case WEST: { x = 1 + 1; if (stage_map[stage][n]) cave_set_feat(y, x, FEAT_MORE_WEST); } } if (place) { py = y; px = x; place = FALSE; } } /* Place the player */ player_place(py, px); } /* Hack -- use the "complex" RNG */ Rand_quick = FALSE; }