/** * Create up to 'num' objects near the given coordinates in a vault. * \param c the current chunk * \param y co-ordinates * \param x co-ordinates * \param depth geneeration depth * \param num number of objects */ void vault_objects(struct chunk *c, int y, int x, int depth, int num) { int i, j, k; /* Attempt to place 'num' objects */ for (; num > 0; --num) { /* Try up to 11 spots looking for empty space */ for (i = 0; i < 11; ++i) { /* Pick a random location */ find_nearby_grid(c, &j, y, 2, &k, x, 3); /* Require "clean" floor space */ if (!square_canputitem(c, j, k)) continue; /* Place an item or gold */ if (randint0(100) < 75) place_object(c, j, k, depth, false, false, ORIGIN_SPECIAL, 0); else place_gold(c, j, k, depth, ORIGIN_VAULT); /* Placement accomplished */ break; } } }
/** * Allocates a single random object in the dungeon. * \param c the current chunk * \param set where the entity is placed (corridor, room or either) * \param typ what is placed (rubble, trap, gold, item) * \param depth generation depth * \param origin item origin (if appropriate) * * 'set' controls where the object is placed (corridor, room, either). * 'typ' conrols the kind of object (rubble, trap, gold, item). */ bool alloc_object(struct chunk *c, int set, int typ, int depth, byte origin) { int x = 0, y = 0; int tries = 0; /* Pick a "legal" spot */ while (tries < 2000) { tries++; find_empty(c, &y, &x); /* If we are ok with a corridor and we're in one, we're done */ if (set & SET_CORR && !square_isroom(c, y, x)) break; /* If we are ok with a room and we're in one, we're done */ if (set & SET_ROOM && square_isroom(c, y, x)) break; } if (tries == 2000) return false; /* Place something */ switch (typ) { case TYP_RUBBLE: place_rubble(c, y, x); break; case TYP_TRAP: place_trap(c, y, x, -1, depth); break; case TYP_GOLD: place_gold(c, y, x, depth, origin); break; case TYP_OBJECT: place_object(c, y, x, depth, false, false, origin, 0); break; case TYP_GOOD: place_object(c, y, x, depth, true, false, origin, 0); break; case TYP_GREAT: place_object(c, y, x, depth, true, true, origin, 0); break; } return true; }
/** * 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); }
/* * Create up to "num" objects near the given coordinates * Only really called by some of the "vault" routines. */ void vault_objects(int y, int x, int num) { int dummy = 0; int i = 0, j = y, k = x; cave_type *c_ptr; /* Attempt to place 'num' objects */ for (; num > 0; --num) { /* Try up to 11 spots looking for empty space */ for (i = 0; i < 11; ++i) { /* Pick a random location */ while (dummy < SAFE_MAX_ATTEMPTS) { j = rand_spread(y, 2); k = rand_spread(x, 3); dummy++; if (!in_bounds(j, k)) continue; break; } if (dummy >= SAFE_MAX_ATTEMPTS) { if (cheat_room) { msg_print("Warning! Could not place vault object!"); } } /* Require "clean" floor space */ c_ptr = &cave[j][k]; if (!is_floor_grid(c_ptr) || c_ptr->o_idx) continue; /* Place an item */ if (randint0(100) < 75) { place_object(j, k, 0L); } /* Place gold */ else { place_gold(j, k); } /* Placement accomplished */ break; } } }
/* * Allocates some objects (using "place" and "type") */ static void alloc_object(int set, int typ, int num) { int y, x, k; int dummy = 0; cave_type *c_ptr = NULL; /* Place some objects */ for (k = 0; k < num; k++) { /* Pick a "legal" spot */ while (dummy < SAFE_MAX_ATTEMPTS) { bool room; dummy++; /* Location */ y = rand_range(min_hgt + 1, max_hgt - 2); x = rand_range(min_wid + 1, max_wid - 2); c_ptr = &cave[y][x]; /* Require "naked" floor grid */ if (!cave_naked_grid(c_ptr)) continue; /* Check for "room" */ room = (c_ptr->info & CAVE_ROOM) ? TRUE : FALSE; /* Require corridor? */ if ((set == ALLOC_SET_CORR) && room) continue; /* Require room? */ if ((set == ALLOC_SET_ROOM) && !room) continue; /* Traps cannot be placed on 'icky' grids (rivers/lakes) */ if ((typ == ALLOC_TYP_TRAP) && (c_ptr->info & CAVE_ICKY)) continue; /* Accept it */ break; } if (dummy >= SAFE_MAX_ATTEMPTS) { if (cheat_room) { msg_print("Warning! Could not place object!"); } return; } /* Place something */ switch (typ) { case ALLOC_TYP_RUBBLE: { c_ptr->feat = FEAT_RUBBLE; break; } case ALLOC_TYP_TRAP: { place_trap(y, x); break; } case ALLOC_TYP_GOLD: { place_gold(y, x); break; } case ALLOC_TYP_OBJECT: { place_object(y, x, FALSE, FALSE); break; } case ALLOC_TYP_INVIS: { /* Create invisible wall */ cave_set_feat(y, x, FEAT_FLOOR); (void)place_field(y, x, FT_WALL_INVIS); break; } } } }
/* * 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; /* Verify legality */ if (!do_cmd_tunnel_test(y, x)) return (FALSE); /* Sound XXX XXX XXX */ /* sound(MSG_DIG); */ /* Titanium */ if (cave_feat[y][x] >= FEAT_PERM_EXTRA) { msg_print("This seems to be permanent rock."); } /* Granite */ else if (cave_feat[y][x] >= FEAT_WALL_EXTRA) { /* Tunnel */ if ((p_ptr->state.skills[SKILL_DIGGING] > 40 + randint0(1600)) && twall(y, x)) { msg_print("You have finished the tunnel."); } /* Keep trying */ else { /* We may continue tunelling */ msg_print("You tunnel into the granite wall."); more = TRUE; } } /* Quartz / Magma */ else if (cave_feat[y][x] >= FEAT_MAGMA) { bool okay = FALSE; bool gold = FALSE; bool hard = FALSE; /* Found gold */ if (cave_feat[y][x] >= FEAT_MAGMA_H) { gold = TRUE; } /* Extract "quartz" flag XXX XXX XXX */ if ((cave_feat[y][x] - FEAT_MAGMA) & 0x01) { hard = TRUE; } /* Quartz */ if (hard) { okay = (p_ptr->state.skills[SKILL_DIGGING] > 20 + randint0(800)); } /* Magma */ else { okay = (p_ptr->state.skills[SKILL_DIGGING] > 10 + randint0(400)); } /* Success */ if (okay && twall(y, x)) { /* Found treasure */ if (gold) { /* Place some gold */ place_gold(y, x, p_ptr->depth); /* Message */ msg_print("You have found something!"); } /* Found nothing */ else { /* Message */ msg_print("You have finished the tunnel."); } } /* Failure (quartz) */ else if (hard) { /* Message, continue digging */ msg_print("You tunnel into the quartz vein."); more = TRUE; } /* Failure (magma) */ else { /* Message, continue digging */ msg_print("You tunnel into the magma vein."); more = TRUE; } } /* Rubble */ else if (cave_feat[y][x] == FEAT_RUBBLE) { /* Remove the rubble */ if ((p_ptr->state.skills[SKILL_DIGGING] > randint0(200)) && twall(y, x)) { /* Message */ msg_print("You have removed the rubble."); /* Hack -- place an object */ if (randint0(100) < 10) { /* Create a simple object */ place_object(y, x, p_ptr->depth, FALSE, FALSE); /* Observe the new object */ if (!squelch_item_ok(&o_list[cave_o_idx[y][x]]) && player_can_see_bold(y, x)) { msg_print("You have found something!"); } } } else { /* Message, keep digging */ msg_print("You dig in the rubble."); more = TRUE; } } /* Secret doors */ else if (cave_feat[y][x] >= FEAT_SECRET) { /* Tunnel */ if ((p_ptr->state.skills[SKILL_DIGGING] > 30 + randint0(1200)) && twall(y, x)) { msg_print("You have finished the tunnel."); } /* Keep trying */ else { /* We may continue tunelling */ msg_print("You tunnel into the granite wall."); more = TRUE; /* Occasional Search XXX XXX */ if (randint0(100) < 25) search(FALSE); } } /* Doors */ else { /* Tunnel */ if ((p_ptr->state.skills[SKILL_DIGGING] > 30 + randint0(1200)) && twall(y, x)) { msg_print("You have finished the tunnel."); } /* Keep trying */ else { /* We may continue tunelling */ msg_print("You tunnel into the door."); more = TRUE; } } /* Result */ return (more); }
/** * 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; } } } }
/* 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); }
/* * Allocates some objects (using "place" and "type") */ static void alloc_object(int set, int typ, int num) { int y = 0, x = 0, k; /* A small level has few objects. */ num = MAX(1, num * cur_hgt * cur_wid / (MAX_HGT*MAX_WID)); /* Diligent players should be encouraged to explore more! */ if (typ == ALLOC_TYP_OBJECT || typ == ALLOC_TYP_GOLD) num = num * (625 + virtue_current(VIRTUE_DILIGENCE)) / 625; for (k = 0; k < num; k++) { object_type forge; int k_idx; if (!_get_loc(set, &x, &y)) { if (cheat_room) msg_print("Warning! Could not place object!"); return; } switch (typ) { case ALLOC_TYP_RUBBLE: place_rubble(y, x); cave[y][x].info &= ~(CAVE_FLOOR); break; case ALLOC_TYP_TRAP: place_trap(y, x); cave[y][x].info &= ~(CAVE_FLOOR); break; case ALLOC_TYP_GOLD: place_gold(y, x); break; case ALLOC_TYP_OBJECT: /* Comment: Monsters drop objects at (ML + DL)/2. In practice, this means that your best drops are just laying on the ground, and this encourages recall scumming for end game resources such as wands of rockets. Note: Vaults are not affected and we want to encourage these! Room templates need some thought ... */ if (base_level > 31) { int n = base_level - 30; object_level = 30 + n/2 + randint1(n/2); } else object_level = base_level; /* paranoia */ place_object(y, x, 0L); object_level = base_level; break; case ALLOC_TYP_FOOD: if (prace_is_(RACE_ENT)) k_idx = lookup_kind(TV_POTION, SV_POTION_WATER); else k_idx = lookup_kind(TV_FOOD, SV_FOOD_RATION); object_prep(&forge, k_idx); obj_make_pile(&forge); drop_near(&forge, -1, y, x); break; case ALLOC_TYP_LIGHT: if (one_in_(3)) k_idx = lookup_kind(TV_FLASK, SV_FLASK_OIL); else k_idx = lookup_kind(TV_LITE, SV_LITE_LANTERN); object_prep(&forge, k_idx); apply_magic(&forge, dun_level, 0); obj_make_pile(&forge); drop_near(&forge, -1, y, x); break; case ALLOC_TYP_RECALL: k_idx = lookup_kind(TV_SCROLL, SV_SCROLL_WORD_OF_RECALL); object_prep(&forge, k_idx); /*obj_make_pile(&forge);*/ drop_near(&forge, -1, y, x); break; case ALLOC_TYP_SKELETON: k_idx = lookup_kind(TV_CORPSE, SV_SKELETON); object_prep(&forge, k_idx); apply_magic(&forge, dun_level, 0); drop_near(&forge, -1, y, x); break; } } }
/* * 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; /* Verify legality */ if (!do_cmd_tunnel_test(y, x)) return (FALSE); /* Sound XXX XXX XXX */ /* sound(MSG_DIG); */ /* Titanium */ if (cave_isperm(cave, y, x)) { msg("This seems to be permanent rock."); } /* Granite */ else if (cave_isrock(cave, y, x)) { /* Tunnel */ if ((p_ptr->state.skills[SKILL_DIGGING] > 40 + randint0(1600)) && twall(y, x)) { msg("You have finished the tunnel."); } /* Keep trying */ else { /* We may continue tunelling */ msg("You tunnel into the granite wall."); more = TRUE; } } /* Quartz / Magma */ else if (cave_ismagma(cave, y, x) || cave_isquartz(cave, y, x)) { bool okay = FALSE; bool gold = FALSE; bool hard = FALSE; /* Found gold */ if (cave_hasgoldvein(cave, y, x)) gold = TRUE; /* Extract "quartz" flag XXX XXX XXX */ if (cave_isquartz(cave, y, x)) hard = TRUE; /* Quartz */ if (hard) okay = (p_ptr->state.skills[SKILL_DIGGING] > 20 + randint0(800)); /* Magma */ else okay = (p_ptr->state.skills[SKILL_DIGGING] > 10 + randint0(400)); /* Success */ if (okay && twall(y, x)) { /* Found treasure */ if (gold) { /* Place some gold */ place_gold(cave, y, x, p_ptr->depth, ORIGIN_FLOOR); /* Message */ msg("You have found something!"); } /* Found nothing */ else { /* Message */ msg("You have finished the tunnel."); } } /* Failure (quartz) */ else if (hard) { /* Message, continue digging */ msg("You tunnel into the quartz vein."); more = TRUE; } /* Failure (magma) */ else { /* Message, continue digging */ msg("You tunnel into the magma vein."); more = TRUE; } } /* Rubble */ else if (cave_isrubble(cave, y, x)) { /* Remove the rubble */ if ((p_ptr->state.skills[SKILL_DIGGING] > randint0(200)) && twall(y, x)) { /* Message */ msg("You have removed the rubble."); /* Hack -- place an object */ if (randint0(100) < 10) { /* Create a simple object */ place_object(cave, y, x, p_ptr->depth, FALSE, FALSE, ORIGIN_RUBBLE, 0); /* Observe the new object */ if (!squelch_item_ok(object_byid(cave->o_idx[y][x])) && player_can_see_bold(y, x)) msg("You have found something!"); } } else { /* Message, keep digging */ msg("You dig in the rubble."); more = TRUE; } } /* Secret doors */ else if (cave_issecretdoor(cave, y, x)) { /* Tunnel */ if ((p_ptr->state.skills[SKILL_DIGGING] > 30 + randint0(1200)) && twall(y, x)) { msg("You have finished the tunnel."); } /* Keep trying */ else { /* We may continue tunelling */ msg("You tunnel into the granite wall."); more = TRUE; /* Occasional Search XXX XXX */ if (randint0(100) < 25) search(FALSE); } } /* Doors */ else { /* Tunnel */ if ((p_ptr->state.skills[SKILL_DIGGING] > 30 + randint0(1200)) && twall(y, x)) { msg("You have finished the tunnel."); } /* Keep trying */ else { /* We may continue tunelling */ msg("You tunnel into the door."); more = TRUE; } } /* Result */ return (more); }
/* * Allocates some objects (using "place" and "type") */ static void alloc_object(int set, int typ, int num) { int y = 0, x = 0, k; int dummy = 0; cave_type *c_ptr; /* A small level has few objects. */ num = num * cur_hgt * cur_wid / (MAX_HGT*MAX_WID) +1; /* Place some objects */ for (k = 0; k < num; k++) { /* Pick a "legal" spot */ while (dummy < SAFE_MAX_ATTEMPTS) { bool room; dummy++; /* Location */ y = randint0(cur_hgt); x = randint0(cur_wid); c_ptr = &cave[y][x]; /* Require "naked" floor grid */ if (!is_floor_grid(c_ptr) || c_ptr->o_idx || c_ptr->m_idx) continue; /* Avoid player location */ if (player_bold(y, x)) continue; /* Check for "room" */ room = (cave[y][x].info & 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; } if (dummy >= SAFE_MAX_ATTEMPTS) { if (cheat_room) { #ifdef JP msg_print("警告!アイテムを配置できません!"); #else msg_print("Warning! Could not place object!"); #endif } return; } /* Place something */ switch (typ) { case ALLOC_TYP_RUBBLE: { place_rubble(y, x); cave[y][x].info &= ~(CAVE_FLOOR); break; } case ALLOC_TYP_TRAP: { place_trap(y, x); cave[y][x].info &= ~(CAVE_FLOOR); break; } case ALLOC_TYP_GOLD: { place_gold(y, x); break; } case ALLOC_TYP_OBJECT: { place_object(y, x, 0L); break; } } } }