/** * Places a monster (of the specified "type") near the given * location. Return true iff a monster was actually summoned. * * We will attempt to place the monster up to 10 times before giving up. * * Note: S_UNIQUE and S_WRAITH will summon Uniques * Note: S_ANY, S_HI_UNDEAD, S_HI_DEMON and S_HI_DRAGON may summon Uniques * Note: None of the other summon codes will ever summon Uniques. * * This function has been changed. We now take the "monster level" * of the summoning monster as a parameter, and use that, along with * the current dungeon level, to help determine the level of the * desired monster. Note that this is an upper bound, and also * tends to "prefer" monsters of that level. Currently, we use * the average of the dungeon and monster levels, and then add * five to allow slight increases in monster power. * * Note that we use the new "monster allocation table" creation code * to restrict the "get_mon_num()" function to the set of "legal" * monsters, making this function much faster and more reliable. * * Note that this function may not succeed, though this is very rare. */ int summon_specific(int y1, int x1, int lev, int type, bool delay, bool call) { int i, x = 0, y = 0; struct monster *mon; struct monster_race *race; /* Look for a location, allow up to 4 squares away */ for (i = 0; i < 60; ++i) { /* Pick a distance */ int d = (i / 15) + 1; /* Pick a location */ scatter(cave, &y, &x, y1, x1, d, true); /* Require "empty" floor grid */ if (!square_isempty(cave, y, x)) continue; /* Hack -- no summon on glyph of warding */ if (square_iswarded(cave, y, x)) continue; /* Okay */ break; } /* Failure */ if (i == 60) return (0); /* Save the "summon" type */ summon_specific_type = type; /* Use the new calling scheme if requested */ if (call && (type != S_UNIQUE) && (type != S_WRAITH)) { return (call_monster(y, x)); } /* Prepare allocation table */ get_mon_num_prep(summon_specific_okay); /* Pick a monster, using the level calculation */ race = get_mon_num((player->depth + lev) / 2 + 5); /* Prepare allocation table */ get_mon_num_prep(NULL); /* Handle failure */ if (!race) return (0); /* Attempt to place the monster (awake, don't allow groups) */ if (!place_new_monster(cave, y, x, race, false, false, ORIGIN_DROP_SUMMON)) return (0); /* Success, return the level of the monster */ mon = square_monster(cave, y, x); /* If delay, try to let the player act before the summoned monsters, * including slowing down faster monsters for one turn */ if (delay) { mon->energy = 0; if (mon->race->speed > player->state.speed) mon_inc_timed(mon, MON_TMD_SLOW, 1, MON_TMD_FLG_NOMESSAGE, false); } return (mon->race->level); }
/* * Build the wilderness area outside of the town. */ void wilderness_gen(void) { int i, y, x; bool daytime; cave_type *c_ptr; /* Big town */ cur_hgt = MAX_HGT; cur_wid = MAX_WID; /* Assume illegal panel */ panel_row_min = cur_hgt; panel_col_min = cur_wid; /* Init the wilderness */ process_dungeon_file("w_info.txt", 0, 0, max_wild_y, max_wild_x); x = p_ptr->wilderness_x; y = p_ptr->wilderness_y; /* Prepare allocation table */ get_mon_num_prep(get_monster_hook(), NULL); /* North border */ generate_area(y - 1, x, TRUE, FALSE); for (i = 1; i < MAX_WID - 1; i++) { border.north[i] = cave[MAX_HGT - 2][i].feat; } /* South border */ generate_area(y + 1, x, TRUE, FALSE); for (i = 1; i < MAX_WID - 1; i++) { border.south[i] = cave[1][i].feat; } /* West border */ generate_area(y, x - 1, TRUE, FALSE); for (i = 1; i < MAX_HGT - 1; i++) { border.west[i] = cave[i][MAX_WID - 2].feat; } /* East border */ generate_area(y, x + 1, TRUE, FALSE); for (i = 1; i < MAX_HGT - 1; i++) { border.east[i] = cave[i][1].feat; } /* North west corner */ generate_area(y - 1, x - 1, FALSE, TRUE); border.north_west = cave[MAX_HGT - 2][MAX_WID - 2].feat; /* North east corner */ generate_area(y - 1, x + 1, FALSE, TRUE); border.north_east = cave[MAX_HGT - 2][1].feat; /* South west corner */ generate_area(y + 1, x - 1, FALSE, TRUE); border.south_west = cave[1][MAX_WID - 2].feat; /* South east corner */ generate_area(y + 1, x + 1, FALSE, TRUE); border.south_east = cave[1][1].feat; /* Leaving the dungeon by stairs */ /* (needed before the town is loaded) */ if (p_ptr->leaving_dungeon) { p_ptr->oldpy = 0; p_ptr->oldpx = 0; } /* Create terrain of the current area */ generate_area(y, x, FALSE, FALSE); /* Special boundary walls -- North */ for (i = 0; i < MAX_WID; i++) { cave[0][i].feat = FEAT_PERM_SOLID; cave[0][i].mimic = border.north[i]; } /* Special boundary walls -- South */ for (i = 0; i < MAX_WID; i++) { cave[MAX_HGT - 1][i].feat = FEAT_PERM_SOLID; cave[MAX_HGT - 1][i].mimic = border.south[i]; } /* Special boundary walls -- West */ for (i = 0; i < MAX_HGT; i++) { cave[i][0].feat = FEAT_PERM_SOLID; cave[i][0].mimic = border.west[i]; } /* Special boundary walls -- East */ for (i = 0; i < MAX_HGT; i++) { cave[i][MAX_WID - 1].feat = FEAT_PERM_SOLID; cave[i][MAX_WID - 1].mimic = border.east[i]; } /* North west corner */ cave[0][0].mimic = border.north_west; /* North east corner */ cave[0][MAX_WID - 1].mimic = border.north_east; /* South west corner */ cave[MAX_HGT - 1][0].mimic = border.south_west; /* South east corner */ cave[MAX_HGT - 1][MAX_WID - 1].mimic = border.south_east; /* Day time */ if ((turn % (10L * TOWN_DAWN)) < ((10L * TOWN_DAWN) / 2)) daytime = TRUE; else daytime = FALSE; /* Light up or darken the area */ for (y = 0; y < cur_hgt; y++) { for (x = 0; x < cur_wid; x++) { /* Get the cave grid */ c_ptr = &cave[y][x]; if (daytime) { /* Assume lit */ c_ptr->info |= (CAVE_GLOW); /* Hack -- Memorize lit grids if allowed */ if (view_perma_grids) c_ptr->info |= (CAVE_MARK); } else { /* Darken "boring" features */ if ((c_ptr->feat <= FEAT_INVIS) || ((c_ptr->feat >= FEAT_DEEP_WATER) && (c_ptr->feat <= FEAT_MOUNTAIN)) || (x == 0) || (x == cur_wid - 1) || (y == 0) || (y == cur_hgt - 1)) { /* Forget the grid */ c_ptr->info &= ~(CAVE_GLOW | CAVE_MARK); } } } } player_place(p_ptr->oldpy, p_ptr->oldpx); p_ptr->leaving_dungeon = FALSE; /* Make some residents */ for (i = 0; i < MIN_M_ALLOC_TN; i++) { /* Make a resident */ (void)alloc_monster(3, TRUE); } /* Set rewarded quests to finished */ for (i = 0; i < max_quests; i++) { if (quest[i].status == QUEST_STATUS_REWARDED) quest[i].status = QUEST_STATUS_FINISHED; } }