From 673bdae75485d14f759af597c3c62b99601f9a43 Mon Sep 17 00:00:00 2001 From: peterb12 Date: Thu, 21 Jul 2005 02:34:44 +0000 Subject: Initial revision git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@3 c06c8d41-db1a-0410-9941-cceddc491573 --- trunk/source/dungeon.cc | 8446 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 8446 insertions(+) create mode 100644 trunk/source/dungeon.cc (limited to 'trunk/source/dungeon.cc') diff --git a/trunk/source/dungeon.cc b/trunk/source/dungeon.cc new file mode 100644 index 0000000000..c899daa7dc --- /dev/null +++ b/trunk/source/dungeon.cc @@ -0,0 +1,8446 @@ +/* + * File: dungeon.cc + * Summary: Functions used when building new levels. + * Written by: Linley Henzell + * + * Change History (most recent first): + * + * + * <9> 07-Aug-2001 MV clean up of give_item; distribution of + * wands, potions and scrolls + * underground rivers and lakes + * <8> 02-Apr-2001 gdl cleanup; nuked all globals + * <7> 06-Mar-2000 bwr reduced vorpal weapon freq, + * spellbooks now hold up to eight spells. + * <6> 11/06/99 cdl random3 -> random2 + * <5> 8/08/99 BWR Upped rarity of unique artefacts + * <4> 7/13/99 BWR Made pole arms of speed. + * <3> 5/22/99 BWR Made named artefact weapons + * rarer, Sword of Power esp. + * <2> 5/09/99 LRH Replaced some sanity checking code in + * spellbook_template with a corrected version + * using ASSERTs. + * <1> -/--/-- LRH Created + */ + +#include +#include +#include + +#include "AppHdr.h" +#include "abyss.h" +#include "defines.h" +#include "enum.h" +#include "externs.h" +#include "dungeon.h" +#include "itemname.h" +#include "items.h" +#include "maps.h" +#include "mon-util.h" +#include "mon-pick.h" +#include "monplace.h" +#include "player.h" +#include "randart.h" +#include "spl-book.h" +#include "stuff.h" +#include "wpn-misc.h" + +struct spec_t { + bool created; + bool hooked_up; + int x1; + int y1; + int x2; + int y2; +}; + +typedef struct spec_t spec_room; + +// DUNGEON BUILDERS +static bool find_in_area(int sx, int sy, int ex, int ey, unsigned char feature); +static bool make_box(int room_x1, int room_y1, int room_x2, int room_y2, + unsigned char floor=0, unsigned char wall=0, unsigned char avoid=0); +static void replace_area(int sx, int sy, int ex, int ey, unsigned char replace, + unsigned char feature); +static int builder_by_type(int level_number, char level_type); +static int builder_by_branch(int level_number); +static int builder_normal(int level_number, char level_type, spec_room &s); +static int builder_basic(int level_number); +static void builder_extras(int level_number, int level_type); +static void builder_items(int level_number, char level_type, int items_wanted); +static void builder_monsters(int level_number, char level_type, int mon_wanted); +static void place_specific_stair(unsigned char stair); +static void place_branch_entrances(int dlevel, char level_type); +static bool place_specific_trap(unsigned char spec_x, unsigned char spec_y, + unsigned char spec_type); +static void place_traps( int level_number ); +static void prepare_swamp(void); +static void prepare_water( int level_number ); +static void check_doors(void); +static void hide_doors(void); +static void make_trail(int xs, int xr, int ys, int yr,int corrlength, int intersect_chance, + int no_corr, unsigned char begin, unsigned char end=0); +static bool make_room(int sx,int sy,int ex,int ey,int max_doors, int doorlevel); +static void join_the_dots(unsigned char dotx1, unsigned char doty1, + unsigned char dotx2, unsigned char doty2, char forbid_x1, char forbid_y1, + char forbid_x2, char forbid_y2); +static void place_pool(unsigned char pool_type, unsigned char pool_x1, + unsigned char pool_y1, unsigned char pool_x2, + unsigned char pool_y2); +static void many_pools(unsigned char pool_type); + +#ifdef USE_RIVERS +static void build_river(unsigned char river_type); //mv +static void build_lake(unsigned char lake_type); //mv +#endif // USE_RIVERS + +static void spotty_level(bool seeded, int iterations, bool boxy); +static void bigger_room(void); +static void plan_main(int level_number, char force_plan); +static char plan_1(void); +static char plan_2(void); +static char plan_3(void); +static char plan_4(char forbid_x1, char forbid_y1, char forbid_x2, + char forbid_y2, unsigned char force_wall); +static char plan_5(void); +static char plan_6(int level_number); +static bool octa_room(spec_room &sr, int oblique_max, unsigned char type_floor); +static void labyrinth_level(int level_number); +static void box_room(int bx1, int bx2, int by1, int by2, int wall_type); +static int box_room_doors( int bx1, int bx2, int by1, int by2, int new_doors); +static void city_level(int level_number); +static void diamond_rooms(int level_number); + +// ITEM & SHOP FUNCTIONS +static void place_shops(int level_number); +static void place_spec_shop(int level_number, unsigned char shop_x, + unsigned char shop_y, unsigned char force_s_type); +static unsigned char item_in_shop(unsigned char shop_type); +static bool treasure_area(int level_number, unsigned char ta1_x, + unsigned char ta2_x, unsigned char ta1_y, + unsigned char ta2_y); +static char rare_weapon(unsigned char w_type); +static bool is_weapon_special(int the_weapon); +static void set_weapon_special(int the_weapon, int spwpn); +static void big_room(int level_number); +static void chequerboard(spec_room &sr, unsigned char + target, unsigned char floor1, unsigned char floor2); +static void roguey_level(int level_number, spec_room &sr); +static void morgue(spec_room &sr); + +// SPECIAL ROOM BUILDERS +static void special_room(int level_number, spec_room &sr); +static void specr_2(spec_room &sr); +static void beehive(spec_room &sr); + +// VAULT FUNCTIONS +static void build_vaults(int level_number, int force_vault); +static void build_minivaults(int level_number, int force_vault); +static int vault_grid( int level_number, int vx, int vy, int altar_count, + FixedVector < char, 7 > &acq_item_class, + FixedVector < int, 7 > &mons_array, + char vgrid, int &initial_x, int &initial_y, + int force_vault, int &num_runes ); + +// ALTAR FUNCTIONS +static int pick_an_altar(void); +static void place_altar(void); + + +/* + ************************************************** + * * + * BEGIN PUBLIC FUNCTIONS * + * * + ************************************************** +*/ + +void builder(int level_number, char level_type) +{ + int i; // generic loop variable + int x,y; // generic map loop variables + + srandom(time(NULL)); + + // blank level with DNGN_ROCK_WALL + make_box(0,0,GXM-1,GYM-1,DNGN_ROCK_WALL,DNGN_ROCK_WALL); + + // delete all traps + for (i = 0; i < MAX_TRAPS; i++) + env.trap[i].type = TRAP_UNASSIGNED; + + // initialize all items + for (i = 0; i < MAX_ITEMS; i++) + init_item( i ); + + // reset all monsters + for (i = 0; i < MAX_MONSTERS; i++) + menv[i].type = -1; + + // unlink all monsters and items from the grid + for(x=0; x 60) + mon_wanted = 60; + } + + place_branch_entrances( level_number, level_type ); + + check_doors(); + + if (!player_in_branch( BRANCH_DIS ) && !player_in_branch( BRANCH_VAULTS )) + hide_doors(); + + if (!player_in_branch( BRANCH_ECUMENICAL_TEMPLE )) + place_traps(level_number); + + int items_wanted = 3 + roll_dice( 3, 11 ); + + if (level_number > 5 && one_chance_in(500 - 5 * level_number)) + items_wanted = 10 + random2avg( 90, 2 ); // rich level! + + // change pre-rock (105) to rock, and pre-floor (106) to floor + replace_area( 0,0,GXM-1,GYM-1, DNGN_BUILDER_SPECIAL_WALL, DNGN_ROCK_WALL ); + replace_area( 0,0,GXM-1,GYM-1, DNGN_BUILDER_SPECIAL_FLOOR, DNGN_FLOOR ); + + // place items + builder_items(level_number, level_type, items_wanted); + + // place monsters + builder_monsters(level_number, level_type, mon_wanted); + + // place shops, if appropriate + if (player_in_branch( BRANCH_MAIN_DUNGEON ) + || player_in_branch( BRANCH_ORCISH_MINES ) + || player_in_branch( BRANCH_ELVEN_HALLS ) + || player_in_branch( BRANCH_LAIR ) + || player_in_branch( BRANCH_VAULTS ) + || player_in_branch( BRANCH_SNAKE_PIT ) + || player_in_branch( BRANCH_SWAMP )) + { + place_shops(level_number); + } + + // If level part of Dis -> all walls metal; + // If part of vaults -> walls depend on level; + // If part of crypt -> all walls stone: + if (player_in_branch( BRANCH_DIS ) + || player_in_branch( BRANCH_VAULTS ) + || player_in_branch( BRANCH_CRYPT )) + { + // always the case with Dis {dlb} + unsigned char vault_wall = DNGN_METAL_WALL; + + if (player_in_branch( BRANCH_VAULTS )) + { + vault_wall = DNGN_ROCK_WALL; + + if (level_number > you.branch_stairs[STAIRS_VAULTS] + 2) + vault_wall = DNGN_STONE_WALL; + + if (level_number > you.branch_stairs[STAIRS_VAULTS] + 4) + vault_wall = DNGN_METAL_WALL; + + if (level_number > you.branch_stairs[STAIRS_VAULTS] + 6 + && one_chance_in(10)) + { + vault_wall = DNGN_GREEN_CRYSTAL_WALL; + } + } + else if (player_in_branch( BRANCH_CRYPT )) + { + vault_wall = DNGN_STONE_WALL; + } + + replace_area(0,0,GXM-1,GYM-1,DNGN_ROCK_WALL,vault_wall); + } + + // Top level of branch levels - replaces up stairs + // with stairs back to dungeon or wherever: + for (i = 0; i< 30; i++) + { + if (you.branch_stairs[i] == 0) + break; + + if (level_number == you.branch_stairs[i] + 1 + && level_type == LEVEL_DUNGEON + && you.where_are_you == BRANCH_ORCISH_MINES + i) + { + for (x = 1; x < GXM; x++) + { + for (y = 1; y < GYM; y++) + { + if (grd[x][y] >= DNGN_STONE_STAIRS_UP_I + && grd[x][y] <= DNGN_ROCK_STAIRS_UP) + { + grd[x][y] = DNGN_RETURN_FROM_ORCISH_MINES + i; + } + } + } + } + } + + // bottom level of branch - replaces down stairs with up ladders: + for (i = 0; i < 30; i++) + { + if (level_number == you.branch_stairs[i] + branch_depth(i) + && level_type == LEVEL_DUNGEON + && you.where_are_you == BRANCH_ORCISH_MINES + i) + { + for (x = 1; x < GXM; x++) + { + for (y = 1; y < GYM; y++) + { + if (grd[x][y] >= DNGN_STONE_STAIRS_DOWN_I + && grd[x][y] <= DNGN_ROCK_STAIRS_DOWN) + { + grd[x][y] = DNGN_ROCK_STAIRS_UP; + } + } + } + } + } + + if (player_in_branch( BRANCH_CRYPT )) + { + if (one_chance_in(3)) + mons_place( MONS_CURSE_SKULL, BEH_SLEEP, MHITNOT, false, 0, 0 ); + + if (one_chance_in(7)) + mons_place( MONS_CURSE_SKULL, BEH_SLEEP, MHITNOT, false, 0, 0 ); + } + + if (player_in_branch( BRANCH_ORCISH_MINES ) && one_chance_in(5)) + place_altar(); + + // hall of blades (1 level deal) - no down staircases, thanks! + if (player_in_branch( BRANCH_HALL_OF_BLADES )) + { + for (x = 1; x < GXM; x++) + { + for (y = 1; y < GYM; y++) + { + if (grd[x][y] >= DNGN_STONE_STAIRS_DOWN_I + && grd[x][y] <= DNGN_ROCK_STAIRS_UP) + { + grd[x][y] = DNGN_FLOOR; + } + } + } + } + + link_items(); + + if (!player_in_branch(BRANCH_COCYTUS) && !player_in_branch(BRANCH_SWAMP)) + prepare_water( level_number ); +} // end builder() + +// Returns item slot or NON_ITEM if it fails +int items( int allow_uniques, // not just true-false, + // because of BCR acquirement hack + int force_class, // desired OBJECTS class {dlb} + int force_type, // desired SUBTYPE - enum varies by OBJ + bool dont_place, // don't randomly place item on level + int item_level, // level of the item, can differ from global + int item_race ) // weapon / armour racial categories + // item_race also gives type of rune! +{ + int temp_rand = 0; // probability determination {dlb} + int range_charges = 0; // for OBJ_WANDS charge count {dlb} + int temp_value = 0; // temporary value storage {dlb} + int loopy = 0; // just another loop variable {dlb} + int count = 0; // just another loop variable {dlb} + + int race_plus = 0; + int race_plus2 = 0; + int x_pos, y_pos; + + int quant = 0; + + FixedVector < int, SPELLBOOK_SIZE > fpass; + int icky = 0; + int p = 0; + + // find an emtpy slot for the item (with culling if required) + p = get_item_slot(10); + if (p == NON_ITEM) + return (NON_ITEM); + + // clear all properties except mitm.base_type {dlb}: + mitm[p].sub_type = 0; + mitm[p].flags = 0; + mitm[p].special = 0; + mitm[p].plus = 0; + mitm[p].plus2 = 0; + mitm[p].x = 0; + mitm[p].y = 0; + mitm[p].link = NON_ITEM; + + // cap item_level unless an acquirement-level item {dlb}: + if (item_level > 50 && item_level != MAKE_GOOD_ITEM) + item_level = 50; + + // determine base_type for item generated {dlb}: + if (force_class != OBJ_RANDOM) + mitm[p].base_type = force_class; + else + { + // nice and large for subtle differences {dlb} + temp_rand = random2(10000); + + mitm[p].base_type = ((temp_rand < 50) ? OBJ_STAVES : // 0.50% + (temp_rand < 200) ? OBJ_BOOKS : // 1.50% + (temp_rand < 450) ? OBJ_JEWELLERY :// 2.50% + (temp_rand < 800) ? OBJ_WANDS : // 3.50% + (temp_rand < 1500) ? OBJ_FOOD : // 7.00% + (temp_rand < 2500) ? OBJ_ARMOUR : // 10.00% + (temp_rand < 3500) ? OBJ_WEAPONS : // 10.00% + (temp_rand < 4500) ? OBJ_POTIONS : // 10.00% + (temp_rand < 6000) ? OBJ_MISSILES : // 15.00% + (temp_rand < 8000) ? OBJ_SCROLLS // 20.00% + : OBJ_GOLD); // 20.00% + + // misc items placement wholly dependent upon current depth {dlb}: + if (item_level > 7 && (20 + item_level) >= random2(3500)) + mitm[p].base_type = OBJ_MISCELLANY; + + if (item_level < 7 + && (mitm[p].base_type == OBJ_BOOKS + || mitm[p].base_type == OBJ_STAVES + || mitm[p].base_type == OBJ_WANDS) + && random2(7) >= item_level) + { + mitm[p].base_type = coinflip() ? OBJ_POTIONS : OBJ_SCROLLS; + } + } + + // determine sub_type accordingly {dlb}: + switch (mitm[p].base_type) + { + case OBJ_WEAPONS: + // generate initial weapon subtype using weighted function -- + // indefinite loop now more evident and fewer array lookups {dlb}: + if (force_type != OBJ_RANDOM) + mitm[p].sub_type = force_type; + else + { + if (random2(20) < 20 - item_level) + { + // these are the common/low level weapon types + temp_rand = random2(12); + + mitm[p].sub_type = ((temp_rand == 0) ? WPN_KNIFE : + (temp_rand == 1) ? WPN_QUARTERSTAFF : + (temp_rand == 2) ? WPN_SLING : + (temp_rand == 3) ? WPN_SPEAR : + (temp_rand == 4) ? WPN_HAND_AXE : + (temp_rand == 5) ? WPN_DAGGER : + (temp_rand == 6) ? WPN_MACE : + (temp_rand == 7) ? WPN_DAGGER : + (temp_rand == 8) ? WPN_CLUB : + (temp_rand == 9) ? WPN_HAMMER : + (temp_rand == 10) ? WPN_WHIP + : WPN_SABRE); + } + else if (item_level > 6 && random2(100) < (10 + item_level) + && one_chance_in(30)) + { + // place the rare_weapon() == 0 weapons + // + // this replaced the infinite loop (wasteful) -- may need + // to make into its own function to allow ease of tweaking + // distribution {dlb}: + temp_rand = random2(9); + + mitm[p].sub_type = ((temp_rand == 8) ? WPN_DEMON_BLADE : + (temp_rand == 7) ? WPN_DEMON_TRIDENT : + (temp_rand == 6) ? WPN_DEMON_WHIP : + (temp_rand == 5) ? WPN_DOUBLE_SWORD : + (temp_rand == 4) ? WPN_EVENINGSTAR : + (temp_rand == 3) ? WPN_EXECUTIONERS_AXE : + (temp_rand == 2) ? WPN_KATANA : + (temp_rand == 1) ? WPN_QUICK_BLADE + /*(temp_rand == 0)*/: WPN_TRIPLE_SWORD); + } + else + { + // pick a weapon based on rarity + for (;;) + { + temp_value = (unsigned char) random2(NUM_WEAPONS); + + if (rare_weapon(temp_value) >= random2(10) + 1) + { + mitm[p].sub_type = temp_value; + break; + } + } + } + } + + if (allow_uniques) + { + // Note there is nothing to stop randarts being reproduced, + // except vast improbability. + if (mitm[p].sub_type != WPN_CLUB && item_level > 2 + && random2(2000) <= 100 + (item_level * 3) && coinflip()) + { + if (you.level_type != LEVEL_ABYSS + && you.level_type != LEVEL_PANDEMONIUM + && one_chance_in(50)) + { + icky = find_okay_unrandart( OBJ_WEAPONS, force_type ); + + if (icky != -1) + { + quant = 1; + make_item_unrandart( mitm[p], icky ); + break; + } + } + + make_item_randart( mitm[p] ); + mitm[p].plus = 0; + mitm[p].plus2 = 0; + mitm[p].plus += random2(7); + mitm[p].plus2 += random2(7); + + if (one_chance_in(3)) + mitm[p].plus += random2(7); + + if (one_chance_in(3)) + mitm[p].plus2 += random2(7); + + if (one_chance_in(9)) + mitm[p].plus -= random2(7); + + if (one_chance_in(9)) + mitm[p].plus2 -= random2(7); + + quant = 1; + + if (one_chance_in(4)) + { + do_curse_item( mitm[p] ); + mitm[p].plus = -random2(6); + mitm[p].plus2 = -random2(6); + } + else if ((mitm[p].plus < 0 || mitm[p].plus2 < 0) + && !one_chance_in(3)) + { + do_curse_item( mitm[p] ); + } + break; + } + + if (item_level > 6 + && random2(3000) <= 30 + (item_level * 3) && one_chance_in(12)) + { + if (make_item_fixed_artefact( mitm[p], (item_level == 51) )) + break; + } + } + + ASSERT(!is_fixed_artefact(mitm[p]) && !is_random_artefact(mitm[p])); + + if (item_level == MAKE_GOOD_ITEM + && force_type != OBJ_RANDOM + && (mitm[p].sub_type == WPN_CLUB || mitm[p].sub_type == WPN_SLING)) + { + mitm[p].sub_type = WPN_LONG_SWORD; + } + + quant = 1; + + mitm[p].plus = 0; + mitm[p].plus2 = 0; + mitm[p].special = SPWPN_NORMAL; + + if (item_race == MAKE_ITEM_RANDOM_RACE && coinflip()) + { + switch (mitm[p].sub_type) + { + case WPN_CLUB: + if (coinflip()) + set_equip_race( mitm[p], ISFLAG_ORCISH ); + break; + + case WPN_MACE: + case WPN_FLAIL: + case WPN_SPIKED_FLAIL: + case WPN_GREAT_MACE: + case WPN_GREAT_FLAIL: + if (one_chance_in(6)) + set_equip_race( mitm[p], ISFLAG_ELVEN ); + if (one_chance_in(4)) + set_equip_race( mitm[p], ISFLAG_DWARVEN ); + if (one_chance_in(3)) + set_equip_race( mitm[p], ISFLAG_ORCISH ); + break; + + case WPN_MORNINGSTAR: + case WPN_HAMMER: + if (one_chance_in(3)) + set_equip_race( mitm[p], ISFLAG_ORCISH ); + if (one_chance_in(3)) + set_equip_race( mitm[p], ISFLAG_DWARVEN ); + break; + + case WPN_DAGGER: + if (one_chance_in(3)) + set_equip_race( mitm[p], ISFLAG_ORCISH ); + if (one_chance_in(4)) + set_equip_race( mitm[p], ISFLAG_DWARVEN ); + if (one_chance_in(4)) + set_equip_race( mitm[p], ISFLAG_ELVEN ); + break; + + case WPN_SHORT_SWORD: + if (one_chance_in(3)) + set_equip_race( mitm[p], ISFLAG_ORCISH ); + if (one_chance_in(3)) + set_equip_race( mitm[p], ISFLAG_DWARVEN ); + if (one_chance_in(3)) + set_equip_race( mitm[p], ISFLAG_ELVEN ); + break; + + case WPN_FALCHION: + if (one_chance_in(5)) + set_equip_race( mitm[p], ISFLAG_DWARVEN ); + if (one_chance_in(3)) + set_equip_race( mitm[p], ISFLAG_ORCISH ); + if (one_chance_in(3)) + set_equip_race( mitm[p], ISFLAG_ELVEN ); + break; + + case WPN_LONG_SWORD: + if (one_chance_in(4)) + set_equip_race( mitm[p], ISFLAG_ORCISH ); + if (coinflip()) + set_equip_race( mitm[p], ISFLAG_ELVEN ); + break; + + case WPN_GREAT_SWORD: + if (one_chance_in(3)) + set_equip_race( mitm[p], ISFLAG_ORCISH ); + break; + + case WPN_SCIMITAR: + if (coinflip()) + set_equip_race( mitm[p], ISFLAG_ORCISH ); + break; + + case WPN_WAR_AXE: + case WPN_HAND_AXE: + case WPN_BROAD_AXE: + case WPN_BATTLEAXE: + if (one_chance_in(3)) + set_equip_race( mitm[p], ISFLAG_ORCISH ); + if (coinflip()) + set_equip_race( mitm[p], ISFLAG_DWARVEN ); + break; + + case WPN_SPEAR: + case WPN_TRIDENT: + if (one_chance_in(4)) + set_equip_race( mitm[p], ISFLAG_ORCISH ); + if (one_chance_in(4)) + set_equip_race( mitm[p], ISFLAG_ELVEN ); + break; + + case WPN_HALBERD: + case WPN_GLAIVE: + case WPN_EXECUTIONERS_AXE: + if (one_chance_in(5)) + set_equip_race( mitm[p], ISFLAG_ORCISH ); + break; + + case WPN_QUICK_BLADE: + if (one_chance_in(4)) + set_equip_race( mitm[p], ISFLAG_ELVEN ); + break; + + case WPN_KATANA: + case WPN_KNIFE: + case WPN_SLING: + set_equip_race( mitm[p], ISFLAG_NO_RACE ); + set_item_ego_type( mitm[p], OBJ_WEAPONS, SPWPN_NORMAL ); + break; + + case WPN_BOW: + if (one_chance_in(6)) + set_equip_race( mitm[p], ISFLAG_ORCISH ); + if (coinflip()) + set_equip_race( mitm[p], ISFLAG_ELVEN ); + break; + + case WPN_CROSSBOW: + if (one_chance_in(4)) + set_equip_race( mitm[p], ISFLAG_ORCISH ); + if (one_chance_in(4)) + set_equip_race( mitm[p], ISFLAG_DWARVEN ); + break; + + case WPN_HAND_CROSSBOW: + if (one_chance_in(3)) + set_equip_race( mitm[p], ISFLAG_ELVEN ); + break; + + case WPN_BLOWGUN: + if (one_chance_in(10)) + set_equip_race( mitm[p], ISFLAG_ELVEN ); + if (one_chance_in(4)) + set_equip_race( mitm[p], ISFLAG_ORCISH ); + break; + } + } + + // fine, but out-of-order relative to mitm[].special ordering {dlb} + switch (item_race) + { + case MAKE_ITEM_ELVEN: + set_equip_race( mitm[p], ISFLAG_ELVEN ); + break; + + case MAKE_ITEM_DWARVEN: + set_equip_race( mitm[p], ISFLAG_DWARVEN ); + break; + + case MAKE_ITEM_ORCISH: + set_equip_race( mitm[p], ISFLAG_ORCISH ); + break; + } + + // if we allow acquirement-type items to be orcish, then + // there's a good chance that we'll just strip them of + // their ego type at the bottom of this function. -- bwr + if (item_level == MAKE_GOOD_ITEM + && cmp_equip_race( mitm[p], ISFLAG_ORCISH )) + { + set_equip_race( mitm[p], ISFLAG_NO_RACE ); + } + + switch (get_equip_race( mitm[p] )) + { + case ISFLAG_ORCISH: + if (coinflip()) + race_plus--; + if (coinflip()) + race_plus2++; + break; + + case ISFLAG_ELVEN: + race_plus += random2(3); + break; + + case ISFLAG_DWARVEN: + if (coinflip()) + race_plus++; + if (coinflip()) + race_plus2++; + break; + } + + mitm[p].plus += race_plus; + mitm[p].plus2 += race_plus2; + + if ((random2(200) <= 50 + item_level + || item_level == MAKE_GOOD_ITEM + || is_demonic(mitm[p].sub_type)) + // nobody would bother enchanting a club + && mitm[p].sub_type != WPN_CLUB + && mitm[p].sub_type != WPN_GIANT_CLUB + && mitm[p].sub_type != WPN_GIANT_SPIKED_CLUB) + { + count = 0; + + do + { + if (random2(300) <= 100 + item_level + || item_level == MAKE_GOOD_ITEM + || is_demonic( mitm[p].sub_type )) + { + // note: this doesn't guarantee special enchantment + switch (mitm[p].sub_type) + { + case WPN_EVENINGSTAR: + if (coinflip()) + set_weapon_special(p, SPWPN_DRAINING); + // **** intentional fall through here **** + case WPN_MORNINGSTAR: + if (one_chance_in(4)) + set_weapon_special(p, SPWPN_VENOM); + + if (one_chance_in(4)) + { + set_weapon_special(p, (coinflip() ? SPWPN_FLAMING + : SPWPN_FREEZING)); + } + + if (one_chance_in(20)) + set_weapon_special(p, SPWPN_VAMPIRICISM); + // **** intentional fall through here **** + case WPN_MACE: + case WPN_GREAT_MACE: + if ((mitm[p].sub_type == WPN_MACE + || mitm[p].sub_type == WPN_GREAT_MACE) + && one_chance_in(4)) + { + set_weapon_special(p, SPWPN_DISRUPTION); + } + // **** intentional fall through here **** + case WPN_FLAIL: + case WPN_SPIKED_FLAIL: + case WPN_GREAT_FLAIL: + case WPN_HAMMER: + if (one_chance_in(25)) + set_weapon_special(p, SPWPN_PAIN); + + if (one_chance_in(25)) + set_weapon_special(p, SPWPN_DISTORTION); + + if (one_chance_in(3) && + (!is_weapon_special(p) || one_chance_in(5))) + set_weapon_special(p, SPWPN_VORPAL); + + if (one_chance_in(4)) + set_weapon_special(p, SPWPN_HOLY_WRATH); + + if (one_chance_in(3)) + set_weapon_special(p, SPWPN_PROTECTION); + + if (one_chance_in(10)) + set_weapon_special(p, SPWPN_DRAINING); + break; + + + case WPN_DAGGER: + if (one_chance_in(10)) + set_weapon_special(p, SPWPN_PAIN); + + if (one_chance_in(3)) + set_weapon_special(p, SPWPN_VENOM); + // **** intentional fall through here **** + + case WPN_SHORT_SWORD: + case WPN_SABRE: + if (one_chance_in(25)) + set_weapon_special(p, SPWPN_DISTORTION); + + if (one_chance_in(10)) + set_weapon_special(p, SPWPN_VAMPIRICISM); + + if (one_chance_in(8)) + set_weapon_special(p, SPWPN_ELECTROCUTION); + + if (one_chance_in(8)) + set_weapon_special(p, SPWPN_PROTECTION); + + if (one_chance_in(10)) + set_weapon_special(p, SPWPN_ORC_SLAYING); + + if (one_chance_in(8)) + { + set_weapon_special(p,(coinflip() ? SPWPN_FLAMING + : SPWPN_FREEZING)); + } + + if (one_chance_in(12)) + set_weapon_special(p, SPWPN_HOLY_WRATH); + + if (one_chance_in(8)) + set_weapon_special(p, SPWPN_DRAINING); + + if (one_chance_in(8)) + set_weapon_special(p, SPWPN_SPEED); + + if (one_chance_in(6)) + set_weapon_special(p, SPWPN_VENOM); + break; + + case WPN_FALCHION: + case WPN_LONG_SWORD: + if (one_chance_in(12)) + set_weapon_special(p, SPWPN_VENOM); + // **** intentional fall through here **** + case WPN_SCIMITAR: + if (one_chance_in(25)) + set_weapon_special(p, SPWPN_PAIN); + + if (one_chance_in(7)) + set_weapon_special(p, SPWPN_SPEED); + // **** intentional fall through here **** + case WPN_GREAT_SWORD: + case WPN_DOUBLE_SWORD: + case WPN_TRIPLE_SWORD: + if (one_chance_in(10)) + set_weapon_special(p, SPWPN_VAMPIRICISM); + + if (one_chance_in(25)) + set_weapon_special(p, SPWPN_DISTORTION); + + if (one_chance_in(5)) + { + set_weapon_special(p,(coinflip() ? SPWPN_FLAMING + : SPWPN_FREEZING)); + } + + if (one_chance_in(7)) + set_weapon_special(p, SPWPN_PROTECTION); + + if (one_chance_in(8)) + set_weapon_special(p, SPWPN_ORC_SLAYING); + + if (one_chance_in(12)) + set_weapon_special(p, SPWPN_DRAINING); + + if (one_chance_in(7)) + set_weapon_special(p, SPWPN_ELECTROCUTION); + + if (one_chance_in(4)) + set_weapon_special(p, SPWPN_HOLY_WRATH); + + if (one_chance_in(4) + && (!is_weapon_special(p) || one_chance_in(3))) + { + set_weapon_special(p, SPWPN_VORPAL); + } + break; + + + case WPN_WAR_AXE: + case WPN_BROAD_AXE: + case WPN_BATTLEAXE: + case WPN_EXECUTIONERS_AXE: + if (one_chance_in(25)) + set_weapon_special(p, SPWPN_HOLY_WRATH); + + if (one_chance_in(14)) + set_weapon_special(p, SPWPN_DRAINING); + // **** intentional fall through here **** + case WPN_HAND_AXE: + if (one_chance_in(30)) + set_weapon_special(p, SPWPN_PAIN); + + if (one_chance_in(10)) + set_weapon_special(p, SPWPN_VAMPIRICISM); + + if (one_chance_in(25)) + set_weapon_special(p, SPWPN_DISTORTION); + + if (one_chance_in(3) + && (!is_weapon_special(p) || one_chance_in(5))) + { + set_weapon_special(p, SPWPN_VORPAL); + } + + if (one_chance_in(6)) + set_weapon_special(p, SPWPN_ORC_SLAYING); + + if (one_chance_in(4)) + { + set_weapon_special(p, (coinflip() ? SPWPN_FLAMING + : SPWPN_FREEZING)); + } + + if (one_chance_in(8)) + set_weapon_special(p, SPWPN_ELECTROCUTION); + + if (one_chance_in(12)) + set_weapon_special(p, SPWPN_VENOM); + + break; + + case WPN_WHIP: + if (one_chance_in(20)) + set_weapon_special(p, SPWPN_DISTORTION); + + if (one_chance_in(6)) + { + set_weapon_special(p, (coinflip() ? SPWPN_FLAMING + : SPWPN_FREEZING)); + } + + if (one_chance_in(6)) + set_weapon_special(p, SPWPN_VENOM); + + if (coinflip()) + set_weapon_special(p, SPWPN_REACHING); + + if (one_chance_in(5)) + set_weapon_special(p, SPWPN_SPEED); + + if (one_chance_in(5)) + set_weapon_special(p, SPWPN_ELECTROCUTION); + break; + + case WPN_HALBERD: + case WPN_GLAIVE: + if (one_chance_in(30)) + set_weapon_special(p, SPWPN_HOLY_WRATH); + + if (one_chance_in(4)) + set_weapon_special(p, SPWPN_PROTECTION); + // **** intentional fall through here **** + case WPN_SCYTHE: + case WPN_TRIDENT: + if (one_chance_in(5)) + set_weapon_special(p, SPWPN_SPEED); + // **** intentional fall through here **** + case WPN_SPEAR: + if (one_chance_in(25)) + set_weapon_special(p, SPWPN_PAIN); + + if (one_chance_in(10)) + set_weapon_special(p, SPWPN_VAMPIRICISM); + + if (one_chance_in(20)) + set_weapon_special(p, SPWPN_DISTORTION); + + if (one_chance_in(5) && + (!is_weapon_special(p) || one_chance_in(6))) + set_weapon_special(p, SPWPN_VORPAL); + + if (one_chance_in(6)) + set_weapon_special(p, SPWPN_ORC_SLAYING); + + if (one_chance_in(6)) + { + set_weapon_special(p, (coinflip() ? SPWPN_FLAMING + : SPWPN_FREEZING)); + } + + if (one_chance_in(6)) + set_weapon_special(p, SPWPN_VENOM); + + if (one_chance_in(3)) + set_weapon_special(p, SPWPN_REACHING); + break; + + + case WPN_SLING: + case WPN_HAND_CROSSBOW: + if (coinflip()) + break; + // **** possible intentional fall through here **** + case WPN_BOW: + case WPN_CROSSBOW: + if (one_chance_in(30)) + set_weapon_special( p, SPWPN_SPEED ); + + if (one_chance_in(5)) + set_weapon_special( p, SPWPN_PROTECTION ); + + if (coinflip()) + set_weapon_special(p, (coinflip() ? SPWPN_FLAME + : SPWPN_FROST)); + break; + + case WPN_BLOWGUN: + if (one_chance_in(7)) + set_weapon_special(p, SPWPN_VENOM); + break; + + // quarterstaff - not powerful, as this would make + // the 'staves' skill just too good + case WPN_QUARTERSTAFF: + if (one_chance_in(30)) + set_weapon_special(p, SPWPN_PAIN); + + if (one_chance_in(20)) + set_weapon_special(p, SPWPN_DISTORTION); + + if (one_chance_in(5)) + set_weapon_special(p, SPWPN_SPEED); + + if (one_chance_in(10)) + set_weapon_special(p, SPWPN_VORPAL); + + if (one_chance_in(5)) + set_weapon_special(p, SPWPN_PROTECTION); + break; + + + case WPN_DEMON_TRIDENT: + case WPN_DEMON_WHIP: + case WPN_DEMON_BLADE: + set_equip_race( mitm[p], ISFLAG_NO_RACE ); + + if (one_chance_in(10)) + set_weapon_special(p, SPWPN_PAIN); + + if (one_chance_in(3) + && (mitm[p].sub_type == WPN_DEMON_WHIP + || mitm[p].sub_type == WPN_DEMON_TRIDENT)) + { + set_weapon_special(p, SPWPN_REACHING); + } + + if (one_chance_in(5)) + set_weapon_special(p, SPWPN_DRAINING); + + if (one_chance_in(5)) + { + set_weapon_special(p, (coinflip() ? SPWPN_FLAMING + : SPWPN_FREEZING)); + } + + if (one_chance_in(5)) + set_weapon_special(p, SPWPN_ELECTROCUTION); + + if (one_chance_in(5)) + set_weapon_special(p, SPWPN_VAMPIRICISM); + + if (one_chance_in(5)) + set_weapon_special(p, SPWPN_VENOM); + break; + + // unlisted weapons have no associated, standard ego-types {dlb} + default: + break; + } + } // end if specially enchanted + + count++; + } + while (item_level == MAKE_GOOD_ITEM + && mitm[p].special == SPWPN_NORMAL + && count < 5); + + // if acquired item still not ego... enchant it up a bit. + if (item_level == MAKE_GOOD_ITEM && mitm[p].special == SPWPN_NORMAL) + { + mitm[p].plus += 2 + random2(3); + mitm[p].plus2 += 2 + random2(3); + } + + const int chance = (item_level == MAKE_GOOD_ITEM) ? 200 + : item_level; + + // odd-looking, but this is how the algorithm compacts {dlb}: + for (loopy = 0; loopy < 4; loopy++) + { + mitm[p].plus += random2(3); + + if (random2(350) > 20 + chance) + break; + } + + // odd-looking, but this is how the algorithm compacts {dlb}: + for (loopy = 0; loopy < 4; loopy++) + { + mitm[p].plus2 += random2(3); + + if (random2(500) > 50 + chance) + break; + } + } + else + { + if (one_chance_in(12)) + { + do_curse_item( mitm[p] ); + mitm[p].plus -= random2(4); + mitm[p].plus2 -= random2(4); + + // clear specials {dlb} + set_item_ego_type( mitm[p], OBJ_WEAPONS, SPWPN_NORMAL ); + } + } + + // value was "0" comment said "orc" so I went with comment {dlb} + if (cmp_equip_race( mitm[p], ISFLAG_ORCISH )) + { + // no holy wrath or slay orc and 1/2 the time no-ego + const int brand = get_weapon_brand( mitm[p] ); + if (brand == SPWPN_HOLY_WRATH + || brand == SPWPN_ORC_SLAYING + || (brand != SPWPN_NORMAL && coinflip())) + { + // this makes no sense {dlb} + // Probably a remnant of the old code which used + // to decrement this when the electric attack happened -- bwr + // if (brand == SPWPN_ELECTROCUTION) + // mitm[p].plus = 0; + + set_item_ego_type( mitm[p], OBJ_WEAPONS, SPWPN_NORMAL ); + } + } + + if ((((is_random_artefact( mitm[p] ) + || get_weapon_brand( mitm[p] ) != SPWPN_NORMAL) + && !one_chance_in(10)) + || ((mitm[p].plus != 0 || mitm[p].plus2 != 0) + && one_chance_in(3))) + && mitm[p].sub_type != WPN_CLUB + && mitm[p].sub_type != WPN_GIANT_CLUB + && mitm[p].sub_type != WPN_GIANT_SPIKED_CLUB + && cmp_equip_desc( mitm[p], 0 ) + && cmp_equip_race( mitm[p], 0 )) + { + set_equip_desc( mitm[p], (coinflip() ? ISFLAG_GLOWING + : ISFLAG_RUNED) ); + } + break; + + case OBJ_MISSILES: + quant = 0; + mitm[p].plus = 0; + mitm[p].special = SPMSL_NORMAL; + + temp_rand = random2(20); + mitm[p].sub_type = (temp_rand < 6) ? MI_STONE : // 30 % + (temp_rand < 10) ? MI_DART : // 20 % + (temp_rand < 14) ? MI_ARROW : // 20 % + (temp_rand < 18) ? MI_BOLT // 20 % + : MI_NEEDLE; // 10 % + + if (force_type != OBJ_RANDOM) + mitm[p].sub_type = force_type; + + // no fancy rocks -- break out before we get to racial/special stuff + if (mitm[p].sub_type == MI_LARGE_ROCK) + { + quant = 2 + random2avg(5,2); + break; + } + else if (mitm[p].sub_type == MI_STONE) + { + quant = 1 + random2(9) + random2(12) + random2(15) + random2(12); + break; + } + + // set racial type: + switch (item_race) + { + case MAKE_ITEM_ELVEN: + set_equip_race( mitm[p], ISFLAG_ELVEN ); + break; + + case MAKE_ITEM_DWARVEN: + set_equip_race( mitm[p], ISFLAG_DWARVEN ); + break; + + case MAKE_ITEM_ORCISH: + set_equip_race( mitm[p], ISFLAG_ORCISH ); + break; + + case MAKE_ITEM_RANDOM_RACE: + if ((mitm[p].sub_type == MI_ARROW + || mitm[p].sub_type == MI_DART) + && one_chance_in(4)) + { + // elven - not for bolts, though + set_equip_race( mitm[p], ISFLAG_ELVEN ); + } + + if ((mitm[p].sub_type == MI_ARROW + || mitm[p].sub_type == MI_BOLT + || mitm[p].sub_type == MI_DART) + && one_chance_in(4)) + { + set_equip_race( mitm[p], ISFLAG_ORCISH ); + } + + if ((mitm[p].sub_type == MI_DART + || mitm[p].sub_type == MI_BOLT) + && one_chance_in(6)) + { + set_equip_race( mitm[p], ISFLAG_DWARVEN ); + } + + if (mitm[p].sub_type == MI_NEEDLE) + { + if (one_chance_in(10)) + set_equip_race( mitm[p], ISFLAG_ELVEN ); + if (one_chance_in(6)) + set_equip_race( mitm[p], ISFLAG_ORCISH ); + } + break; + } + + // note that needles can only be poisoned + // + // Actually, it'd be really nice if there where + // some paralysis or slowing poison needles, just + // so that blowguns have some added utility over + // the other launchers/throwing weapons. -- bwr + if (mitm[p].sub_type == MI_NEEDLE + && (item_level == MAKE_GOOD_ITEM || !one_chance_in(5))) + { + set_item_ego_type( mitm[p], OBJ_MISSILES, SPMSL_POISONED_II ); + } + else + { + // decide specials: + if (item_level == MAKE_GOOD_ITEM) + temp_rand = random2(150); + else + temp_rand = random2(2000 - 55 * item_level); + + set_item_ego_type( mitm[p], OBJ_MISSILES, + (temp_rand < 60) ? SPMSL_FLAME : + (temp_rand < 120) ? SPMSL_ICE : + (temp_rand < 150) ? SPMSL_POISONED_II + : SPMSL_NORMAL ); + } + + // orcish ammo gets poisoned a lot more often -- in the original + // code it was poisoned every time!? + if (cmp_equip_race( mitm[p], ISFLAG_ORCISH ) && one_chance_in(3)) + set_item_ego_type( mitm[p], OBJ_MISSILES, SPMSL_POISONED_II ); + + // reduced quantity if special + if (get_ammo_brand( mitm[p] ) != SPMSL_NORMAL ) + quant = 1 + random2(9) + random2(12) + random2(12); + else + quant = 1 + random2(9) + random2(12) + random2(15) + random2(12); + + if (10 + item_level >= random2(100)) + mitm[p].plus += random2(5); + + // elven arrows and dwarven bolts are quality items + if ((cmp_equip_race( mitm[p], ISFLAG_ELVEN ) + && mitm[p].sub_type == MI_ARROW) + || (cmp_equip_race( mitm[p], ISFLAG_DWARVEN ) + && mitm[p].sub_type == MI_BOLT)) + { + mitm[p].plus += random2(3); + } + break; + + case OBJ_ARMOUR: + quant = 1; + + mitm[p].plus = 0; + mitm[p].plus2 = 0; + mitm[p].special = SPARM_NORMAL; + + if (force_type != OBJ_RANDOM) + mitm[p].sub_type = force_type; + else + { + mitm[p].sub_type = random2(3); + + if (random2(35) <= item_level + 10) + { + mitm[p].sub_type = random2(5); + if (one_chance_in(4)) + mitm[p].sub_type = ARM_ANIMAL_SKIN; + } + + if (random2(60) <= item_level + 10) + mitm[p].sub_type = random2(8); + + if (10 + item_level >= random2(400) && one_chance_in(20)) + mitm[p].sub_type = ARM_DRAGON_HIDE + random2(7); + + if (10 + item_level >= random2(500) && one_chance_in(20)) + { + mitm[p].sub_type = ARM_STEAM_DRAGON_HIDE + random2(11); + + if (mitm[p].sub_type == ARM_ANIMAL_SKIN && one_chance_in(20)) + mitm[p].sub_type = ARM_CRYSTAL_PLATE_MAIL; + } + + // secondary armours: + if (one_chance_in(5)) + { + mitm[p].sub_type = ARM_SHIELD + random2(5); + + if (mitm[p].sub_type == ARM_SHIELD) // 33.3% + { + if (coinflip()) + mitm[p].sub_type = ARM_BUCKLER; // 50.0% + else if (one_chance_in(3)) + mitm[p].sub_type = ARM_LARGE_SHIELD; // 16.7% + } + } + } + + if (mitm[p].sub_type == ARM_HELMET) + { + set_helmet_type( mitm[p], THELM_HELMET ); + set_helmet_desc( mitm[p], THELM_DESC_PLAIN ); + + if (one_chance_in(3)) + set_helmet_type( mitm[p], random2( THELM_NUM_TYPES ) ); + + if (one_chance_in(3)) + set_helmet_random_desc( mitm[p] ); + } + + if (allow_uniques == 1 + && item_level > 2 + && random2(2000) <= (100 + item_level * 3) + && coinflip()) + { + if ((you.level_type != LEVEL_ABYSS + && you.level_type != LEVEL_PANDEMONIUM) + && one_chance_in(50)) + { + icky = find_okay_unrandart(OBJ_ARMOUR); + if (icky != -1) + { + quant = 1; + make_item_unrandart( mitm[p], icky ); + break; + } + } + + hide2armour( &(mitm[p].sub_type) ); + + // mitm[p].special = SPARM_RANDART_II + random2(4); + make_item_randart( mitm[p] ); + mitm[p].plus = 0; + + if (mitm[p].sub_type == ARM_BOOTS) + { + mitm[p].plus2 = TBOOT_BOOTS; + if (one_chance_in(10)) + mitm[p].plus2 = random2( NUM_BOOT_TYPES ); + } + + mitm[p].plus += random2(4); + + if (one_chance_in(5)) + mitm[p].plus += random2(4); + + if (one_chance_in(6)) + mitm[p].plus -= random2(8); + + quant = 1; + + if (one_chance_in(5)) + { + do_curse_item( mitm[p] ); + mitm[p].plus = -random2(6); + } + else if (mitm[p].plus < 0 && !one_chance_in(3)) + { + do_curse_item( mitm[p] ); + } + break; + } + + mitm[p].plus = 0; + + if (item_race == MAKE_ITEM_RANDOM_RACE && coinflip()) + { + switch (mitm[p].sub_type) + { + case ARM_SHIELD: // shield - must do special things for this! + case ARM_BUCKLER: + case ARM_LARGE_SHIELD: + if (one_chance_in(4)) + set_equip_race( mitm[p], ISFLAG_ELVEN ); + if (one_chance_in(3)) + set_equip_race( mitm[p], ISFLAG_DWARVEN ); + break; + + case ARM_CLOAK: + if (one_chance_in(4)) + set_equip_race( mitm[p], ISFLAG_ORCISH ); + if (one_chance_in(4)) + set_equip_race( mitm[p], ISFLAG_DWARVEN ); + if (one_chance_in(4)) + set_equip_race( mitm[p], ISFLAG_ELVEN ); + break; + + case ARM_GLOVES: + if (one_chance_in(4)) + set_equip_race( mitm[p], ISFLAG_ELVEN ); + break; + + case ARM_BOOTS: + if (one_chance_in(4)) + { + mitm[p].plus2 = TBOOT_NAGA_BARDING; + break; + } + + if (one_chance_in(4)) + { + mitm[p].plus2 = TBOOT_CENTAUR_BARDING; + break; + } + + if (one_chance_in(4)) + set_equip_race( mitm[p], ISFLAG_ORCISH ); + if (one_chance_in(4)) + set_equip_race( mitm[p], ISFLAG_ELVEN ); + if (one_chance_in(6)) + set_equip_race( mitm[p], ISFLAG_DWARVEN ); + break; + + case ARM_HELMET: + if (cmp_helmet_type( mitm[p], THELM_CAP ) + || cmp_helmet_type( mitm[p], THELM_WIZARD_HAT )) + { + if (one_chance_in(6)) + set_equip_race( mitm[p], ISFLAG_ELVEN ); + } + else + { + // helms and helmets + if (one_chance_in(8)) + set_equip_race( mitm[p], ISFLAG_ORCISH ); + if (one_chance_in(6)) + set_equip_race( mitm[p], ISFLAG_DWARVEN ); + } + break; + + case ARM_ROBE: + if (one_chance_in(4)) + set_equip_race( mitm[p], ISFLAG_ELVEN ); + break; + + case ARM_RING_MAIL: + case ARM_SCALE_MAIL: + case ARM_CHAIN_MAIL: + case ARM_SPLINT_MAIL: + case ARM_BANDED_MAIL: + case ARM_PLATE_MAIL: + if (mitm[p].sub_type <= ARM_CHAIN_MAIL && one_chance_in(6)) + set_equip_race( mitm[p], ISFLAG_ELVEN ); + if (mitm[p].sub_type >= ARM_RING_MAIL && one_chance_in(5)) + set_equip_race( mitm[p], ISFLAG_DWARVEN ); + if (one_chance_in(5)) + set_equip_race( mitm[p], ISFLAG_ORCISH ); + + default: // skins, hides, crystal plate are always plain + break; + } + } + + switch (item_race) + { + case MAKE_ITEM_ELVEN: + set_equip_race( mitm[p], ISFLAG_ELVEN ); + break; + + case MAKE_ITEM_DWARVEN: + set_equip_race( mitm[p], ISFLAG_DWARVEN ); + if (coinflip()) + mitm[p].plus++; + break; + + case MAKE_ITEM_ORCISH: + set_equip_race( mitm[p], ISFLAG_ORCISH ); + break; + } + + + if (50 + item_level >= random2(250) + || item_level == MAKE_GOOD_ITEM + || (mitm[p].sub_type == ARM_HELMET + && cmp_helmet_type( mitm[p], THELM_WIZARD_HAT ))) + { + mitm[p].plus += random2(3); + + if (mitm[p].sub_type <= ARM_PLATE_MAIL && 20 + item_level >= random2(300)) + mitm[p].plus += random2(3); + + if (30 + item_level >= random2(350) + && (item_level == MAKE_GOOD_ITEM + || (!cmp_equip_race( mitm[p], ISFLAG_ORCISH ) + || (mitm[p].sub_type <= ARM_PLATE_MAIL && coinflip())))) + { + switch (mitm[p].sub_type) + { + case ARM_SHIELD: // shield - must do special things for this! + case ARM_LARGE_SHIELD: + case ARM_BUCKLER: + set_item_ego_type( mitm[p], OBJ_ARMOUR, SPARM_PROTECTION ); + break; // prot + //break; + + case ARM_CLOAK: + if (cmp_equip_race( mitm[p], ISFLAG_DWARVEN )) + break; + + switch (random2(4)) + { + case 0: + set_item_ego_type( mitm[p], + OBJ_ARMOUR, SPARM_POISON_RESISTANCE ); + break; + + case 1: + set_item_ego_type( mitm[p], + OBJ_ARMOUR, SPARM_DARKNESS ); + break; + case 2: + set_item_ego_type( mitm[p], + OBJ_ARMOUR, SPARM_MAGIC_RESISTANCE ); + break; + case 3: + set_item_ego_type( mitm[p], + OBJ_ARMOUR, SPARM_PRESERVATION ); + break; + } + break; + + case ARM_HELMET: + if (cmp_helmet_type(mitm[p],THELM_WIZARD_HAT) && coinflip()) + { + if (one_chance_in(3)) + { + set_item_ego_type( mitm[p], + OBJ_ARMOUR, SPARM_MAGIC_RESISTANCE ); + } + else + { + set_item_ego_type( mitm[p], + OBJ_ARMOUR, SPARM_INTELLIGENCE ); + } + } + else + { + set_item_ego_type( mitm[p], OBJ_ARMOUR, + coinflip() ? SPARM_SEE_INVISIBLE + : SPARM_INTELLIGENCE ); + } + break; + + case ARM_GLOVES: + set_item_ego_type( mitm[p], OBJ_ARMOUR, + coinflip() ? SPARM_DEXTERITY + : SPARM_STRENGTH ); + break; + + case ARM_BOOTS: + switch (random2(3)) + { + case 0: + if (mitm[p].plus2 == TBOOT_BOOTS) + set_item_ego_type(mitm[p], OBJ_ARMOUR, SPARM_RUNNING); + break; + case 1: + set_item_ego_type(mitm[p], OBJ_ARMOUR, SPARM_LEVITATION); + break; + case 2: + set_item_ego_type(mitm[p], OBJ_ARMOUR, SPARM_STEALTH); + break; + } + break; + + case ARM_ROBE: + switch (random2(4)) + { + case 0: + set_item_ego_type( mitm[p], OBJ_ARMOUR, + coinflip() ? SPARM_COLD_RESISTANCE + : SPARM_FIRE_RESISTANCE ); + break; + + case 1: + set_item_ego_type( mitm[p], + OBJ_ARMOUR, SPARM_MAGIC_RESISTANCE ); + break; + + case 2: + set_item_ego_type( mitm[p], OBJ_ARMOUR, + coinflip() ? SPARM_POSITIVE_ENERGY + : SPARM_RESISTANCE ); + break; + case 3: + if (force_type != OBJ_RANDOM + || is_random_artefact( mitm[p] ) + || get_armour_ego_type( mitm[p] ) != SPARM_NORMAL + || random2(50) > 10 + item_level) + { + break; + } + + set_item_ego_type( mitm[p], OBJ_ARMOUR, SPARM_ARCHMAGI ); + break; + } + break; + + default: // other body armours: + set_item_ego_type( mitm[p], OBJ_ARMOUR, + coinflip() ? SPARM_COLD_RESISTANCE + : SPARM_FIRE_RESISTANCE ); + + if (one_chance_in(9)) + { + set_item_ego_type( mitm[p], + OBJ_ARMOUR, SPARM_POSITIVE_ENERGY ); + } + + if (one_chance_in(5)) + { + set_item_ego_type( mitm[p], + OBJ_ARMOUR, SPARM_MAGIC_RESISTANCE ); + } + + if (one_chance_in(5)) + { + set_item_ego_type( mitm[p], + OBJ_ARMOUR, SPARM_POISON_RESISTANCE ); + } + + if (mitm[p].sub_type == ARM_PLATE_MAIL + && one_chance_in(15)) + { + set_item_ego_type( mitm[p], + OBJ_ARMOUR, SPARM_PONDEROUSNESS ); + mitm[p].plus += 3 + random2(4); + } + break; + } + } + } + else if (one_chance_in(12)) + { + // mitm[p].plus = (coinflip() ? 99 : 98); // 98? 99? + do_curse_item( mitm[p] ); + + if (one_chance_in(5)) + mitm[p].plus -= random2(3); + + set_item_ego_type( mitm[p], OBJ_ARMOUR, SPARM_NORMAL ); + } + + // if not given a racial type, and special, give shiny/runed/etc desc. + if (cmp_equip_race( mitm[p], 0 ) + && cmp_equip_desc( mitm[p], 0 ) + && (((is_random_artefact(mitm[p]) + || get_armour_ego_type( mitm[p] ) != SPARM_NORMAL) + && !one_chance_in(10)) + || (mitm[p].plus != 0 && one_chance_in(3)))) + { + switch (random2(3)) + { + case 0: + set_equip_desc( mitm[p], ISFLAG_GLOWING ); + break; + + case 1: + set_equip_desc( mitm[p], ISFLAG_RUNED ); + break; + + case 2: + default: + set_equip_desc( mitm[p], ISFLAG_EMBROIDERED_SHINY ); + break; + } + } + + // Make sure you don't get a hide from acquirement (since that + // would be an enchanted item which somehow didn't get converted + // into armour). + if (item_level == MAKE_GOOD_ITEM) + hide2armour( &(mitm[p].sub_type) ); // what of animal hides? {dlb} + + // skin armours + Crystal PM don't get special enchantments + // or species, but can be randarts + if (mitm[p].sub_type >= ARM_DRAGON_HIDE + && mitm[p].sub_type <= ARM_SWAMP_DRAGON_ARMOUR) + { + set_equip_race( mitm[p], ISFLAG_NO_RACE ); + set_item_ego_type( mitm[p], OBJ_ARMOUR, SPARM_NORMAL ); + } + break; + + case OBJ_WANDS: + // determine sub_type: + if (force_type != OBJ_RANDOM) + mitm[p].sub_type = force_type; + else + { + mitm[p].sub_type = random2( NUM_WANDS ); + + // Adjusted distribution here -- bwr + // Wands used to be uniform (5.26% each) + // + // Now: + // invis, hasting, healing (1.11% each) + // fireball, teleportaion (3.74% each) + // others (6.37% each) + if ((mitm[p].sub_type == WAND_INVISIBILITY + || mitm[p].sub_type == WAND_HASTING + || mitm[p].sub_type == WAND_HEALING) + || ((mitm[p].sub_type == WAND_FIREBALL + || mitm[p].sub_type == WAND_TELEPORTATION) + && coinflip())) + { + mitm[p].sub_type = random2( NUM_WANDS ); + } + } + + // determine upper bound on charges: + range_charges = ((mitm[p].sub_type == WAND_HEALING + || mitm[p].sub_type == WAND_HASTING + || mitm[p].sub_type == WAND_INVISIBILITY) ? 8 : + (mitm[p].sub_type == WAND_FLAME + || mitm[p].sub_type == WAND_FROST + || mitm[p].sub_type == WAND_MAGIC_DARTS + || mitm[p].sub_type == WAND_RANDOM_EFFECTS) ? 28 + : 16); + + // generate charges randomly: + mitm[p].plus = random2avg(range_charges, 3); + // + // set quantity to one: + quant = 1; + break; + + case OBJ_FOOD: // this can be parsed out {dlb} + // determine sub_type: + if (force_type == OBJ_RANDOM) + { + temp_rand = random2(1000); + + mitm[p].sub_type = + ((temp_rand >= 750) ? FOOD_MEAT_RATION : // 25.00% chance + (temp_rand >= 450) ? FOOD_BREAD_RATION :// 30.00% chance + (temp_rand >= 350) ? FOOD_PEAR : // 10.00% chance + (temp_rand >= 250) ? FOOD_APPLE : // 10.00% chance + (temp_rand >= 150) ? FOOD_CHOKO : // 10.00% chance + (temp_rand >= 140) ? FOOD_CHEESE : // 1.00% chance + (temp_rand >= 130) ? FOOD_PIZZA : // 1.00% chance + (temp_rand >= 120) ? FOOD_SNOZZCUMBER : // 1.00% chance + (temp_rand >= 110) ? FOOD_APRICOT : // 1.00% chance + (temp_rand >= 100) ? FOOD_ORANGE : // 1.00% chance + (temp_rand >= 90) ? FOOD_BANANA : // 1.00% chance + (temp_rand >= 80) ? FOOD_STRAWBERRY : // 1.00% chance + (temp_rand >= 70) ? FOOD_RAMBUTAN : // 1.00% chance + (temp_rand >= 60) ? FOOD_LEMON : // 1.00% chance + (temp_rand >= 50) ? FOOD_GRAPE : // 1.00% chance + (temp_rand >= 40) ? FOOD_SULTANA : // 1.00% chance + (temp_rand >= 30) ? FOOD_LYCHEE : // 1.00% chance + (temp_rand >= 20) ? FOOD_BEEF_JERKY : // 1.00% chance + (temp_rand >= 10) ? FOOD_SAUSAGE : // 1.00% chance + (temp_rand >= 5) ? FOOD_HONEYCOMB // 0.50% chance + : FOOD_ROYAL_JELLY );// 0.50% chance + } + else + mitm[p].sub_type = force_type; + + // Happens with ghoul food acquirement -- use place_chunks() outherwise + if (mitm[p].sub_type == FOOD_CHUNK) + { + for (count = 0; count < 1000; count++) + { + temp_rand = random2( NUM_MONSTERS ); // random monster + temp_rand = mons_charclass( temp_rand ); // corpse base type + + if (mons_weight( temp_rand ) > 0) // drops a corpse + break; + } + + // set chunk flavour (default to common dungeon rat steaks): + mitm[p].plus = (count == 1000) ? MONS_RAT : temp_rand; + + // set duration + mitm[p].special = (10 + random2(11)) * 10; + } + + // determine quantity: + if (allow_uniques > 1) + quant = allow_uniques; + else + { + quant = 1; + + if (mitm[p].sub_type != FOOD_MEAT_RATION + && mitm[p].sub_type != FOOD_BREAD_RATION) + { + if (one_chance_in(80)) + quant += random2(3); + + if (mitm[p].sub_type == FOOD_STRAWBERRY + || mitm[p].sub_type == FOOD_GRAPE + || mitm[p].sub_type == FOOD_SULTANA) + { + quant += 3 + random2avg(15,2); + } + } + } + break; + + case OBJ_POTIONS: + quant = 1; + + if (one_chance_in(18)) + quant++; + + if (one_chance_in(25)) + quant++; + + if (force_type != OBJ_RANDOM) + mitm[p].sub_type = force_type; + else + { + temp_rand = random2(9); // general type of potion; + + switch (temp_rand) + { + case 0: + case 1: + case 2: + case 8: + // healing potions + if (one_chance_in(3)) + mitm[p].sub_type = POT_HEAL_WOUNDS; // 14.074% + else + mitm[p].sub_type = POT_HEALING; // 28.148% + + if (one_chance_in(20)) + mitm[p].sub_type = POT_CURE_MUTATION; // 2.222% + break; + + case 3: + case 4: + // enhancements + if (coinflip()) + mitm[p].sub_type = POT_SPEED; // 6.444% + else + mitm[p].sub_type = POT_MIGHT; // 6.444% + + if (one_chance_in(10)) + mitm[p].sub_type = POT_BERSERK_RAGE; // 1.432% + + if (one_chance_in(5)) + mitm[p].sub_type = POT_INVISIBILITY; // 3.580% + + if (one_chance_in(6)) + mitm[p].sub_type = POT_LEVITATION; // 3.580% + + if (one_chance_in(30)) + mitm[p].sub_type = POT_PORRIDGE; // 0.741% + break; + + case 5: + // gain ability + mitm[p].sub_type = POT_GAIN_STRENGTH + random2(3); // 1.125% + // or 0.375% each + + if (one_chance_in(10)) + mitm[p].sub_type = POT_EXPERIENCE; // 0.125% + + if (one_chance_in(10)) + mitm[p].sub_type = POT_MAGIC; // 0.139% + + if (!one_chance_in(8)) + mitm[p].sub_type = POT_RESTORE_ABILITIES; // 9.722% + + quant = 1; + break; + + case 6: + case 7: + // bad things + switch (random2(6)) + { + case 0: + case 4: + // is this not always the case? - no, level one is 0 {dlb} + if (item_level > 0) + { + mitm[p].sub_type = POT_POISON; // 6.475% + + if (item_level > 10 && one_chance_in(4)) + mitm[p].sub_type = POT_STRONG_POISON; + + break; + } + + /* **** intentional fall through **** */ // ignored for % + case 5: + if (item_level > 6) + { + mitm[p].sub_type = POT_MUTATION; // 3.237% + break; + } + + /* **** intentional fall through **** */ // ignored for % + case 1: + mitm[p].sub_type = POT_SLOWING; // 3.237% + break; + + case 2: + mitm[p].sub_type = POT_PARALYSIS; // 3.237% + break; + + case 3: + mitm[p].sub_type = POT_CONFUSION; // 3.237% + break; + + } + + if (one_chance_in(8)) + mitm[p].sub_type = POT_DEGENERATION; // 2.775% + + if (one_chance_in(1000)) // 0.022% + mitm[p].sub_type = POT_DECAY; + + break; + } + } + + mitm[p].plus = 0; + break; + + case OBJ_SCROLLS: + // determine sub_type: + if (force_type == OBJ_RANDOM) + { + // only used in certain cases {dlb} + int depth_mod = random2(1 + item_level); + + temp_rand = random2(920); + + mitm[p].sub_type = + ((temp_rand > 751) ? SCR_IDENTIFY : // 18.26% + (temp_rand > 629) ? SCR_REMOVE_CURSE : // 13.26% + (temp_rand > 554) ? SCR_TELEPORTATION : // 8.15% + (temp_rand > 494) ? SCR_DETECT_CURSE : // 6.52% + (temp_rand > 464) ? SCR_FEAR : // 3.26% + (temp_rand > 434) ? SCR_NOISE : // 3.26% + (temp_rand > 404) ? SCR_MAGIC_MAPPING : // 3.26% + (temp_rand > 374) ? SCR_FORGETFULNESS : // 3.26% + (temp_rand > 344) ? SCR_RANDOM_USELESSNESS :// 3.26% + (temp_rand > 314) ? SCR_CURSE_WEAPON : // 3.26% + (temp_rand > 284) ? SCR_CURSE_ARMOUR : // 3.26% + (temp_rand > 254) ? SCR_RECHARGING : // 3.26% + (temp_rand > 224) ? SCR_BLINKING : // 3.26% + (temp_rand > 194) ? SCR_PAPER : // 3.26% + (temp_rand > 164) ? SCR_ENCHANT_ARMOUR : // 3.26% + (temp_rand > 134) ? SCR_ENCHANT_WEAPON_I : // 3.26% + (temp_rand > 104) ? SCR_ENCHANT_WEAPON_II : // 3.26% + + // Crawl is kind to newbie adventurers {dlb}: + // yes -- these five are messy {dlb}: + // yes they are a hellish mess of tri-ops and long lines, + // this formating is somewhat better -- bwr + (temp_rand > 74) ? + ((item_level < 4) ? SCR_TELEPORTATION + : SCR_IMMOLATION) : // 3.26% + (temp_rand > 59) ? + ((depth_mod < 4) ? SCR_TELEPORTATION + : SCR_ACQUIREMENT) : // 1.63% + (temp_rand > 44) ? + ((depth_mod < 4) ? SCR_DETECT_CURSE + : SCR_SUMMONING) : // 1.63% + (temp_rand > 29) ? + ((depth_mod < 4) ? SCR_TELEPORTATION // 1.63% + : SCR_ENCHANT_WEAPON_III) : + (temp_rand > 14) ? + ((depth_mod < 7) ? SCR_DETECT_CURSE + : SCR_TORMENT) // 1.63% + // default: + : ((depth_mod < 7) ? SCR_TELEPORTATION // 1.63% + : SCR_VORPALISE_WEAPON)); + } + else + mitm[p].sub_type = force_type; + + // determine quantity: + temp_rand = random2(48); + + quant = ((temp_rand > 1 + || mitm[p].sub_type == SCR_VORPALISE_WEAPON + || mitm[p].sub_type == SCR_ENCHANT_WEAPON_III + || mitm[p].sub_type == SCR_ACQUIREMENT + || mitm[p].sub_type == SCR_TORMENT) ? 1 : // 95.83% + (temp_rand == 0) ? 2 // 2.08% + : 3); // 2.08% + mitm[p].plus = 0; + break; + + case OBJ_JEWELLERY: + // determine whether an unrandart will be generated {dlb}: + if (item_level > 2 + && you.level_type != LEVEL_ABYSS + && you.level_type != LEVEL_PANDEMONIUM + && random2(2000) <= 100 + (item_level * 3) + && one_chance_in(20)) + { + icky = find_okay_unrandart(OBJ_JEWELLERY); + + if (icky != -1) + { + quant = 1; + make_item_unrandart( mitm[p], icky ); + break; + } + } + + // otherwise, determine jewellery type {dlb}: + if (force_type == OBJ_RANDOM) + { + mitm[p].sub_type = (!one_chance_in(4) ? random2(24) // rings + : AMU_RAGE + random2(10)); + + // Adjusted distribution here -- bwr + if ((mitm[p].sub_type == RING_INVISIBILITY + || mitm[p].sub_type == RING_REGENERATION + || mitm[p].sub_type == RING_TELEPORT_CONTROL + || mitm[p].sub_type == RING_SLAYING) + && !one_chance_in(3)) + { + mitm[p].sub_type = random2(24); + } + } + else + mitm[p].sub_type = force_type; + + // quantity is always one {dlb}: + quant = 1; + + // everything begins as uncursed, unenchanted jewellery {dlb}: + mitm[p].plus = 0; + mitm[p].plus2 = 0; + + // set pluses for rings that require them {dlb}: + switch (mitm[p].sub_type) + { + case RING_PROTECTION: + case RING_STRENGTH: + case RING_SLAYING: + case RING_EVASION: + case RING_DEXTERITY: + case RING_INTELLIGENCE: + if (one_chance_in(5)) // 20% of such rings are cursed {dlb} + { + do_curse_item( mitm[p] ); + mitm[p].plus = (coinflip() ? -2 : -3); + + if (one_chance_in(3)) + mitm[p].plus -= random2(4); + } + else + { + mitm[p].plus += 1 + (one_chance_in(3) ? random2(3) + : random2avg(6, 2)); + } + break; + + default: + break; + } + + // rings of slaying also require that pluses2 be set {dlb}: + if (mitm[p].sub_type == RING_SLAYING) + { + if (item_cursed( mitm[p] ) && !one_chance_in(20)) + mitm[p].plus2 = -1 - random2avg(6, 2); + else + { + mitm[p].plus2 += 1 + (one_chance_in(3) ? random2(3) + : random2avg(6, 2)); + + if (random2(25) < 9) // 36% of such rings {dlb} + { + // make "ring of damage" + do_uncurse_item( mitm[p] ); + mitm[p].plus = 0; + mitm[p].plus2 += 2; + } + } + } + + // All jewellery base types should now work. -- bwr + if (allow_uniques == 1 && item_level > 2 + && random2(2000) <= 100 + (item_level * 3) && coinflip()) + { + make_item_randart( mitm[p] ); + break; + } + + // rings of hunger and teleportation are always cursed {dlb}: + if (mitm[p].sub_type == RING_HUNGER + || mitm[p].sub_type == RING_TELEPORTATION + || one_chance_in(50)) + { + do_curse_item( mitm[p] ); + } + break; + + case OBJ_BOOKS: + create_book: + do + { + mitm[p].sub_type = random2(NUM_BOOKS); + + if (book_rarity(mitm[p].sub_type) == 100) + continue; + + if (mitm[p].sub_type != BOOK_DESTRUCTION + && mitm[p].sub_type != BOOK_MANUAL) + { + if (one_chance_in(10)) + { + if (coinflip()) + mitm[p].sub_type = BOOK_WIZARDRY; + else + mitm[p].sub_type = BOOK_POWER; + } + + if (random2(item_level + 1) + 1 >= book_rarity(mitm[p].sub_type) + || one_chance_in(100)) + { + break; + } + else + { + mitm[p].sub_type = BOOK_DESTRUCTION; + continue; + } + } + } + while (mitm[p].sub_type == BOOK_DESTRUCTION + || mitm[p].sub_type == BOOK_MANUAL); + + if (book_rarity(mitm[p].sub_type) == 100) + goto create_book; + + mitm[p].special = random2(5); + + if (one_chance_in(10)) + mitm[p].special += random2(8) * 10; + + if (force_type != OBJ_RANDOM) + mitm[p].sub_type = force_type; + + quant = 1; + + // tome of destruction : rare! + if (force_type == BOOK_DESTRUCTION + || (random2(7000) <= item_level + 20 && item_level > 10 + && force_type == OBJ_RANDOM)) + { + mitm[p].sub_type = BOOK_DESTRUCTION; + } + + // skill manuals - also rare + // fixed to generate manuals for *all* extant skills - 14mar2000 {dlb} + if (force_type == BOOK_MANUAL + || (random2(4000) <= item_level + 20 && item_level > 6 + && force_type == OBJ_RANDOM)) + { + mitm[p].sub_type = BOOK_MANUAL; + + if (one_chance_in(4)) + { + mitm[p].plus = SK_SPELLCASTING + + random2(NUM_SKILLS - SK_SPELLCASTING); + } + else + { + mitm[p].plus = random2(SK_UNARMED_COMBAT); + + if (mitm[p].plus == SK_UNUSED_1) + mitm[p].plus = SK_UNARMED_COMBAT; + } + } + break; + + case OBJ_STAVES: // this can be parsed, too {dlb} + if (force_type != OBJ_RANDOM) + mitm[p].sub_type = force_type; + else + { + mitm[p].sub_type = random2(13); + + // top three non-spell staves are in separate block -- bwr + if (mitm[p].sub_type >= 10) + mitm[p].sub_type = STAFF_AIR + mitm[p].sub_type - 10; + + // spell staves + if (one_chance_in(20)) + mitm[p].sub_type = STAFF_SMITING + random2(10); + + if ((mitm[p].sub_type == STAFF_ENERGY + || mitm[p].sub_type == STAFF_CHANNELING) && one_chance_in(4)) + { + mitm[p].sub_type = coinflip() ? STAFF_WIZARDRY : STAFF_POWER; + } + } + + mitm[p].special = random2(9); + + quant = 1; + break; + + case OBJ_ORBS: // always forced in current setup {dlb} + quant = 1; + + if (force_type != OBJ_RANDOM) + mitm[p].sub_type = force_type; + + // I think we only have one type of orb now, so ... {dlb} + set_unique_item_status( OBJ_ORBS, mitm[p].sub_type, UNIQ_EXISTS ); + break; + + // I think these must always be forced, too ... {dlb} + + case OBJ_MISCELLANY: //mv: rewrote with use of NUM_MISCELLANY (9 Aug 01) + if (force_type == OBJ_RANDOM) + { + do + mitm[p].sub_type = random2(NUM_MISCELLANY); + while //mv: never generated + ((mitm[p].sub_type == MISC_RUNE_OF_ZOT) + || (mitm[p].sub_type == MISC_HORN_OF_GERYON) + || (mitm[p].sub_type == MISC_PORTABLE_ALTAR_OF_NEMELEX) + // mv: others are possible but less often + // btw. chances of generating decks are almost the same as + // before, other chances are now distributed more steadily + || (mitm[p].sub_type == MISC_DECK_OF_POWER && !one_chance_in(12)) + || (mitm[p].sub_type == MISC_DECK_OF_SUMMONINGS && !one_chance_in(3)) + || (mitm[p].sub_type == MISC_DECK_OF_TRICKS && !one_chance_in(3)) + || (mitm[p].sub_type == MISC_DECK_OF_WONDERS && !one_chance_in(3)) + ); + + // filling those silly empty boxes -- bwr + if (mitm[p].sub_type == MISC_EMPTY_EBONY_CASKET + && !one_chance_in(20)) + { + mitm[p].sub_type = MISC_BOX_OF_BEASTS; + } + } + else + { + mitm[p].sub_type = force_type; + } + + if (mitm[p].sub_type == MISC_DECK_OF_WONDERS + || mitm[p].sub_type == MISC_DECK_OF_SUMMONINGS + || mitm[p].sub_type == MISC_DECK_OF_POWER) + { + mitm[p].plus = 4 + random2(10); + } + + if (mitm[p].sub_type == MISC_DECK_OF_TRICKS) + mitm[p].plus = 6 + random2avg(15, 2); + + if (mitm[p].sub_type == MISC_RUNE_OF_ZOT) + mitm[p].plus = item_race; + + quant = 1; + break; // mv: end of rewrote; + + // that is, everything turns to gold if not enumerated above, so ... {dlb} + default: + mitm[p].base_type = OBJ_GOLD; + + // Note that acquirement level gold gives much less than the + // price of a scroll of acquirement (520 gold). -- bwr + if (item_level == MAKE_GOOD_ITEM) + quant = 50 + random2avg(100, 2) + random2avg(100, 2); + else + quant = 1 + random2avg(19, 2) + random2(item_level); + break; + } + + mitm[p].quantity = quant; + + // should really only be used for monster inventories. + if (dont_place) + { + mitm[p].x = 0; + mitm[p].y = 0; + mitm[p].link = NON_ITEM; + } + else + { + do + { + x_pos = random2(GXM); + y_pos = random2(GYM); + } + while (grd[x_pos][y_pos] != DNGN_FLOOR); + + move_item_to_grid( &p, x_pos, y_pos ); + } + + item_colour( mitm[p] ); + + // Okay, this check should be redundant since the purpose of + // this function is to create valid items. Still, we're adding + // this safety for fear that a report of Trog giving a non-existant + // item might symbolize something more serious. -- bwr + return (is_valid_item( mitm[p] ) ? p : NON_ITEM); +} // end items() + + +void give_item(int mid, int level_number) //mv: cleanup+minor changes +{ + int temp_rand = 0; // probability determination {dlb} + + int bp = 0; + int thing_created = 0; + int hand_used = 0; // for Ettins etc. + int xitc = 0; + int xitt = 0; + + int iquan = 0; + // forces colour and quantity, too for intial weapons {dlb} + int force_item = 0; + + int item_race = MAKE_ITEM_RANDOM_RACE; + int give_level = level_number; + + //mv: THIS CODE DISTRIBUTES WANDS/SCROLLS/POTIONS + //(now only to uniques but it's easy to modify that) + //7 Aug 01 + + //mv - give scroll + + if (mons_is_unique( menv[mid].type ) && one_chance_in(3)) + { + thing_created = items(0, OBJ_SCROLLS, OBJ_RANDOM, true, give_level, 0); + if (thing_created == NON_ITEM) + return; + + mitm[thing_created].flags = 0; + menv[mid].inv[MSLOT_SCROLL] = thing_created; + } + + //mv - give wand + if (mons_is_unique( menv[mid].type ) && one_chance_in(5)) + { + thing_created = items(0, OBJ_WANDS, OBJ_RANDOM, true, give_level, 0); + if (thing_created == NON_ITEM) + return; + + mitm[thing_created].flags = 0; + menv[mid].inv[MSLOT_WAND] = thing_created; + } + + //mv - give potion + if (mons_is_unique( menv[mid].type ) && one_chance_in(3)) + { + thing_created = items(0, OBJ_POTIONS, OBJ_RANDOM, true, give_level, 0); + if (thing_created == NON_ITEM) + return; + + mitm[thing_created].flags = 0; + menv[mid].inv[MSLOT_POTION] = thing_created; + } + + + //end of DISTRIBUTE WANDS/POTIONS/SCROLLS CODE + + bp = get_item_slot(); + if (bp == NON_ITEM) + return; + + mitm[bp].quantity = 0; // set below if force_item, else we toss this item! + mitm[bp].plus = 0; + mitm[bp].plus2 = 0; + mitm[bp].special = 0; + + // this flags things to "goto give_armour" below ... {dlb} + mitm[bp].base_type = 101; + + if (menv[mid].type == MONS_DANCING_WEAPON + && player_in_branch( BRANCH_HALL_OF_BLADES )) + { + give_level = MAKE_GOOD_ITEM; + } + + // moved setting of quantity here to keep it in mind {dlb} + iquan = 1; + // I wonder if this is even used, given calls to item() {dlb} + + + switch (menv[mid].type) + { + case MONS_KOBOLD: + // a few of the smarter kobolds have blowguns. + if (one_chance_in(15) && level_number > 1) + { + mitm[bp].base_type = OBJ_WEAPONS; + mitm[bp].sub_type = WPN_BLOWGUN; + break; + } + // intentional fallthrough + case MONS_BIG_KOBOLD: + if (random2(5) < 3) // give hand weapon + { + mitm[bp].base_type = OBJ_WEAPONS; + + temp_rand = random2(5); + mitm[bp].sub_type = ((temp_rand > 2) ? WPN_DAGGER : // 40% + (temp_rand > 0) ? WPN_SHORT_SWORD // 40% + : WPN_CLUB); // 20% + } + else if (random2(5) < 2) // give darts + { + item_race = MAKE_ITEM_NO_RACE; + mitm[bp].base_type = OBJ_MISSILES; + mitm[bp].sub_type = MI_DART; + iquan = 1 + random2(5); + } + else + goto give_ammo; + break; + + case MONS_HOBGOBLIN: + if (one_chance_in(3)) + item_race = MAKE_ITEM_ORCISH; + + if (random2(5) < 3) // give hand weapon + { + mitm[bp].base_type = OBJ_WEAPONS; + mitm[bp].sub_type = WPN_CLUB; + } + else + goto give_ammo; + break; + + case MONS_GOBLIN: + if (one_chance_in(3)) + item_race = MAKE_ITEM_ORCISH; + + if (one_chance_in(12) && level_number > 1) + { + mitm[bp].base_type = OBJ_WEAPONS; + mitm[bp].base_type = WPN_BLOWGUN; + break; + } + // deliberate fall through {dlb} + case MONS_JESSICA: + case MONS_IJYB: + if (random2(5) < 3) // < 1 // give hand weapon + { + mitm[bp].base_type = OBJ_WEAPONS; + mitm[bp].sub_type = (coinflip() ? WPN_DAGGER : WPN_CLUB); + } + else + goto give_ammo; + break; + + case MONS_WIGHT: + case MONS_NORRIS: + mitm[bp].base_type = OBJ_WEAPONS; + mitm[bp].sub_type = (one_chance_in(6) ? WPN_WAR_AXE + random2(4) + : WPN_MACE + random2(12)); + + if (coinflip()) + { + force_item = 1; + item_race = MAKE_ITEM_NO_RACE; + mitm[bp].plus += 1 + random2(3); + mitm[bp].plus2 += 1 + random2(3); + + if (one_chance_in(5)) + set_item_ego_type( mitm[bp], OBJ_WEAPONS, SPWPN_FREEZING ); + } + + if (one_chance_in(3)) + do_curse_item( mitm[bp] ); + break; + + case MONS_GNOLL: + case MONS_OGRE_MAGE: + case MONS_NAGA_WARRIOR: + case MONS_GREATER_NAGA: + case MONS_EDMUND: + case MONS_DUANE: + item_race = MAKE_ITEM_NO_RACE; + + if (!one_chance_in(5)) + { + mitm[bp].base_type = OBJ_WEAPONS; + + temp_rand = random2(5); + mitm[bp].sub_type = ((temp_rand > 2) ? WPN_SPEAR : // 40% + (temp_rand == 2) ? WPN_FLAIL : // 20% + (temp_rand == 1) ? WPN_HALBERD // 20% + : WPN_CLUB); // 20% + } + break; + + case MONS_ORC: + if (one_chance_in(15) && level_number > 1) + { + mitm[bp].base_type = OBJ_WEAPONS; + mitm[bp].base_type = WPN_BLOWGUN; + break; + } + // deliberate fall through {gdl} + case MONS_ORC_PRIEST: + item_race = MAKE_ITEM_ORCISH; + // deliberate fall through {dlb} + case MONS_TERENCE: + if (!one_chance_in(5)) + { + mitm[bp].base_type = OBJ_WEAPONS; + + temp_rand = random2(240); + mitm[bp].sub_type = ((temp_rand > 209) ? WPN_DAGGER : //12.50% + (temp_rand > 179) ? WPN_CLUB : //12.50% + (temp_rand > 152) ? WPN_FLAIL : //11.25% + (temp_rand > 128) ? WPN_HAND_AXE : //10.00% + (temp_rand > 108) ? WPN_HAMMER : // 8.33% + (temp_rand > 88) ? WPN_HALBERD : // 8.33% + (temp_rand > 68) ? WPN_SHORT_SWORD : // 8.33% + (temp_rand > 48) ? WPN_MACE : // 8.33% + (temp_rand > 38) ? WPN_WHIP : // 4.17% + (temp_rand > 28) ? WPN_TRIDENT : // 4.17% + (temp_rand > 18) ? WPN_FALCHION : // 4.17% + (temp_rand > 8) ? WPN_MORNINGSTAR : // 4.17% + (temp_rand > 2) ? WPN_WAR_AXE // 2.50% + : WPN_SPIKED_FLAIL);// 1.25% + } + else + goto give_ammo; + break; + + case MONS_DEEP_ELF_FIGHTER: + case MONS_DEEP_ELF_HIGH_PRIEST: + case MONS_DEEP_ELF_KNIGHT: + case MONS_DEEP_ELF_PRIEST: + case MONS_DEEP_ELF_SOLDIER: + item_race = MAKE_ITEM_ELVEN; + mitm[bp].base_type = OBJ_WEAPONS; + + temp_rand = random2(8); + mitm[bp].sub_type = ((temp_rand > 5) ? WPN_LONG_SWORD : // 2 in 8 + (temp_rand > 3) ? WPN_SHORT_SWORD : // 2 in 8 + (temp_rand > 2) ? WPN_SCIMITAR : // 1 in 8 + (temp_rand > 1) ? WPN_MACE : // 1 in 8 + (temp_rand > 0) ? WPN_BOW // 1 in 8 + : WPN_HAND_CROSSBOW); // 1 in 8 + break; + + case MONS_DEEP_ELF_ANNIHILATOR: + case MONS_DEEP_ELF_CONJURER: + case MONS_DEEP_ELF_DEATH_MAGE: + case MONS_DEEP_ELF_DEMONOLOGIST: + case MONS_DEEP_ELF_MAGE: + case MONS_DEEP_ELF_SORCERER: + case MONS_DEEP_ELF_SUMMONER: + item_race = MAKE_ITEM_ELVEN; + mitm[bp].base_type = OBJ_WEAPONS; + + temp_rand = random2(6); + mitm[bp].sub_type = ((temp_rand > 3) ? WPN_LONG_SWORD : // 2 in 6 + (temp_rand > 2) ? WPN_SHORT_SWORD :// 1 in 6 + (temp_rand > 1) ? WPN_SABRE : // 1 in 6 + (temp_rand > 0) ? WPN_DAGGER // 1 in 6 + : WPN_WHIP); // 1 in 6 + break; + + case MONS_ORC_WARRIOR: + case MONS_ORC_HIGH_PRIEST: + case MONS_BLORK_THE_ORC: + item_race = MAKE_ITEM_ORCISH; + // deliberate fall-through {dlb} + case MONS_DANCING_WEAPON: // give_level may have been adjusted above + case MONS_FRANCES: + case MONS_FRANCIS: + case MONS_HAROLD: + case MONS_JOSEPH: + case MONS_LOUISE: + case MONS_MICHAEL: + case MONS_NAGA: + case MONS_NAGA_MAGE: + case MONS_RUPERT: + case MONS_SKELETAL_WARRIOR: + case MONS_WAYNE: + mitm[bp].base_type = OBJ_WEAPONS; + + temp_rand = random2(120); + mitm[bp].sub_type = ((temp_rand > 109) ? WPN_LONG_SWORD : // 8.33% + (temp_rand > 99) ? WPN_SHORT_SWORD : // 8.33% + (temp_rand > 89) ? WPN_SCIMITAR : // 8.33% + (temp_rand > 79) ? WPN_BATTLEAXE : // 8.33% + (temp_rand > 69) ? WPN_HAND_AXE : // 8.33% + (temp_rand > 59) ? WPN_HALBERD : // 8.33% + (temp_rand > 49) ? WPN_GLAIVE : // 8.33% + (temp_rand > 39) ? WPN_MORNINGSTAR : // 8.33% + (temp_rand > 29) ? WPN_GREAT_MACE : // 8.33% + (temp_rand > 19) ? WPN_TRIDENT : // 8.33% + (temp_rand > 10) ? WPN_WAR_AXE : // 7.50% + (temp_rand > 1) ? WPN_FLAIL : // 7.50% + (temp_rand > 0) ? WPN_BROAD_AXE // 0.83% + : WPN_SPIKED_FLAIL); // 0.83% + break; + + case MONS_ORC_WARLORD: + // being at the top has it's priviledges + if (one_chance_in(3)) + give_level = MAKE_GOOD_ITEM; + // deliberate fall-through + case MONS_ORC_KNIGHT: + item_race = MAKE_ITEM_ORCISH; + // deliberate fall-through, I guess {dlb} + case MONS_NORBERT: + case MONS_JOZEF: + case MONS_URUG: + case MONS_VAULT_GUARD: + case MONS_VAMPIRE_KNIGHT: + mitm[bp].base_type = OBJ_WEAPONS; + + temp_rand = random2(24); + mitm[bp].sub_type = ((temp_rand > 19) ? WPN_GREAT_SWORD :// 16.67% + (temp_rand > 15) ? WPN_LONG_SWORD : // 16.67% + (temp_rand > 11) ? WPN_BATTLEAXE : // 16.67% + (temp_rand > 7) ? WPN_WAR_AXE : // 16.67% + (temp_rand > 5) ? WPN_GREAT_MACE : // 8.33% + (temp_rand > 3) ? WPN_GREAT_FLAIL :// 8.33% + (temp_rand > 1) ? WPN_GLAIVE : // 8.33% + (temp_rand > 0) ? WPN_BROAD_AXE // 4.17% + : WPN_HALBERD); // 4.17% + + if (one_chance_in(4)) + mitm[bp].plus += 1 + random2(3); + break; + + case MONS_CYCLOPS: + case MONS_STONE_GIANT: + item_race = MAKE_ITEM_NO_RACE; + mitm[bp].base_type = OBJ_MISSILES; + mitm[bp].sub_type = MI_LARGE_ROCK; + break; + + case MONS_TWO_HEADED_OGRE: + case MONS_ETTIN: + item_race = MAKE_ITEM_NO_RACE; + hand_used = 0; + + if (menv[mid].inv[MSLOT_WEAPON] != NON_ITEM) + hand_used = 1; + + mitm[bp].base_type = OBJ_WEAPONS; + mitm[bp].sub_type = (one_chance_in(3) ? WPN_GIANT_SPIKED_CLUB + : WPN_GIANT_CLUB); + + if (one_chance_in(10) || menv[mid].type == MONS_ETTIN) + { + mitm[bp].sub_type = ((one_chance_in(10)) ? WPN_GREAT_FLAIL + : WPN_GREAT_MACE); + } + break; + + case MONS_REAPER: + give_level = MAKE_GOOD_ITEM; + // intentional fall-through... + + case MONS_SIGMUND: + item_race = MAKE_ITEM_NO_RACE; + mitm[bp].base_type = OBJ_WEAPONS; + mitm[bp].sub_type = WPN_SCYTHE; + break; + + case MONS_BALRUG: + item_race = MAKE_ITEM_NO_RACE; + mitm[bp].base_type = OBJ_WEAPONS; + mitm[bp].sub_type = WPN_DEMON_WHIP; + break; + + case MONS_RED_DEVIL: + if (!one_chance_in(3)) + { + item_race = MAKE_ITEM_NO_RACE; + mitm[bp].base_type = OBJ_WEAPONS; + mitm[bp].sub_type = (one_chance_in(3) ? WPN_DEMON_TRIDENT + : WPN_TRIDENT); + } + break; + + case MONS_OGRE: + case MONS_HILL_GIANT: + case MONS_EROLCHA: + item_race = MAKE_ITEM_NO_RACE; + mitm[bp].base_type = OBJ_WEAPONS; + + mitm[bp].sub_type = (one_chance_in(3) ? WPN_GIANT_SPIKED_CLUB + : WPN_GIANT_CLUB); + + if (one_chance_in(10)) + { + mitm[bp].sub_type = (one_chance_in(10) ? WPN_GREAT_FLAIL + : WPN_GREAT_MACE); + } + break; + + case MONS_CENTAUR: + case MONS_CENTAUR_WARRIOR: + item_race = MAKE_ITEM_NO_RACE; + mitm[bp].base_type = OBJ_WEAPONS; + mitm[bp].sub_type = WPN_BOW; + break; + + case MONS_YAKTAUR: + case MONS_YAKTAUR_CAPTAIN: + item_race = MAKE_ITEM_NO_RACE; + mitm[bp].base_type = OBJ_WEAPONS; + mitm[bp].sub_type = WPN_CROSSBOW; + break; + + case MONS_EFREET: + case MONS_ERICA: + force_item = 1; + item_race = MAKE_ITEM_NO_RACE; + mitm[bp].base_type = OBJ_WEAPONS; + mitm[bp].sub_type = WPN_SCIMITAR; + mitm[bp].plus = random2(5); + mitm[bp].plus2 = random2(5); + mitm[bp].colour = RED; // forced by force_item above {dlb} + set_item_ego_type( mitm[bp], OBJ_WEAPONS, SPWPN_FLAMING ); + break; + + case MONS_ANGEL: + force_item = 1; + mitm[bp].base_type = OBJ_WEAPONS; + mitm[bp].colour = WHITE; // forced by force_item above {dlb} + + set_equip_desc( mitm[bp], ISFLAG_GLOWING ); + if (one_chance_in(3)) + { + mitm[bp].sub_type = (one_chance_in(3) ? WPN_GREAT_MACE : WPN_MACE); + set_item_ego_type( mitm[bp], OBJ_WEAPONS, SPWPN_HOLY_WRATH ); + } + else + { + mitm[bp].sub_type = WPN_LONG_SWORD; + } + + mitm[bp].plus = 1 + random2(3); + mitm[bp].plus2 = 1 + random2(3); + break; + + case MONS_DAEVA: + force_item = 1; + mitm[bp].base_type = OBJ_WEAPONS; + mitm[bp].colour = WHITE; // forced by force_item above {dlb} + + mitm[bp].sub_type = (one_chance_in(4) ? WPN_GREAT_SWORD + : WPN_LONG_SWORD); + + set_equip_desc( mitm[bp], ISFLAG_GLOWING ); + set_item_ego_type( mitm[bp], OBJ_WEAPONS, SPWPN_HOLY_WRATH ); + mitm[bp].plus = 1 + random2(3); + mitm[bp].plus2 = 1 + random2(3); + break; + + case MONS_HELL_KNIGHT: + case MONS_MAUD: + case MONS_ADOLF: + case MONS_MARGERY: + force_item = 1; + mitm[bp].base_type = OBJ_WEAPONS; + mitm[bp].sub_type = WPN_LONG_SWORD + random2(3); + + if (one_chance_in(7)) + mitm[bp].sub_type = WPN_HALBERD; + if (one_chance_in(7)) + mitm[bp].sub_type = WPN_GLAIVE; + if (one_chance_in(7)) + mitm[bp].sub_type = WPN_GREAT_MACE; + if (one_chance_in(7)) + mitm[bp].sub_type = WPN_BATTLEAXE; + if (one_chance_in(7)) + mitm[bp].sub_type = WPN_WAR_AXE; + if (one_chance_in(7)) + mitm[bp].sub_type = WPN_BROAD_AXE; + if (one_chance_in(7)) + mitm[bp].sub_type = WPN_DEMON_TRIDENT; + if (one_chance_in(7)) + mitm[bp].sub_type = WPN_DEMON_BLADE; + if (one_chance_in(7)) + mitm[bp].sub_type = WPN_DEMON_WHIP; + + temp_rand = random2(3); + set_equip_desc( mitm[bp], (temp_rand == 1) ? ISFLAG_GLOWING : + (temp_rand == 2) ? ISFLAG_RUNED + : ISFLAG_NO_DESC ); + + if (one_chance_in(3)) + set_item_ego_type( mitm[bp], OBJ_WEAPONS, SPWPN_FLAMING ); + else if (one_chance_in(3)) + { + temp_rand = random2(5); + + set_item_ego_type( mitm[bp], OBJ_WEAPONS, + ((temp_rand == 0) ? SPWPN_DRAINING : + (temp_rand == 1) ? SPWPN_VORPAL : + (temp_rand == 2) ? SPWPN_PAIN : + (temp_rand == 3) ? SPWPN_DISTORTION + : SPWPN_SPEED) ); + } + + mitm[bp].plus += random2(6); + mitm[bp].plus2 += random2(6); + + mitm[bp].colour = RED; // forced by force_item above {dlb} + + if (one_chance_in(3)) + mitm[bp].colour = DARKGREY; + if (one_chance_in(5)) + mitm[bp].colour = CYAN; + break; + + case MONS_FIRE_GIANT: + force_item = 1; + mitm[bp].base_type = OBJ_WEAPONS; + mitm[bp].sub_type = WPN_GREAT_SWORD; + mitm[bp].plus = 0; + mitm[bp].plus2 = 0; + set_item_ego_type( mitm[bp], OBJ_WEAPONS, SPWPN_FLAMING ); + + mitm[bp].colour = RED; // forced by force_item above {dlb} + if (one_chance_in(3)) + mitm[bp].colour = DARKGREY; + if (one_chance_in(5)) + mitm[bp].colour = CYAN; + break; + + case MONS_FROST_GIANT: + force_item = 1; + mitm[bp].base_type = OBJ_WEAPONS; + mitm[bp].sub_type = WPN_BATTLEAXE; + mitm[bp].plus = 0; + mitm[bp].plus2 = 0; + set_item_ego_type( mitm[bp], OBJ_WEAPONS, SPWPN_FREEZING ); + + // forced by force_item above {dlb} + mitm[bp].colour = (one_chance_in(3) ? WHITE : CYAN); + break; + + case MONS_KOBOLD_DEMONOLOGIST: + case MONS_ORC_WIZARD: + case MONS_ORC_SORCERER: + item_race = MAKE_ITEM_ORCISH; + // deliberate fall-through, I guess {dlb} + case MONS_NECROMANCER: + case MONS_WIZARD: + case MONS_PSYCHE: + case MONS_DONALD: + case MONS_JOSEPHINE: + case MONS_AGNES: + mitm[bp].base_type = OBJ_WEAPONS; + mitm[bp].sub_type = WPN_DAGGER; + break; + + case MONS_CEREBOV: + force_item = 1; + make_item_fixed_artefact( mitm[bp], false, SPWPN_SWORD_OF_CEREBOV ); + break; + + case MONS_DISPATER: + force_item = 1; + make_item_fixed_artefact( mitm[bp], false, SPWPN_STAFF_OF_DISPATER ); + break; + + case MONS_ASMODEUS: + force_item = 1; + make_item_fixed_artefact( mitm[bp], false, SPWPN_SCEPTRE_OF_ASMODEUS ); + break; + + case MONS_GERYON: + //mv: probably should be moved out of this switch, + //but it's not worth of it, unless we have more + //monsters with misc. items + mitm[bp].base_type = OBJ_MISCELLANY; + mitm[bp].sub_type = MISC_HORN_OF_GERYON; + break; + + case MONS_SALAMANDER: //mv: new 8 Aug 2001 + //Yes, they've got really nice items, but + //it's almost impossible to get them + force_item = 1; + item_race = MAKE_ITEM_NO_RACE; + mitm[bp].base_type = OBJ_WEAPONS; + temp_rand = random2(6); + + mitm[bp].sub_type = ((temp_rand == 5) ? WPN_GREAT_SWORD : + (temp_rand == 4) ? WPN_TRIDENT : + (temp_rand == 3) ? WPN_SPEAR : + (temp_rand == 2) ? WPN_GLAIVE : + (temp_rand == 1) ? WPN_BOW + : WPN_HALBERD); + + if (mitm[bp].sub_type == WPN_BOW) + set_item_ego_type( mitm[bp], OBJ_WEAPONS, SPWPN_FLAME ); + else + set_item_ego_type( mitm[bp], OBJ_WEAPONS, SPWPN_FLAMING ); + + mitm[bp].plus = random2(5); + mitm[bp].plus2 = random2(5); + mitm[bp].colour = RED; // forced by force_item above {dlb} + break; + } // end "switch(menv[mid].type)" + + // only happens if something in above switch doesn't set it {dlb} + if (mitm[bp].base_type == 101) + { + mitm[bp].base_type = OBJ_UNASSIGNED; + goto give_ammo; + } + + mitm[bp].x = 0; + mitm[bp].y = 0; + mitm[bp].link = NON_ITEM; + + if (force_item) + mitm[bp].quantity = iquan; + else if (mons_is_unique( menv[mid].type )) + { + if (random2(100) <= 9 + menv[mid].hit_dice) + give_level = MAKE_GOOD_ITEM; + else + give_level = level_number + 5; + } + + xitc = mitm[bp].base_type; + xitt = mitm[bp].sub_type; + + // Note this mess, all the work above doesn't mean much unless + // force_item is set... otherwise we're just going to take the + // base and subtypes and create a new item. -- bwr + thing_created = ((force_item) ? bp : items( 0, xitc, xitt, true, + give_level, item_race) ); + + if (thing_created == NON_ITEM) + return; + + mitm[thing_created].x = 0; + mitm[thing_created].y = 0; + mitm[thing_created].link = NON_ITEM; + unset_ident_flags( mitm[thing_created], ISFLAG_IDENT_MASK ); + + //mv: now every item gets in appropriate slot + //no more miscellany in potion slot etc. (19 May 2001) + // hand_used = 0 unless Ettin's 2nd hand etc. + if ( mitm[thing_created].base_type == OBJ_WEAPONS ) + menv[mid].inv[hand_used] = thing_created; + else if ( mitm[thing_created].base_type == OBJ_MISSILES ) + menv[mid].inv[MSLOT_MISSILE] = thing_created; + else if ( mitm[thing_created].base_type == OBJ_SCROLLS ) + menv[mid].inv[MSLOT_SCROLL] = thing_created; + else if ( mitm[thing_created].base_type == OBJ_GOLD ) + menv[mid].inv[MSLOT_GOLD] = thing_created; + else if ( mitm[thing_created].base_type == OBJ_POTIONS ) + menv[mid].inv[MSLOT_POTION] = thing_created; + else if ( mitm[thing_created].base_type == OBJ_MISCELLANY ) + menv[mid].inv[MSLOT_MISCELLANY] = thing_created; + + + if (get_weapon_brand( mitm[thing_created] ) == SPWPN_PROTECTION ) + menv[mid].armour_class += 5; + + if (!force_item || mitm[thing_created].colour == BLACK) + item_colour( mitm[thing_created] ); + + give_ammo: + // mv: gives ammunition + // note that item_race is not reset for this section + if (menv[mid].inv[MSLOT_WEAPON] != NON_ITEM + && launches_things( mitm[menv[mid].inv[MSLOT_WEAPON]].sub_type )) + { + xitc = OBJ_MISSILES; + xitt = launched_by(mitm[menv[mid].inv[MSLOT_WEAPON]].sub_type); + + thing_created = items( 0, xitc, xitt, true, give_level, item_race ); + if (thing_created == NON_ITEM) + return; + + // monsters will always have poisoned needles -- otherwise + // they are just going to behave badly --GDL + if (xitt == MI_NEEDLE) + set_item_ego_type(mitm[thing_created], OBJ_MISSILES, SPMSL_POISONED); + + mitm[thing_created].x = 0; + mitm[thing_created].y = 0; + mitm[thing_created].flags = 0; + menv[mid].inv[MSLOT_MISSILE] = thing_created; + + item_colour( mitm[thing_created] ); + } // end if needs ammo + + bp = get_item_slot(); + if (bp == NON_ITEM) + return; + + mitm[bp].x = 0; + mitm[bp].y = 0; + mitm[bp].link = NON_ITEM; + + item_race = MAKE_ITEM_RANDOM_RACE; + give_level = 1 + (level_number / 2); + + int force_colour = 0; //mv: important !!! Items with force_colour = 0 + //are colored defaultly after following + //switch. Others will get force_colour. + + switch (menv[mid].type) + { + case MONS_DEEP_ELF_ANNIHILATOR: + case MONS_DEEP_ELF_CONJURER: + case MONS_DEEP_ELF_DEATH_MAGE: + case MONS_DEEP_ELF_DEMONOLOGIST: + case MONS_DEEP_ELF_FIGHTER: + case MONS_DEEP_ELF_HIGH_PRIEST: + case MONS_DEEP_ELF_KNIGHT: + case MONS_DEEP_ELF_MAGE: + case MONS_DEEP_ELF_PRIEST: + case MONS_DEEP_ELF_SOLDIER: + case MONS_DEEP_ELF_SORCERER: + case MONS_DEEP_ELF_SUMMONER: + if (item_race == MAKE_ITEM_RANDOM_RACE) + item_race = MAKE_ITEM_ELVEN; + // deliberate fall through {dlb} + case MONS_IJYB: + case MONS_ORC: + case MONS_ORC_HIGH_PRIEST: + case MONS_ORC_PRIEST: + case MONS_ORC_SORCERER: + if (item_race == MAKE_ITEM_RANDOM_RACE) + item_race = MAKE_ITEM_ORCISH; + // deliberate fall through {dlb} + case MONS_ERICA: + case MONS_HAROLD: + case MONS_JOSEPH: + case MONS_JOSEPHINE: + case MONS_JOZEF: + case MONS_NORBERT: + case MONS_PSYCHE: + case MONS_TERENCE: + if (random2(5) < 2) + { + mitm[bp].base_type = OBJ_ARMOUR; + + switch (random2(8)) + { + case 0: + case 1: + case 2: + case 3: + mitm[bp].sub_type = ARM_LEATHER_ARMOUR; + break; + case 4: + case 5: + mitm[bp].sub_type = ARM_RING_MAIL; + break; + case 6: + mitm[bp].sub_type = ARM_SCALE_MAIL; + break; + case 7: + mitm[bp].sub_type = ARM_CHAIN_MAIL; + break; + } + } + else + return; + break; + + case MONS_DUANE: + case MONS_EDMUND: + case MONS_RUPERT: + case MONS_URUG: + case MONS_WAYNE: + mitm[bp].base_type = OBJ_ARMOUR; + mitm[bp].sub_type = ARM_LEATHER_ARMOUR + random2(4); + break; + + case MONS_ORC_WARLORD: + // being at the top has it's priviledges + if (one_chance_in(3)) + give_level = MAKE_GOOD_ITEM; + // deliberate fall through + case MONS_ORC_KNIGHT: + case MONS_ORC_WARRIOR: + if (item_race == MAKE_ITEM_RANDOM_RACE) + item_race = MAKE_ITEM_ORCISH; + // deliberate fall through {dlb} + case MONS_ADOLF: + case MONS_HELL_KNIGHT: + case MONS_LOUISE: + case MONS_MARGERY: + case MONS_MAUD: + case MONS_VAMPIRE_KNIGHT: + case MONS_VAULT_GUARD: + mitm[bp].base_type = OBJ_ARMOUR; + mitm[bp].sub_type = ARM_CHAIN_MAIL + random2(4); + break; + + case MONS_ANGEL: + case MONS_SIGMUND: + case MONS_WIGHT: + item_race = MAKE_ITEM_NO_RACE; + mitm[bp].base_type = OBJ_ARMOUR; + mitm[bp].sub_type = ARM_ROBE; + force_colour = WHITE; //mv: always white + break; + + case MONS_NAGA: + case MONS_NAGA_MAGE: + case MONS_NAGA_WARRIOR: + if (!one_chance_in(3)) + return; + // deliberate fall through {dlb} + case MONS_DONALD: + case MONS_GREATER_NAGA: + case MONS_JESSICA: + case MONS_KOBOLD_DEMONOLOGIST: + case MONS_OGRE_MAGE: + case MONS_ORC_WIZARD: + case MONS_WIZARD: + item_race = MAKE_ITEM_NO_RACE; + mitm[bp].base_type = OBJ_ARMOUR; + mitm[bp].sub_type = ARM_ROBE; + break; + + case MONS_BORIS: + give_level = MAKE_GOOD_ITEM; + // fall-through + case MONS_AGNES: + case MONS_BLORK_THE_ORC: + case MONS_FRANCES: + case MONS_FRANCIS: + case MONS_NECROMANCER: + case MONS_VAMPIRE_MAGE: + mitm[bp].base_type = OBJ_ARMOUR; + mitm[bp].sub_type = ARM_ROBE; + force_colour = DARKGREY; //mv: always darkgrey + break; + + default: + return; + } // end of switch(menv [mid].type) + + iquan = 1; //because it may have been set earlier + //by giving ammo or weapons {dlb} + + xitc = mitm[bp].base_type; + xitt = mitm[bp].sub_type; + + if (mons_is_unique( menv[mid].type ) && give_level != MAKE_GOOD_ITEM) + { + if (random2(100) < 9 + menv[mid].hit_dice) + give_level = MAKE_GOOD_ITEM; + else + give_level = level_number + 5; + } + + thing_created = items( 0, xitc, xitt, true, give_level, item_race ); + + if (thing_created == NON_ITEM) + return; + + mitm[thing_created].x = 0; + mitm[thing_created].y = 0; + mitm[thing_created].link = NON_ITEM; + menv[mid].inv[MSLOT_ARMOUR] = thing_created; + + //mv: all items with force_colour = 0 are colored via items(). + if (force_colour) + mitm[thing_created].colour = force_colour; + + menv[mid].armour_class += property( mitm[thing_created], PARM_AC ); + + const int armour_plus = mitm[thing_created].plus; + + ASSERT(abs(armour_plus) < 20); + + if (abs(armour_plus) < 20) + menv[mid].armour_class += armour_plus; + + menv[mid].evasion += property( mitm[thing_created], PARM_EVASION ) / 2; + + if (menv[mid].evasion < 1) + menv[mid].evasion = 1; // This *shouldn't* happen. +} // end give_item() + +//--------------------------------------------------------------------------- +// PRIVATE HELPER FUNCTIONS +//--------------------------------------------------------------------------- + +static bool is_weapon_special(int the_weapon) +{ + return (mitm[the_weapon].special != SPWPN_NORMAL); +} // end is_weapon_special() + +static void set_weapon_special(int the_weapon, int spwpn) +{ + set_item_ego_type( mitm[the_weapon], OBJ_WEAPONS, spwpn ); +} // end set_weapon_special() + +static void check_doors(void) +{ + unsigned char ig; + unsigned char solid_count = 0; // clarifies innermost loop {dlb} + int x,y; + + for (x = 1; x < GXM-1; x++) + { + for (y = 1; y < GYM-1; y++) + { + ig = grd[x][y]; + + if (ig != DNGN_CLOSED_DOOR) + continue; + + solid_count = 0; + + // first half of each conditional represents bounds checking {dlb}: + if (grd[x - 1][y] < DNGN_LAST_SOLID_TILE) + solid_count++; + + if (grd[x + 1][y] < DNGN_LAST_SOLID_TILE) + solid_count++; + + if (grd[x][y - 1] < DNGN_LAST_SOLID_TILE) + solid_count++; + + if (grd[x][y + 1] < DNGN_LAST_SOLID_TILE) + solid_count++; + + grd[x][y] = ((solid_count < 2) ? DNGN_FLOOR : DNGN_CLOSED_DOOR); + } + } +} // end check_doors() + +static void hide_doors(void) +{ + unsigned char dx = 0, dy = 0; // loop variables + unsigned char wall_count = 0; // clarifies inner loop {dlb} + + for (dx = 1; dx < GXM-1; dx++) + { + for (dy = 1; dy < GYM-1; dy++) + { + // only one out of four doors are candidates for hiding {gdl}: + if (grd[dx][dy] == DNGN_CLOSED_DOOR && one_chance_in(4)) + { + wall_count = 0; + + if (grd[dx - 1][dy] == DNGN_ROCK_WALL) + wall_count++; + + if (grd[dx + 1][dy] == DNGN_ROCK_WALL) + wall_count++; + + if (grd[dx][dy - 1] == DNGN_ROCK_WALL) + wall_count++; + + if (grd[dx][dy + 1] == DNGN_ROCK_WALL) + wall_count++; + + // if door is attached to more than one wall, hide it {dlb}: + if (wall_count > 1) + grd[dx][dy] = DNGN_SECRET_DOOR; + } + } + } +} // end hide_doors() + +static void prepare_swamp(void) +{ + int i, j; // loop variables + int temp_rand; // probability determination {dlb} + + for (i = 10; i < (GXM - 10); i++) + { + for (j = 10; j < (GYM - 10); j++) + { + // doors -> floors {dlb} + if (grd[i][j] == DNGN_CLOSED_DOOR || grd[i][j] == DNGN_SECRET_DOOR) + grd[i][j] = DNGN_FLOOR; + + // floors -> shallow water 1 in 3 times {dlb} + if (grd[i][j] == DNGN_FLOOR && one_chance_in(3)) + grd[i][j] = DNGN_SHALLOW_WATER; + + // walls -> deep/shallow water or remain unchanged {dlb} + if (grd[i][j] == DNGN_ROCK_WALL) + { + temp_rand = random2(6); + + if (temp_rand > 0) // 17% chance unchanged {dlb} + { + grd[i][j] = ((temp_rand > 2) ? DNGN_SHALLOW_WATER // 50% + : DNGN_DEEP_WATER); // 33% + } + } + } + } +} // end prepare_swamp() + +// Gives water which is next to ground/shallow water a chance of being +// shallow. Checks each water space. +static void prepare_water( int level_number ) +{ + int i, j, k, l; // loop variables {dlb} + unsigned char which_grid; // code compaction {dlb} + + for (i = 10; i < (GXM - 10); i++) + { + for (j = 10; j < (GYM - 10); j++) + { + if (grd[i][j] == DNGN_DEEP_WATER) + { + for (k = -1; k < 2; k++) + { + for (l = -1; l < 2; l++) + { + if (k != 0 || l != 0) + { + which_grid = grd[i + k][j + l]; + + // must come first {dlb} + if (which_grid == DNGN_SHALLOW_WATER + && one_chance_in( 8 + level_number )) + { + grd[i][j] = DNGN_SHALLOW_WATER; + } + else if (which_grid >= DNGN_FLOOR + && random2(100) < 80 - level_number * 4) + { + grd[i][j] = DNGN_SHALLOW_WATER; + } + } + } + } + } + } + } +} // end prepare_water() + +static bool find_in_area(int sx, int sy, int ex, int ey, unsigned char feature) +{ + int x,y; + + if (feature != 0) + { + for(x = sx; x <= ex; x++) + { + for(y = sy; y <= ey; y++) + { + if (grd[x][y] == feature) + return (true); + } + } + } + + return (false); +} + +// stamp a box. can avoid a possible type, and walls and floors can +// be different (or not stamped at all) +// Note that the box boundaries are INclusive. +static bool make_box(int room_x1, int room_y1, int room_x2, int room_y2, + unsigned char floor, unsigned char wall, unsigned char avoid) +{ + int bx,by; + + // check for avoidance + if (find_in_area(room_x1, room_y1, room_x2, room_y2, avoid)) + return false; + + // draw walls + if (wall != 0) + { + for(bx=room_x1; bx<=room_x2; bx++) + { + grd[bx][room_y1] = wall; + grd[bx][room_y2] = wall; + } + for(by=room_y1+1; by= 0) + { + you.unique_creatures[40 + which_demon] = 1; + build_vaults(level_number, which_demon + 60); + } + else + { + plan_main(level_number, 0); + build_minivaults(level_number, 300 + random2(9)); + } + + return 1; + } + + // must be normal dungeon + return 0; +} + +// returns 1 if we should skip further generation, +// -1 if we should immediately quit, and 0 otherwise. +static int builder_by_branch(int level_number) +{ + switch (you.where_are_you) + { + case BRANCH_HIVE: + if (level_number == you.branch_stairs[STAIRS_HIVE] + + branch_depth(STAIRS_HIVE)) + build_vaults(level_number, 80); + else + spotty_level(false, 100 + random2(500), false); + return 1; + + case BRANCH_SLIME_PITS: + if (level_number == you.branch_stairs[STAIRS_SLIME_PITS] + + branch_depth(STAIRS_SLIME_PITS)) + { + build_vaults(level_number, 81); + } + else + spotty_level(false, 100 + random2(500), false); + return 1; + + case BRANCH_VAULTS: + if (level_number == you.branch_stairs[STAIRS_VAULTS] + + branch_depth(STAIRS_VAULTS)) + { + build_vaults(level_number, 82); + return 1; + } + break; + + case BRANCH_HALL_OF_BLADES: + if (level_number == you.branch_stairs[STAIRS_HALL_OF_BLADES] + + branch_depth(STAIRS_HALL_OF_BLADES)) + { + build_vaults(level_number, 83); + return 1; + } + break; + + case BRANCH_HALL_OF_ZOT: + if (level_number == you.branch_stairs[STAIRS_HALL_OF_ZOT] + + branch_depth(STAIRS_HALL_OF_ZOT)) + { + build_vaults(level_number, 84); + return 1; + } + break; + + case BRANCH_ECUMENICAL_TEMPLE: + if (level_number == you.branch_stairs[STAIRS_ECUMENICAL_TEMPLE] + + branch_depth(STAIRS_ECUMENICAL_TEMPLE)) + { + build_vaults(level_number, 85); + return 1; + } + break; + + case BRANCH_SNAKE_PIT: + if (level_number == you.branch_stairs[STAIRS_SNAKE_PIT] + + branch_depth(STAIRS_SNAKE_PIT)) + { + build_vaults(level_number, 86); + return 1; + } + break; + + case BRANCH_ELVEN_HALLS: + if (level_number == you.branch_stairs[STAIRS_ELVEN_HALLS] + + branch_depth(STAIRS_ELVEN_HALLS)) + { + build_vaults(level_number, 87); + return 1; + } + break; + + case BRANCH_TOMB: + if (level_number == you.branch_stairs[STAIRS_TOMB] + 1) + { + build_vaults(level_number, 88); + return 1; + } + else if (level_number == you.branch_stairs[STAIRS_TOMB] + 2) + { + build_vaults(level_number, 89); + return 1; + } + else if (level_number == you.branch_stairs[STAIRS_TOMB] + 3) + { + build_vaults(level_number, 90); + return 1; + } + break; + + case BRANCH_SWAMP: + if (level_number == you.branch_stairs[STAIRS_SWAMP] + + branch_depth(STAIRS_SWAMP)) + { + build_vaults(level_number, 91); + return 1; + } + break; + + case BRANCH_ORCISH_MINES: + spotty_level(false, 100 + random2(500), false); + return 1; + + case BRANCH_LAIR: + if (!one_chance_in(3)) + { + spotty_level(false, 100 + random2(500), false); + return 1; + } + break; + + case BRANCH_VESTIBULE_OF_HELL: + build_vaults( level_number, 50 ); + link_items(); + return -1; + + case BRANCH_DIS: + if (level_number == 33) + { + build_vaults(level_number, 51); + return 1; + } + break; + + case BRANCH_GEHENNA: + if (level_number == 33) + { + build_vaults(level_number, 52); + return 1; + } + break; + + case BRANCH_COCYTUS: + if (level_number == 33) + { + build_vaults(level_number, 53); + return 1; + } + break; + + case BRANCH_TARTARUS: + if (level_number == 33) + { + build_vaults(level_number, 54); + return 1; + } + break; + + default: + break; + } + return 0; +} + +// returns 1 if we should dispense with city building, +// 0 otherwise. Also sets special_room if one is generated +// so that we can link it up later. + +static int builder_normal(int level_number, char level_type, spec_room &sr) +{ + UNUSED( level_type ); + + bool skipped = false; + bool done_city = false; + + if (player_in_branch( BRANCH_DIS )) + { + city_level(level_number); + return 1; + } + + if (player_in_branch( BRANCH_MAIN_DUNGEON ) + && level_number > 10 && level_number < 23 && one_chance_in(9)) + { + // Can't have vaults on you.where_are_you != BRANCH_MAIN_DUNGEON levels + build_vaults(level_number, 100); + return 1; + } + + if (player_in_branch( BRANCH_VAULTS )) + { + if (one_chance_in(3)) + city_level(level_number); + else + plan_main(level_number, 4); + return 1; + } + + if (level_number > 7 && level_number < 23) + { + if (one_chance_in(16)) + { + spotty_level(false, 0, coinflip()); + return 1; + } + + if (one_chance_in(16)) + { + bigger_room(); + return 1; + } + } + + if (level_number > 2 && level_number < 23 && one_chance_in(3)) + { + plan_main(level_number, 0); + + if (one_chance_in(3) && level_number > 6) + build_minivaults(level_number, 200); + + return 1; + } + + if (one_chance_in(3)) + skipped = true; + + //V was 3 + if (!skipped && one_chance_in(7)) + { + // sometimes roguey_levels generate a special room + roguey_level(level_number, sr); + + if (level_number > 6 + && player_in_branch( BRANCH_MAIN_DUNGEON ) + && one_chance_in(4)) + { + build_minivaults(level_number, 200); + return 1; + } + } + else + { + if (!skipped && level_number > 13 && one_chance_in(8)) + { + if (one_chance_in(3)) + city_level(level_number); + else + plan_main(level_number, 4); + done_city = true; + } + } + + // maybe create a special room, if roguey_level hasn't done it + // already. + if (!sr.created && level_number > 5 && !done_city && one_chance_in(5)) + special_room(level_number, sr); + + return 0; +} + +// returns 1 if we should skip extras(), otherwise 0 +static int builder_basic(int level_number) +{ + int temp_rand; + int doorlevel = random2(11); + int corrlength = 2 + random2(14); + int roomsize = 4 + random2(5) + random2(6); + int no_corr = (one_chance_in(100) ? 500 + random2(500) : 30 + random2(200)); + int intersect_chance = (one_chance_in(20) ? 400 : random2(20)); + + make_trail( 35, 30, 35, 20, corrlength, intersect_chance, no_corr, + DNGN_STONE_STAIRS_DOWN_I, DNGN_STONE_STAIRS_UP_I ); + + make_trail( 10, 15, 10, 15, corrlength, intersect_chance, no_corr, + DNGN_STONE_STAIRS_DOWN_II, DNGN_STONE_STAIRS_UP_II ); + + make_trail(50,20,10,15,corrlength,intersect_chance,no_corr, + DNGN_STONE_STAIRS_DOWN_III, DNGN_STONE_STAIRS_UP_III); + + if (one_chance_in(4)) + { + make_trail( 10, 20, 40, 20, corrlength, intersect_chance, no_corr, + DNGN_ROCK_STAIRS_DOWN ); + } + + if (one_chance_in(4)) + { + make_trail( 50, 20, 40, 20, corrlength, intersect_chance, no_corr, + DNGN_ROCK_STAIRS_UP ); + } + + + if (level_number > 1 && one_chance_in(16)) + big_room(level_number); + + if (random2(level_number) > 6 && one_chance_in(3)) + diamond_rooms(level_number); + + // make some rooms: + int i, no_rooms, max_doors; + int sx,sy,ex,ey, time_run; + + temp_rand = random2(750); + time_run = 0; + + no_rooms = ((temp_rand > 63) ? (5 + random2avg(29, 2)) : // 91.47% {dlb} + (temp_rand > 14) ? 100 // 6.53% {dlb} + : 1); // 2.00% {dlb} + + max_doors = 2 + random2(8); + + for (i = 0; i < no_rooms; i++) + { + sx = 8 + random2(50); + sy = 8 + random2(40); + ex = sx + 2 + random2(roomsize); + ey = sy + 2 + random2(roomsize); + + if (!make_room(sx,sy,ex,ey,max_doors, doorlevel)) + { + time_run++; + i--; + } + + if (time_run > 30) + { + time_run = 0; + i++; + } + } + + // make some more rooms: + no_rooms = 1 + random2(3); + max_doors = 1; + + for (i = 0; i < no_rooms; i++) + { + sx = 8 + random2(55); + sy = 8 + random2(45); + ex = sx + 5 + random2(6); + ey = sy + 5 + random2(6); + + if (!make_room(sx,sy,ex,ey,max_doors, doorlevel)) + { + time_run++; + i--; + } + + if (time_run > 30) + { + time_run = 0; + i++; + } + } + + return 0; +} + +static void builder_extras( int level_number, int level_type ) +{ + UNUSED( level_type ); + + if (level_number >= 11 && level_number <= 23 && one_chance_in(15)) + place_specific_stair(DNGN_ENTER_LABYRINTH); + + if (level_number > 6 + && player_in_branch( BRANCH_MAIN_DUNGEON ) + && one_chance_in(3)) + { + build_minivaults(level_number, 200); + return; + } + + if (level_number > 5 && one_chance_in(10)) + { + many_pools( (coinflip() ? DNGN_DEEP_WATER : DNGN_LAVA) ); + return; + } + +#ifdef USE_RIVERS + //mv: it's better to be here so other dungeon features + // are not overriden by water + int river_type = one_chance_in( 5 + level_number ) ? DNGN_SHALLOW_WATER + : DNGN_DEEP_WATER; + + if (level_number > 11 + && (one_chance_in(5) || (level_number > 15 && !one_chance_in(5)))) + { + river_type = DNGN_LAVA; + } + + if (player_in_branch( BRANCH_GEHENNA )) + { + river_type = DNGN_LAVA; + + if (coinflip()) + build_river( river_type ); + else + build_lake( river_type ); + } + else if (player_in_branch( BRANCH_COCYTUS )) + { + river_type = DNGN_DEEP_WATER; + + if (coinflip()) + build_river( river_type ); + else + build_lake( river_type ); + } + + + if (level_number > 8 && one_chance_in(16)) + build_river( river_type ); + else if (level_number > 8 && one_chance_in(12)) + { + build_lake( (river_type != DNGN_SHALLOW_WATER) ? river_type + : DNGN_DEEP_WATER ); + } +#endif // USE_RIVERS +} + +static void place_traps(int level_number) +{ + int i; + int num_traps = random2avg(9, 2); + + for (i = 0; i < num_traps; i++) + { + // traps can be placed in vaults + if (env.trap[i].type != TRAP_UNASSIGNED) + continue; + + do + { + env.trap[i].x = 10 + random2(GXM - 20); + env.trap[i].y = 10 + random2(GYM - 20); + } + while (grd[env.trap[i].x][env.trap[i].y] != DNGN_FLOOR); + + env.trap[i].type = TRAP_DART; + + if ((random2(1 + level_number) > 1) && one_chance_in(4)) + env.trap[i].type = TRAP_NEEDLE; + if (random2(1 + level_number) > 2) + env.trap[i].type = TRAP_ARROW; + if (random2(1 + level_number) > 3) + env.trap[i].type = TRAP_SPEAR; + if (random2(1 + level_number) > 5) + env.trap[i].type = TRAP_AXE; + if (random2(1 + level_number) > 7) + env.trap[i].type = TRAP_BOLT; + if (random2(1 + level_number) > 11) + env.trap[i].type = TRAP_BLADE; + + if ((random2(1 + level_number) > 14 && one_chance_in(3)) + || (player_in_branch( BRANCH_HALL_OF_ZOT ) && coinflip())) + { + env.trap[i].type = TRAP_ZOT; + } + + if (one_chance_in(20)) + env.trap[i].type = TRAP_TELEPORT; + if (one_chance_in(40)) + env.trap[i].type = TRAP_AMNESIA; + + grd[env.trap[i].x][env.trap[i].y] = DNGN_UNDISCOVERED_TRAP; + } // end "for i" +} // end place_traps() + +static void place_specific_stair(unsigned char stair) +{ + int sx, sy; + + do + { + sx = random2(GXM-10); + sy = random2(GYM-10); + } + while(grd[sx][sy] != DNGN_FLOOR || mgrd[sx][sy] != NON_MONSTER); + + grd[sx][sy] = stair; +} + + +static void place_branch_entrances(int dlevel, char level_type) +{ + unsigned char stair; + unsigned char entrance; + int sx, sy; + + if (!level_type == LEVEL_DUNGEON) + return; + + if (player_in_branch( BRANCH_MAIN_DUNGEON )) + { + // stair to HELL + if (dlevel >= 20 && dlevel <= 27) + place_specific_stair(DNGN_ENTER_HELL); + + // stair to PANDEMONIUM + if (dlevel >= 20 && dlevel <= 50 && (dlevel == 23 || one_chance_in(4))) + place_specific_stair(DNGN_ENTER_PANDEMONIUM); + + // stairs to ABYSS + if (dlevel >= 20 && dlevel <= 30 && (dlevel == 24 || one_chance_in(3))) + place_specific_stair(DNGN_ENTER_ABYSS); + + // level 26: replaces all down stairs with staircases to Zot: + if (dlevel == 26) + { + for (sx = 1; sx < GXM; sx++) + { + for (sy = 1; sy < GYM; sy++) + { + if (grd[sx][sy] >= DNGN_STONE_STAIRS_DOWN_I + && grd[sx][sy] <= DNGN_ROCK_STAIRS_DOWN) + { + grd[sx][sy] = DNGN_ENTER_ZOT; + } + } + } + } + } + + // place actual branch entrances + for (int branch = 0; branch < 30; branch++) + { + stair = 0; + entrance = 100; + + if (you.branch_stairs[branch] == 100) // set in newgame + break; + + if (you.branch_stairs[branch] != dlevel) + continue; + + // decide if this branch leaves from this level + switch(branch) + { + case STAIRS_ORCISH_MINES: + case STAIRS_HIVE: + case STAIRS_LAIR: + case STAIRS_VAULTS: + case STAIRS_ECUMENICAL_TEMPLE: + entrance = BRANCH_MAIN_DUNGEON; + break; + + case STAIRS_SLIME_PITS: + case STAIRS_SWAMP: + case STAIRS_SNAKE_PIT: + entrance = BRANCH_LAIR; + break; + + case STAIRS_ELVEN_HALLS: + entrance = BRANCH_ORCISH_MINES; + break; + + case STAIRS_CRYPT: + case STAIRS_HALL_OF_BLADES: + entrance = BRANCH_VAULTS; + break; + + case STAIRS_TOMB: + entrance = BRANCH_CRYPT; + break; + + default: + entrance = 100; + break; + } + + if (you.where_are_you != entrance) + continue; + + stair = branch + DNGN_ENTER_ORCISH_MINES; + place_specific_stair(stair); + } // end loop - possible branch entrances +} + +static void make_trail(int xs, int xr, int ys, int yr, int corrlength, + int intersect_chance, int no_corr, unsigned char begin, + unsigned char end) +{ + int x_start, y_start; // begin point + int x_ps, y_ps; // end point + int finish = 0; + int length = 0; + int temp_rand; + + // temp positions + int dir_x = 0; + int dir_y = 0; + int dir_x2, dir_y2; + + do + { + x_start = xs + random2(xr); + y_start = ys + random2(yr); + } + while (grd[x_start][y_start] != DNGN_ROCK_WALL + && grd[x_start][y_start] != DNGN_FLOOR); + + // assign begin feature + if (begin != 0) + grd[x_start][y_start] = begin; + x_ps = x_start; + y_ps = y_start; + + // wander + do // (while finish < no_corr) + { + dir_x2 = ((x_ps < 15) ? 1 : 0); + + if (x_ps > 65) + dir_x2 = -1; + + dir_y2 = ((y_ps < 15) ? 1 : 0); + + if (y_ps > 55) + dir_y2 = -1; + + temp_rand = random2(10); + + // Put something in to make it go to parts of map it isn't in now + if (coinflip()) + { + if (dir_x2 != 0 && temp_rand < 6) + dir_x = dir_x2; + + if (dir_x2 == 0 || temp_rand >= 6) + dir_x = (coinflip()? -1 : 1); + + dir_y = 0; + } + else + { + if (dir_y2 != 0 && temp_rand < 6) + dir_y = dir_y2; + + if (dir_y2 == 0 || temp_rand >= 6) + dir_y = (coinflip()? -1 : 1); + + dir_x = 0; + } + + if (dir_x == 0 && dir_y == 0) + continue; + + if (x_ps < 8) + { + dir_x = 1; + dir_y = 0; + } + + if (y_ps < 8) + { + dir_y = 1; + dir_x = 0; + } + + if (x_ps > (GXM - 8)) + { + dir_x = -1; + dir_y = 0; + } + + if (y_ps > (GYM - 8)) + { + dir_y = -1; + dir_x = 0; + } + + // corridor length.. change only when going vertical? + if (dir_x == 0 || length == 0) + length = random2(corrlength) + 2; + + int bi = 0; + + for (bi = 0; bi < length; bi++) + { + // Below, I've changed the values of the unimportant variable from + // 0 to random2(3) - 1 to avoid getting stuck on the "stuck!" bit + if (x_ps < 9) + { + dir_y = 0; //random2(3) - 1; + dir_x = 1; + } + + if (x_ps > (GXM - 9)) + { + dir_y = 0; //random2(3) - 1; + dir_x = -1; + } + + if (y_ps < 9) + { + dir_y = 1; + dir_x = 0; //random2(3) - 1; + } + + if (y_ps > (GYM - 9)) + { + dir_y = -1; + dir_x = 0; //random2(3) - 1; + } + + // don't interfere with special rooms + if (grd[x_ps + dir_x][y_ps + dir_y] == DNGN_BUILDER_SPECIAL_WALL) + break; + + // see if we stop due to intersection with another corridor/room + if (grd[x_ps + 2 * dir_x][y_ps + 2 * dir_y] == DNGN_FLOOR + && !one_chance_in(intersect_chance)) + break; + + x_ps += dir_x; + y_ps += dir_y; + + if (grd[x_ps][y_ps] == DNGN_ROCK_WALL) + grd[x_ps][y_ps] = DNGN_FLOOR; + } + + if (finish == no_corr - 1 && grd[x_ps][y_ps] != DNGN_FLOOR) + finish -= 2; + + finish++; + } + while (finish < no_corr); + + // assign end feature + if (end != 0) + grd[x_ps][y_ps] = end; +} + +static int good_door_spot(int x, int y) +{ + if ((grd[x][y] > DNGN_WATER_X && grd[x][y] < DNGN_ENTER_PANDEMONIUM) + || grd[x][y] == DNGN_CLOSED_DOOR) + { + return 1; + } + + return 0; +} + +// return TRUE if a room was made successfully +static bool make_room(int sx,int sy,int ex,int ey,int max_doors, int doorlevel) +{ + int find_door = 0; + int diag_door = 0; + int rx,ry; + + // check top & bottom for possible doors + for (rx = sx; rx <= ex; rx++) + { + find_door += good_door_spot(rx,sy); + find_door += good_door_spot(rx,ey); + } + + // check left and right for possible doors + for (ry = sy+1; ry < ey; ry++) + { + find_door += good_door_spot(sx,ry); + find_door += good_door_spot(ex,ry); + } + + diag_door += good_door_spot(sx,sy); + diag_door += good_door_spot(ex,sy); + diag_door += good_door_spot(sx,ey); + diag_door += good_door_spot(ex,ey); + + if ((diag_door + find_door) > 1 && max_doors == 1) + return false; + + if (find_door == 0 || find_door > max_doors) + return false; + + // look for 'special' rock walls - don't interrupt them + if (find_in_area(sx,sy,ex,ey,DNGN_BUILDER_SPECIAL_WALL)) + return false; + + // convert the area to floor + for (rx=sx; rx<=ex; rx++) + { + for(ry=sy; ry<=ey; ry++) + { + if (grd[rx][ry] <= DNGN_FLOOR) + grd[rx][ry] = DNGN_FLOOR; + } + } + + // put some doors on the sides (but not in corners), + // where it makes sense to do so. + for(ry=sy+1; ry 0 + && you.level_type == LEVEL_DUNGEON // avoid generating on temp levels + && !player_in_hell() + && !player_in_branch( BRANCH_ORCISH_MINES ) + && !player_in_branch( BRANCH_HIVE ) + && !player_in_branch( BRANCH_LAIR ) + && !player_in_branch( BRANCH_SLIME_PITS ) + && !player_in_branch( BRANCH_ECUMENICAL_TEMPLE )) + { + while(one_chance_in(3)) + { + which_unique = -1; // 30 in total + + while(which_unique < 0 || you.unique_creatures[which_unique]) + { + // sometimes, we just quit if a unique is already placed. + if (which_unique >= 0 && !one_chance_in(3)) + { + which_unique = -1; + break; + } + + which_unique = ((level_number > 19) ? 20 + random2(11) : + (level_number > 16) ? 13 + random2(10) : + (level_number > 13) ? 9 + random2( 9) : + (level_number > 9) ? 6 + random2( 5) : + (level_number > 7) ? 4 + random2( 4) : + (level_number > 3) ? 2 + random2( 4) + : random2(4)); + } + + // usually, we'll have quit after a few tries. Make sure we don't + // create unique[-1] by accident. + if (which_unique < 0) + break; + + // note: unique_creatures 40 + used by unique demons + if (place_monster( not_used, 280 + which_unique, level_number, + BEH_SLEEP, MHITNOT, false, 1, 1, true )) + { + totalplaced++; + } + } + } + + // do aquatic and lava monsters: + + // count the number of lava and water tiles {dlb}: + lava_spaces = 0; + water_spaces = 0; + + for (x = 0; x < GXM; x++) + { + for (y = 0; y < GYM; y++) + { + if (grd[x][y] == DNGN_LAVA) + { + lava_spaces++; + } + else if (grd[x][y] == DNGN_DEEP_WATER + || grd[x][y] == DNGN_SHALLOW_WATER) + { + water_spaces++; + } + } + } + + if (lava_spaces > 49) + { + for (i = 0; i < 4; i++) + { + swimming_things[i] = MONS_LAVA_WORM + random2(3); + + //mv: this is really ugly, but easiest + //IMO generation of water/lava beasts should be changed, + //because we want data driven code and not things like it + if (one_chance_in(30)) + swimming_things[i] = MONS_SALAMANDER; + } + + aq_creatures = random2avg(9, 2) + (random2(lava_spaces) / 10); + + if (aq_creatures > 15) + aq_creatures = 15; + + for (i = 0; i < aq_creatures; i++) + { + if (place_monster( not_used, swimming_things[ random2(4) ], + level_number, BEH_SLEEP, MHITNOT, + false, 1, 1, true )) + { + totalplaced++; + } + + if (totalplaced > 99) + break; + } + } + + if (water_spaces > 49) + { + for (i = 0; i < 4; i++) + { + // mixing enums and math ticks me off !!! 15jan2000 {dlb} + swimming_things[i] = MONS_BIG_FISH + random2(4); + + // swamp worms and h2o elementals generated below: {dlb} + if (player_in_branch( BRANCH_SWAMP ) && !one_chance_in(3)) + swimming_things[i] = MONS_SWAMP_WORM; + } + + if (level_number >= 25 && one_chance_in(5)) + swimming_things[0] = MONS_WATER_ELEMENTAL; + + if (player_in_branch( BRANCH_COCYTUS )) + swimming_things[3] = MONS_WATER_ELEMENTAL; + + aq_creatures = random2avg(9, 2) + (random2(water_spaces) / 10); + + if (aq_creatures > 15) + aq_creatures = 15; + + for (i = 0; i < aq_creatures; i++) + { + if (place_monster( not_used, swimming_things[ random2(4) ], + level_number, BEH_SLEEP, MHITNOT, + false, 1, 1, true )) + { + totalplaced++; + } + + if (totalplaced > 99) + break; + } + } +} + +static void builder_items(int level_number, char level_type, int items_wanted) +{ + UNUSED( level_type ); + + int i = 0; + unsigned char specif_type = OBJ_RANDOM; + int items_levels = level_number; + int item_no; + + if (player_in_branch( BRANCH_VAULTS )) + { + items_levels *= 15; + items_levels /= 10; + } + else if (player_in_branch( BRANCH_ORCISH_MINES )) + { + specif_type = OBJ_GOLD; /* lots of gold in the orcish mines */ + } + + if (player_in_branch( BRANCH_VESTIBULE_OF_HELL ) + || player_in_hell() + || player_in_branch( BRANCH_SLIME_PITS ) + || player_in_branch( BRANCH_HALL_OF_BLADES ) + || player_in_branch( BRANCH_ECUMENICAL_TEMPLE )) + { + /* No items in hell, the slime pits, the Hall */ + return; + } + else + { + for (i = 0; i < items_wanted; i++) + items( 1, specif_type, OBJ_RANDOM, false, items_levels, 250 ); + + // Make sure there's a very good chance of a knife being placed + // in the first five levels, but not a guarantee of one. The + // intent of this is to reduce the advantage that "cutting" + // starting weapons have. -- bwr + if (player_in_branch( BRANCH_MAIN_DUNGEON ) + && level_number < 5 && coinflip()) + { + item_no = items( 0, OBJ_WEAPONS, WPN_KNIFE, false, 0, 250 ); + + // Guarantee that the knife is uncursed and non-special + if (item_no != NON_ITEM) + { + mitm[item_no].plus = 0; + mitm[item_no].plus2 = 0; + mitm[item_no].flags = 0; // no id, no race/desc, no curse + mitm[item_no].special = 0; // no ego type + } + } + } +} + +// the entire intent of this function is to find a +// hallway from a special room to a floor space somewhere, +// changing the special room wall (DNGN_BUILDER_SPECIAL_WALL) +// to a closed door, and normal rock wall to pre-floor. +// Anything that might otherwise block the hallway is changed +// to pre-floor. +static void specr_2(spec_room &sr) +{ + int bkout = 0; + int cx = 0, cy = 0; + int sx = 0, sy = 0; + int dx = 0, dy = 0; + int i,j; + + // paranoia -- how did we get here if there's no actual special room?? + if (!sr.created) + return; + + grolko: + + if (bkout > 100) + return; + + switch (random2(4)) + { + case 0: + // go up from north edge + cx = sr.x1 + (random2(sr.x2 - sr.x1)); + cy = sr.y1; + dx = 0; + dy = -1; + break; + case 1: + // go down from south edge + cx = sr.x1 + (random2(sr.x2 - sr.x1)); + cy = sr.y2; + dx = 0; + dy = 1; + break; + case 2: + // go left from west edge + cy = sr.y1 + (random2(sr.y2 - sr.y1)); + cx = sr.x1; + dx = -1; + dy = 0; + break; + case 3: + // go right from east edge + cy = sr.y1 + (random2(sr.y2 - sr.y1)); + cx = sr.x2; + dx = 1; + dy = 0; + break; + } + + sx = cx; + sy = cy; + + for (i = 0; i < 100; i++) + { + sx += dx; + sy += dy; + + // quit if we run off the map before finding floor + if (sx < 6 || sx > (GXM - 7) || sy < 6 || sy > (GYM - 7)) + { + bkout++; + goto grolko; + } + + // look around for floor + if (i > 0) + { + if (grd[sx + 1][sy] == DNGN_FLOOR) + break; + if (grd[sx][sy + 1] == DNGN_FLOOR) + break; + if (grd[sx - 1][sy] == DNGN_FLOOR) + break; + if (grd[sx][sy - 1] == DNGN_FLOOR) + break; + } + } + + sx = cx; + sy = cy; + + for (j = 0; j < i + 2; j++) + { + if (grd[sx][sy] == DNGN_BUILDER_SPECIAL_WALL) + grd[sx][sy] = DNGN_CLOSED_DOOR; + + if (j > 0 && grd[sx + dx][sy + dy] > DNGN_ROCK_WALL + && grd[sx + dx][sy + dy] < DNGN_FLOOR) + grd[sx][sy] = DNGN_BUILDER_SPECIAL_FLOOR; + + if (grd[sx][sy] == DNGN_ROCK_WALL) + grd[sx][sy] = DNGN_BUILDER_SPECIAL_FLOOR; + + sx += dx; + sy += dy; + } + + sr.hooked_up = true; +} // end specr_2() + +static void special_room(int level_number, spec_room &sr) +{ + char spec_room_type = SROOM_LAIR_KOBOLD; + int lev_mons; + int thing_created = 0; + int x, y; + + unsigned char obj_type = OBJ_RANDOM; // used in calling items() {dlb} + unsigned char i; // general purpose loop variable {dlb} + int temp_rand = 0; // probability determination {dlb} + + FixedVector < int, 10 > mons_alloc; // was [20] {dlb} + + char lordx = 0, lordy = 0; + + // overwrites anything; this function better be called early on during + // creation.. + int room_x1 = 8 + random2(55); + int room_y1 = 8 + random2(45); + int room_x2 = room_x1 + 4 + random2avg(6,2); + int room_y2 = room_y1 + 4 + random2avg(6,2); + + // do special walls & floor + make_box( room_x1, room_y1, room_x2, room_y2, + DNGN_BUILDER_SPECIAL_FLOOR, DNGN_BUILDER_SPECIAL_WALL ); + + // set up passed in spec_room structure + sr.created = true; + sr.hooked_up = false; + sr.x1 = room_x1 + 1; + sr.x2 = room_x2 - 1; + sr.y1 = room_y1 + 1; + sr.y2 = room_y2 - 1; + + if (level_number < 7) + spec_room_type = SROOM_LAIR_KOBOLD; + else + { + spec_room_type = random2(NUM_SPECIAL_ROOMS); + + if (level_number < 23 && one_chance_in(4)) + spec_room_type = SROOM_BEEHIVE; + + if ((level_number > 13 && spec_room_type == SROOM_LAIR_KOBOLD) + || (level_number < 16 && spec_room_type == SROOM_MORGUE) + || (level_number < 17 && one_chance_in(4))) + { + spec_room_type = SROOM_LAIR_ORC; + } + + if (level_number > 19 && coinflip()) + spec_room_type = SROOM_MORGUE; + } + + + switch (spec_room_type) + { + case SROOM_LAIR_ORC: + // determine which monster array to generate {dlb}: + lev_mons = ((level_number > 24) ? 3 : + (level_number > 15) ? 2 : + (level_number > 9) ? 1 + : 0); + + // fill with baseline monster type {dlb}: + for (i = 0; i < 10; i++) + { + mons_alloc[i] = MONS_ORC; + } + + // fill in with special monster types {dlb}: + switch (lev_mons) + { + case 0: + mons_alloc[9] = MONS_ORC_WARRIOR; + break; + case 1: + mons_alloc[8] = MONS_ORC_WARRIOR; + mons_alloc[9] = MONS_ORC_WARRIOR; + break; + case 2: + mons_alloc[6] = MONS_ORC_KNIGHT; + mons_alloc[7] = MONS_ORC_WARRIOR; + mons_alloc[8] = MONS_ORC_WARRIOR; + mons_alloc[9] = MONS_OGRE; + break; + case 3: + mons_alloc[2] = MONS_ORC_WARRIOR; + mons_alloc[3] = MONS_ORC_WARRIOR; + mons_alloc[4] = MONS_ORC_WARRIOR; + mons_alloc[5] = MONS_ORC_KNIGHT; + mons_alloc[6] = MONS_ORC_KNIGHT; + mons_alloc[7] = MONS_OGRE; + mons_alloc[8] = MONS_OGRE; + mons_alloc[9] = MONS_TROLL; + break; + } + + // place monsters and give them items {dlb}: + for (x = sr.x1; x <= sr.x2; x++) + { + for (y = sr.y1; y <= sr.y2; y++) + { + if (one_chance_in(4)) + continue; + + mons_place( mons_alloc[random2(10)], BEH_SLEEP, MHITNOT, + true, x, y ); + } + } + break; + + case SROOM_LAIR_KOBOLD: + lordx = sr.x1 + random2(sr.x2 - sr.x1); + lordy = sr.y1 + random2(sr.y2 - sr.y1); + + // determine which monster array to generate {dlb}: + lev_mons = ((level_number < 4) ? 0 : + (level_number < 6) ? 1 : (level_number < 9) ? 2 : 3); + + // fill with baseline monster type {dlb}: + for (i = 0; i < 10; i++) + { + mons_alloc[i] = MONS_KOBOLD; + } + + // fill in with special monster types {dlb}: + // in this case, they are uniformly the same {dlb}: + for (i = (7 - lev_mons); i < 10; i++) + { + mons_alloc[i] = MONS_BIG_KOBOLD; + } + + // place monsters and give them items {dlb}: + for (x = sr.x1; x <= sr.x2; x++) + { + for (y = sr.y1; y <= sr.y2; y++) + { + if (one_chance_in(4)) + continue; + + // we'll put the boss down later. + if (x == lordx && y == lordy) + continue; + + mons_place( mons_alloc[random2(10)], BEH_SLEEP, MHITNOT, + true, x, y ); + } + } + + // put the boss monster down + mons_place( MONS_BIG_KOBOLD, BEH_SLEEP, MHITNOT, true, lordx, lordy ); + + break; + + case SROOM_TREASURY: + // should only appear in deep levels, with a guardian + // Maybe have several types of treasure room? + // place treasure {dlb}: + for (x = sr.x1; x <= sr.x2; x++) + { + for (y = sr.y1; y <= sr.y2; y++) + { + temp_rand = random2(11); + + obj_type = ((temp_rand > 8) ? OBJ_WEAPONS : // 2 in 11 + (temp_rand > 6) ? OBJ_ARMOUR : // 2 in 11 + (temp_rand > 5) ? OBJ_MISSILES : // 1 in 11 + (temp_rand > 4) ? OBJ_WANDS : // 1 in 11 + (temp_rand > 3) ? OBJ_SCROLLS : // 1 in 11 + (temp_rand > 2) ? OBJ_JEWELLERY : // 1 in 11 + (temp_rand > 1) ? OBJ_BOOKS : // 1 in 11 + (temp_rand > 0) ? OBJ_STAVES // 1 in 11 + : OBJ_POTIONS); // 1 in 11 + + thing_created = items( 1, obj_type, OBJ_RANDOM, true, + level_number * 3, 250 ); + + if (thing_created != NON_ITEM) + { + mitm[thing_created].x = x; + mitm[thing_created].y = y; + } + } + } + + // place guardian {dlb}: + mons_place( MONS_GUARDIAN_NAGA, BEH_SLEEP, MHITNOT, true, + sr.x1 + random2( sr.x2 - sr.x1 ), + sr.y1 + random2( sr.y2 - sr.y1 ) ); + + break; + + case SROOM_BEEHIVE: + beehive(sr); + break; + + case SROOM_MORGUE: + morgue(sr); + break; + } +} // end special_room() + +// fills a special room with bees +static void beehive(spec_room &sr) +{ + int i; + int x,y; + + for (x = sr.x1; x <= sr.x2; x++) + { + for (y = sr.y1; y <= sr.y2; y++) + { + if (coinflip()) + continue; + + i = get_item_slot(); + if (i == NON_ITEM) + goto finished_food; + + mitm[i].quantity = 1; + mitm[i].base_type = OBJ_FOOD; + mitm[i].sub_type = (one_chance_in(25) ? FOOD_ROYAL_JELLY + : FOOD_HONEYCOMB); + mitm[i].x = x; + mitm[i].y = y; + + item_colour( mitm[i] ); + } + } + + + finished_food: + + int queenx = sr.x1 + random2(sr.x2 - sr.x1); + int queeny = sr.y1 + random2(sr.y2 - sr.y1); + + for (x = sr.x1; x <= sr.x2; x++) + { + for (y = sr.y1; y <= sr.y2; y++) + { + if (x == queenx && y == queeny) + continue; + + // the hive is chock full of bees! + + mons_place( one_chance_in(7) ? MONS_KILLER_BEE_LARVA + : MONS_KILLER_BEE, + BEH_SLEEP, MHITNOT, true, x, y ); + } + } + + mons_place( MONS_QUEEN_BEE, BEH_SLEEP, MHITNOT, true, queenx, queeny ); +} // end beehive() + +static void build_minivaults(int level_number, int force_vault) +{ + // for some weird reason can't put a vault on level 1, because monster equip + // isn't generated. + int altar_count = 0; + + FixedVector < char, 7 > acq_item_class; + // hack - passing chars through '...' promotes them to ints, which + // barfs under gcc in fixvec.h. So don't. + acq_item_class[0] = OBJ_WEAPONS; + acq_item_class[1] = OBJ_ARMOUR; + acq_item_class[2] = OBJ_WEAPONS; + acq_item_class[3] = OBJ_JEWELLERY; + acq_item_class[4] = OBJ_BOOKS; + acq_item_class[5] = OBJ_STAVES; + acq_item_class[6] = OBJ_MISCELLANY; + + FixedVector < int, 7 > mons_array(RANDOM_MONSTER, + RANDOM_MONSTER, + RANDOM_MONSTER, + RANDOM_MONSTER, + RANDOM_MONSTER, + RANDOM_MONSTER, + RANDOM_MONSTER); + + char vgrid[81][81]; + + if (force_vault == 200) + { + force_vault = 200 + random2(37); + } + + vault_main(vgrid, mons_array, force_vault, level_number); + + int vx, vy; + int v1x, v1y; + + /* find a target area which can be safely overwritten: */ + while(1) + { + //if ( one_chance_in(1000) ) return; + v1x = 12 + random2(45); + v1y = 12 + random2(35); + + for (vx = v1x; vx < v1x + 12; vx++) + { + for (vy = v1y; vy < v1y + 12; vy++) + { + if (one_chance_in(2000)) + return; + + if ((grd[vx][vy] != DNGN_FLOOR + && grd[vx][vy] != DNGN_ROCK_WALL + && grd[vx][vy] != DNGN_CLOSED_DOOR + && grd[vx][vy] != DNGN_SECRET_DOOR) + || igrd[vx][vy] != NON_ITEM + || mgrd[vx][vy] != NON_MONSTER) + { + goto out_of_check; + } + } + } + + /* must not be completely isolated: */ + for (vx = v1x; vx < v1x + 12; vx++) + { + // if (vx != v1x && vx != v1x + 12) continue; + for (vy = v1y; vy < v1y + 12; vy++) + { + // if (vy != v1y && vy != v1y + 12) continue; + if (grd[vx][vy] == DNGN_FLOOR + || grd[vx][vy] == DNGN_CLOSED_DOOR + || grd[vx][vy] == DNGN_SECRET_DOOR) + goto break_out; + } + } + + out_of_check: + continue; + + break_out: + break; + } + + for (vx = v1x; vx < v1x + 12; vx++) + { + for (vy = v1y; vy < v1y + 12; vy++) + { + grd[vx][vy] = vgrid[vx - v1x][vy - v1y]; + } + } + + // these two are throwaways: + int initial_x, initial_y; + int num_runes = 0; + + // paint the minivault onto the grid + for (vx = v1x; vx < v1x + 12; vx++) + { + for (vy = v1y; vy < v1y + 12; vy++) + { + altar_count = vault_grid( level_number, vx, vy, altar_count, + acq_item_class, mons_array, + grd[vx][vy], initial_x, initial_y, + force_vault, num_runes ); + } + } +} // end build_minivaults() + +static void build_vaults(int level_number, int force_vault) +{ + // for some weird reason can't put a vault on level 1, because monster equip + // isn't generated. + int i,j; // general loop variables + int altar_count = 0; + FixedVector < char, 10 > stair_exist; + char stx, sty; + int initial_x=0, initial_y=0; + + FixedVector < char, 7 > acq_item_class; + // hack - passing chars through '...' promotes them to ints, which + // barfs under gcc in fixvec.h. So don't. -- GDL + acq_item_class[0] = OBJ_WEAPONS; + acq_item_class[1] = OBJ_ARMOUR; + acq_item_class[2] = OBJ_WEAPONS; + acq_item_class[3] = OBJ_JEWELLERY; + acq_item_class[4] = OBJ_BOOKS; + acq_item_class[5] = OBJ_STAVES; + acq_item_class[6] = OBJ_MISCELLANY; + + FixedVector < int, 7 > mons_array(RANDOM_MONSTER, + RANDOM_MONSTER, + RANDOM_MONSTER, + RANDOM_MONSTER, + RANDOM_MONSTER, + RANDOM_MONSTER, + RANDOM_MONSTER); + + char roomsss = 10 + random2(90); + char which_room = 0; + + bool exclusive = (one_chance_in(10) ? false : true); + + //bool exclusive2 = coinflip(); // usage commented out below {dlb} + + char vgrid[81][81]; + + char gluggy = vault_main(vgrid, mons_array, force_vault, level_number); + + int vx, vy; + int v1x = 0, v1y = 0, v2x = 0, v2y = 0; + + //int item_made; + + char dig_dir_x = 0; + char dig_dir_y = 0; + char dig_place_x = 0; + char dig_place_y = 0; + int num_runes = 0; + + // note: assumes *no* previous item (I think) or monster (definitely) + // placement + for (vx = 0; vx < GXM; vx++) + { + for (vy = 0; vy < GYM; vy++) + { + altar_count = vault_grid( level_number, vx, vy, altar_count, + acq_item_class, mons_array, + vgrid[vy][vx], initial_x, initial_y, + force_vault, num_runes ); + } + } + + switch (gluggy) + { + case MAP_NORTH: + v1x = 1; + v2x = GXM; + v1y = 1; + v2y = 35; + initial_y++; + dig_dir_x = 0; + dig_dir_y = 1; + break; + + case MAP_NORTHWEST: + v1x = 1; + v2x = 40; + v1y = 1; + v2y = 35; + initial_y++; + dig_dir_x = 1; + dig_dir_y = 0; + break; + + case MAP_NORTHEAST: + v1x = 40; + v2x = GXM; + v1y = 1; + v2y = 35; + initial_y++; + dig_dir_x = -1; + dig_dir_y = 0; + break; + + case MAP_SOUTHWEST: + v1x = 1; + v2x = 40; + v1y = 35; + v2y = GYM; + initial_y--; + dig_dir_x = 0; + dig_dir_y = -1; + break; + + case MAP_SOUTHEAST: + v1x = 40; + v2x = GXM; + v1y = 35; + v2y = GYM; + initial_y--; + dig_dir_x = 0; + dig_dir_y = -1; + break; + + case MAP_ENCOMPASS: + return; + + case MAP_NORTH_DIS: + v1x = 1; + v2x = GXM; + v1y = 1; + v2y = 35; + plan_4(1, 1, 80, 35, DNGN_METAL_WALL); + goto vstair; + } + + char cnx, cny; + char romx1[30], romy1[30], romx2[30], romy2[30]; + + for (i = 0; i < roomsss; i++) + { + do + { + romx1[which_room] = 10 + random2(50); + romy1[which_room] = 10 + random2(40); + romx2[which_room] = romx1[which_room] + 2 + random2(8); + romy2[which_room] = romy1[which_room] + 2 + random2(8); + } + while ((romx1[which_room] >= v1x && romx1[which_room] <= v2x + && romy1[which_room] >= v1y && romy1[which_room] <= v2y) + || (romx2[which_room] >= v1x && romx2[which_room] <= v2x + && romy2[which_room] >= v1y && romy2[which_room] <= v2y)); + + if (i == 0) + { + join_the_dots(initial_x, initial_y, romx1[which_room], romy1[which_room], + v1x, v1y, v2x, v2y); + } + else if (exclusive) + { + for (cnx = romx1[which_room] - 1; cnx < romx2[which_room] + 1; + cnx++) + { + for (cny = romy1[which_room] - 1; cny < romy2[which_room] + 1; + cny++) + { + if (grd[cnx][cny] != DNGN_ROCK_WALL) + goto continuing; + } + } + } + + replace_area(romx1[which_room], romy1[which_room], romx2[which_room], + romy2[which_room], DNGN_ROCK_WALL, DNGN_FLOOR); + + if (which_room > 0) // && !exclusive2 + { + const int rx1 = romx1[which_room]; + const int rx2 = romx2[which_room]; + const int prev_rx1 = romx1[which_room - 1]; + const int prev_rx2 = romx2[which_room - 1]; + + const int ry1 = romy1[which_room]; + const int ry2 = romy2[which_room]; + const int prev_ry1 = romy1[which_room - 1]; + const int prev_ry2 = romy2[which_room - 1]; + + join_the_dots( rx1 + random2( rx2 - rx1 ), + ry1 + random2( ry2 - ry1 ), + prev_rx1 + random2( prev_rx2 - prev_rx1 ), + prev_ry1 + random2( prev_ry2 - prev_ry1 ), + v1x, v1y, v2x, v2y); + } + + which_room++; + + if (which_room >= 29) + break; + + continuing: + continue; // next i loop + + } + + vstair: + dig_place_x = initial_x; + dig_place_y = initial_y; + + if (gluggy != MAP_NORTH_DIS) + { + for (i = 0; i < 40; i++) + { + dig_place_x += dig_dir_x; + dig_place_y += dig_dir_y; + + if (dig_place_x < 10 || dig_place_x > (GXM - 10) + || dig_place_y < 10 || dig_place_y > (GYM - 10)) + { + break; + } + + if (grd[dig_place_x][dig_place_y] == DNGN_ROCK_WALL) + grd[dig_place_x][dig_place_y] = DNGN_FLOOR; + } + } + + unsigned char pos_x, pos_y; + + for (stx = 0; stx < 10; stx++) + stair_exist[stx] = 0; + + for (stx = 0; stx < GXM; stx++) + { + for (sty = 0; sty < GYM; sty++) + { + if (grd[stx][sty] >= DNGN_STONE_STAIRS_DOWN_I + && grd[stx][sty] <= DNGN_ROCK_STAIRS_UP) + { + stair_exist[grd[stx][sty] - 82] = 1; + } + } + } + + if (player_in_branch( BRANCH_DIS )) + { + for (sty = 0; sty < 5; sty++) + stair_exist[sty] = 1; + + for (sty = 6; sty < 10; sty++) + stair_exist[sty] = 0; + } + + for (j = 0; j < (coinflip()? 4 : 3); j++) + { + for (i = 0; i < 2; i++) + { + + if (stair_exist[(82 + j + (i * 4)) - 82] == 1) // does this look funny to *you*? {dlb} + continue; + + do + { + pos_x = 10 + random2(GXM - 20); + pos_y = 10 + random2(GYM - 20); + } + while (grd[pos_x][pos_y] != DNGN_FLOOR + || (pos_x >= v1x && pos_x <= v2x && pos_y >= v1y + && pos_y <= v2y)); + + grd[pos_x][pos_y] = j + ((i == 0) ? DNGN_STONE_STAIRS_DOWN_I + : DNGN_STONE_STAIRS_UP_I); + } + } +} // end build_vaults() + +// returns altar_count - seems rather odd to me to force such a return +// when I believe the value is only used in the case of the ecumenical +// temple - oh, well... {dlb} +static int vault_grid( int level_number, int vx, int vy, int altar_count, + FixedVector < char, 7 > &acq_item_class, + FixedVector < int, 7 > &mons_array, + char vgrid, int &initial_x, int &initial_y, + int force_vault, int &num_runes) +{ + int not_used; + + // first, set base tile for grids {dlb}: + grd[vx][vy] = ((vgrid == 'x') ? DNGN_ROCK_WALL : + (vgrid == 'X') ? DNGN_PERMAROCK_WALL : + (vgrid == 'c') ? DNGN_STONE_WALL : + (vgrid == 'v') ? DNGN_METAL_WALL : + (vgrid == 'b') ? DNGN_GREEN_CRYSTAL_WALL : + (vgrid == 'a') ? DNGN_WAX_WALL : + (vgrid == '+') ? DNGN_CLOSED_DOOR : + (vgrid == '=') ? DNGN_SECRET_DOOR : + (vgrid == 'w') ? DNGN_DEEP_WATER : + (vgrid == 'l') ? DNGN_LAVA : + (vgrid == '>') ? DNGN_ROCK_STAIRS_DOWN : + (vgrid == '<') ? DNGN_ROCK_STAIRS_UP : + (vgrid == '}') ? DNGN_STONE_STAIRS_DOWN_I : + (vgrid == '{') ? DNGN_STONE_STAIRS_UP_I : + (vgrid == ')') ? DNGN_STONE_STAIRS_DOWN_II : + (vgrid == '(') ? DNGN_STONE_STAIRS_UP_II : + (vgrid == ']') ? DNGN_STONE_STAIRS_DOWN_III : + (vgrid == '[') ? DNGN_STONE_STAIRS_UP_III : + (vgrid == 'A') ? DNGN_STONE_ARCH : + (vgrid == 'B') ? (DNGN_ALTAR_ZIN + altar_count) :// see below + (vgrid == 'C') ? pick_an_altar() : // f(x) elsewhere {dlb} + + (vgrid == 'F') ? (one_chance_in(100) + ? (coinflip() ? DNGN_SILVER_STATUE + : DNGN_ORANGE_CRYSTAL_STATUE) + : DNGN_GRANITE_STATUE) : + + (vgrid == 'I') ? DNGN_ORCISH_IDOL : + (vgrid == 'S') ? DNGN_SILVER_STATUE : + (vgrid == 'G') ? DNGN_GRANITE_STATUE : + (vgrid == 'H') ? DNGN_ORANGE_CRYSTAL_STATUE : + (vgrid == 'T') ? DNGN_BLUE_FOUNTAIN : + (vgrid == 'U') ? DNGN_SPARKLING_FOUNTAIN : + (vgrid == 'V') ? DNGN_PERMADRY_FOUNTAIN : + (vgrid == '\0')? DNGN_ROCK_WALL : + DNGN_FLOOR); // includes everything else + + // then, handle oddball grids {dlb}: + switch (vgrid) + { + case 'B': + altar_count++; + break; + case '@': + initial_x = vx; + initial_y = vy; + break; + case '^': + place_specific_trap(vx, vy, TRAP_RANDOM); + break; + } + + // then, handle grids that place "stuff" {dlb}: + switch (vgrid) // yes, I know this is a bit ugly ... {dlb} + { + case 'R': + case '$': + case '%': + case '*': + case '|': + case 'P': // possible rune + case 'O': // definite rune + case 'Z': // definite orb + { + int item_made = NON_ITEM; + unsigned char which_class = OBJ_RANDOM; + unsigned char which_type = OBJ_RANDOM; + int which_depth; + bool possible_rune = one_chance_in(3); // lame, I know {dlb} + int spec = 250; + + if (vgrid == 'R') + { + which_class = OBJ_FOOD; + which_type = (one_chance_in(3) ? FOOD_ROYAL_JELLY + : FOOD_HONEYCOMB); + } + else if (vgrid == '$') + { + which_class = OBJ_GOLD; + which_type = OBJ_RANDOM; + } + else if (vgrid == '%' || vgrid == '*') + { + which_class = OBJ_RANDOM; + which_type = OBJ_RANDOM; + } + else if (vgrid == 'Z') + { + which_class = OBJ_ORBS; + which_type = ORB_ZOT; + } + else if (vgrid == '|' + || (vgrid == 'P' && (!possible_rune || num_runes > 0)) + || (vgrid == 'O' && num_runes > 0)) + { + which_class = acq_item_class[random2(7)]; + which_type = OBJ_RANDOM; + } + else // for 'P' (1 out of 3 times) {dlb} + { + which_class = OBJ_MISCELLANY; + which_type = MISC_RUNE_OF_ZOT; + num_runes++; + + if (you.level_type == LEVEL_PANDEMONIUM) + { + if (force_vault >= 60 && force_vault <= 63) + spec = force_vault; + else + spec = 50; + } + else if (you.level_type == LEVEL_ABYSS) + spec = 51; + else + spec = you.where_are_you; + } + + which_depth = ((vgrid == '|' + || vgrid == 'P' + || vgrid == 'O' + || vgrid == 'Z') ? MAKE_GOOD_ITEM : + (vgrid == '*') ? 5 + (level_number * 2) + : level_number); + + item_made = items( 1, which_class, which_type, true, + which_depth, spec ); + + if (item_made != NON_ITEM) + { + mitm[item_made].x = vx; + mitm[item_made].y = vy; + } + } + break; + } + + // finally, handle grids that place monsters {dlb}: + if (vgrid >= '0' && vgrid <= '9') + { + int monster_level; + int monster_type_thing; + + monster_level = ((vgrid == '8') ? (4 + (level_number * 2)) : + (vgrid == '9') ? (5 + level_number) : level_number); + + if (monster_level > 30) // very high level monsters more common here + monster_level = 30; + + monster_type_thing = ((vgrid == '8' + || vgrid == '9' + || vgrid == '0') ? RANDOM_MONSTER + : mons_array[(vgrid - '1')]); + + place_monster( not_used, monster_type_thing, monster_level, BEH_SLEEP, + MHITNOT, true, vx, vy, false); + } + + // again, this seems odd, given that this is just one of many + // vault types {dlb} + return (altar_count); +} // end vault_grid() + +static void replace_area(int sx, int sy, int ex, int ey, unsigned char replace, + unsigned char feature) +{ + int x,y; + for(x=sx; x<=ex; x++) + for(y=sy; y<=ey; y++) + if (grd[x][y] == replace) + grd[x][y] = feature; +} + +static void join_the_dots(unsigned char dotx1, unsigned char doty1, + unsigned char dotx2, unsigned char doty2, + char forbid_x1, char forbid_y1, char forbid_x2, + char forbid_y2) +{ + if (dotx1 == dotx2 && doty1 == doty2) + return; + + char atx = dotx1, aty = doty1; + + int join_count = 0; + + grd[atx][aty] = DNGN_FLOOR; + + do + { + join_count++; + + if (join_count > 10000) // just insurance + return; + + if (atx < dotx2 + && (forbid_x1 == 0 + || (atx + 1 < forbid_x1 || atx + 1 > forbid_x2 + || (aty > forbid_y2 || aty < forbid_y1)))) + { + atx++; + goto continuing; + } + + if (atx > dotx2 + && (forbid_x2 == 0 + || (atx - 1 > forbid_x2 || atx - 1 < forbid_x1 + || (aty > forbid_y2 || aty < forbid_y1)))) + { + atx--; + goto continuing; + } + + if (aty > doty2 + && (forbid_y2 == 0 + || (aty - 1 > forbid_y2 || aty - 1 < forbid_y1 + || (atx > forbid_x2 || atx < forbid_x1)))) + { + aty--; + goto continuing; + } + + if (aty < doty2 + && (forbid_y1 == 0 + || (aty + 1 < forbid_y1 || aty + 1 > forbid_y2 + || (atx > forbid_x2 || atx < forbid_x1)))) + { + aty++; + goto continuing; + } + + continuing: + grd[atx][aty] = DNGN_FLOOR; + + } + while (atx != dotx2 || aty != doty2); +} // end join_the_dots() + +static void place_pool(unsigned char pool_type, unsigned char pool_x1, + unsigned char pool_y1, unsigned char pool_x2, + unsigned char pool_y2) +{ + int i, j; + unsigned char left_edge, right_edge; + + // don't place LAVA pools in crypt.. use shallow water instead. + if (pool_type == DNGN_LAVA + && (player_in_branch(BRANCH_CRYPT) || player_in_branch(BRANCH_TOMB))) + { + pool_type = DNGN_SHALLOW_WATER; + } + + if (pool_x1 >= pool_x2 - 4 || pool_y1 >= pool_y2 - 4) + return; + + left_edge = pool_x1 + 2 + random2(pool_x2 - pool_x1); + right_edge = pool_x2 - 2 - random2(pool_x2 - pool_x1); + + for (j = pool_y1 + 1; j < pool_y2 - 1; j++) + { + for (i = pool_x1 + 1; i < pool_x2 - 1; i++) + { + if (i >= left_edge && i <= right_edge && grd[i][j] == DNGN_FLOOR) + grd[i][j] = pool_type; + } + + if (j - pool_y1 < (pool_y2 - pool_y1) / 2 || one_chance_in(4)) + { + if (left_edge > pool_x1 + 1) + left_edge -= random2(3); + + if (right_edge < pool_x2 - 1) + right_edge += random2(3); + } + + if (left_edge < pool_x2 - 1 + && (j - pool_y1 >= (pool_y2 - pool_y1) / 2 + || left_edge <= pool_x1 + 2 || one_chance_in(4))) + { + left_edge += random2(3); + } + + if (right_edge > pool_x1 + 1 + && (j - pool_y1 >= (pool_y2 - pool_y1) / 2 + || right_edge >= pool_x2 - 2 || one_chance_in(4))) + { + right_edge -= random2(3); + } + } +} // end place_pool() + +static void many_pools(unsigned char pool_type) +{ + int pools = 0; + int i = 0, j = 0, k = 0, l = 0; + int m = 0, n = 0; + int no_pools = 20 + random2avg(9, 2); + int timeout = 0; + + if (player_in_branch( BRANCH_COCYTUS )) + pool_type = DNGN_DEEP_WATER; + else if (player_in_branch( BRANCH_GEHENNA )) + pool_type = DNGN_LAVA; + + do + { + timeout++; + + if (timeout >= 30000) + break; + + i = 6 + random2( GXM - 26 ); + j = 6 + random2( GYM - 26 ); + k = i + 2 + roll_dice( 2, 9 ); + l = j + 2 + roll_dice( 2, 9 ); + + for (m = i; m < k; m++) + { + for (n = j; n < l; n++) + { + if (grd[m][n] != DNGN_FLOOR) + goto continue_pools; + } + } + + place_pool(pool_type, i, j, k, l); + pools++; + + continue_pools: + continue; + } + while (pools < no_pools); +} // end many_pools() + +void item_colour( item_def &item ) +{ + int switchnum = 0; + int temp_value; + + switch (item.base_type) + { + case OBJ_WEAPONS: + if (is_unrandom_artefact( item )) + break; // unrandarts already coloured + + if (is_fixed_artefact( item )) + { + switch (item.special) // was: - 180, but that is *wrong* {dlb} + { + case SPWPN_SINGING_SWORD: + case SPWPN_SCEPTRE_OF_TORMENT: + item.colour = YELLOW; + break; + case SPWPN_WRATH_OF_TROG: + case SPWPN_SWORD_OF_POWER: + item.colour = RED; + break; + case SPWPN_SCYTHE_OF_CURSES: + item.colour = DARKGREY; + break; + case SPWPN_MACE_OF_VARIABILITY: + item.colour = random_colour(); + break; + case SPWPN_GLAIVE_OF_PRUNE: + item.colour = MAGENTA; + break; + case SPWPN_SWORD_OF_ZONGULDROK: + item.colour = LIGHTGREY; + break; + case SPWPN_KNIFE_OF_ACCURACY: + item.colour = LIGHTCYAN; + break; + case SPWPN_STAFF_OF_OLGREB: + item.colour = GREEN; + break; + case SPWPN_VAMPIRES_TOOTH: + item.colour = WHITE; + break; + case SPWPN_STAFF_OF_WUCAD_MU: + item.colour = BROWN; + break; + } + break; + } + + if (is_demonic( item.sub_type )) + item.colour = random_colour(); + else if (launches_things( item.sub_type )) + item.colour = BROWN; + else + { + switch (item.sub_type) + { + case WPN_CLUB: + case WPN_GIANT_CLUB: + case WPN_GIANT_SPIKED_CLUB: + case WPN_ANCUS: + case WPN_WHIP: + case WPN_QUARTERSTAFF: + item.colour = BROWN; + break; + case WPN_QUICK_BLADE: + item.colour = LIGHTBLUE; + break; + case WPN_EXECUTIONERS_AXE: + item.colour = RED; + break; + default: + item.colour = LIGHTCYAN; + if (cmp_equip_race( item, ISFLAG_DWARVEN )) + item.colour = CYAN; + break; + } + } + + // I don't think this is ever done -- see start of case {dlb}: + if (is_random_artefact( item ) && one_chance_in(5)) + item.colour = random_colour(); + break; + + case OBJ_MISSILES: + switch (item.sub_type) + { + case MI_STONE: + case MI_LARGE_ROCK: + case MI_ARROW: + item.colour = BROWN; + break; + case MI_NEEDLE: + item.colour = WHITE; + break; + default: + item.colour = LIGHTCYAN; + if (cmp_equip_race( item, ISFLAG_DWARVEN )) + item.colour = CYAN; + break; + } + break; + + case OBJ_ARMOUR: + if (is_unrandom_artefact( item )) + break; /* unrandarts have already been coloured */ + + switch (item.sub_type) + { + case ARM_CLOAK: + case ARM_ROBE: + item.colour = random_colour(); + break; + + case ARM_HELMET: + //caps and wizard's hats are random coloured + if (cmp_helmet_type( item, THELM_CAP ) + || cmp_helmet_type( item, THELM_WIZARD_HAT )) + { + item.colour = random_colour(); + } + else + item.colour = LIGHTCYAN; + break; + + case ARM_BOOTS: // maybe more interesting boot colours? + case ARM_GLOVES: + case ARM_LEATHER_ARMOUR: + item.colour = BROWN; + break; + case ARM_DRAGON_HIDE: + case ARM_DRAGON_ARMOUR: + item.colour = mons_colour( MONS_DRAGON ); + break; + case ARM_TROLL_HIDE: + case ARM_TROLL_LEATHER_ARMOUR: + item.colour = mons_colour( MONS_TROLL ); + break; + case ARM_CRYSTAL_PLATE_MAIL: + item.colour = LIGHTGREY; + break; + case ARM_ICE_DRAGON_HIDE: + case ARM_ICE_DRAGON_ARMOUR: + item.colour = mons_colour( MONS_ICE_DRAGON ); + break; + case ARM_STEAM_DRAGON_HIDE: + case ARM_STEAM_DRAGON_ARMOUR: + item.colour = mons_colour( MONS_STEAM_DRAGON ); + break; + case ARM_MOTTLED_DRAGON_HIDE: + case ARM_MOTTLED_DRAGON_ARMOUR: + item.colour = mons_colour( MONS_MOTTLED_DRAGON ); + break; + case ARM_STORM_DRAGON_HIDE: + case ARM_STORM_DRAGON_ARMOUR: + item.colour = mons_colour( MONS_STORM_DRAGON ); + break; + case ARM_GOLD_DRAGON_HIDE: + case ARM_GOLD_DRAGON_ARMOUR: + item.colour = mons_colour( MONS_GOLDEN_DRAGON ); + break; + case ARM_ANIMAL_SKIN: + item.colour = BROWN; + break; + case ARM_SWAMP_DRAGON_HIDE: + case ARM_SWAMP_DRAGON_ARMOUR: + item.colour = mons_colour( MONS_SWAMP_DRAGON ); + break; + default: + item.colour = LIGHTCYAN; + if (cmp_equip_race( item, ISFLAG_DWARVEN )) + item.colour = CYAN; + break; + } + + // I don't think this is ever done -- see start of case {dlb}: + if (is_random_artefact( item ) && one_chance_in(5)) + item.colour = random_colour(); + break; + + case OBJ_WANDS: + item.special = you.item_description[IDESC_WANDS][item.sub_type]; + + switch (item.special % 12) + { + case 0: //"iron wand" + item.colour = CYAN; + break; + case 1: //"brass wand" + case 5: //"gold wand" + item.colour = YELLOW; + break; + case 2: //"bone wand" + case 8: //"ivory wand" + case 9: //"glass wand" + case 10: //"lead wand" + default: + item.colour = LIGHTGREY; + break; + case 3: //"wooden wand" + case 4: //"copper wand" + case 7: //"bronze wand" + item.colour = BROWN; + break; + case 6: //"silver wand" + item.colour = WHITE; + break; + case 11: //"plastic wand" + item.colour = random_colour(); + break; + } + + if (item.special / 12 == 9) + item.colour = DARKGREY; + + // rare wands (eg disintegration - these will be very rare): + // maybe only 1 thing, like: crystal, shining, etc. + break; + + case OBJ_POTIONS: + item.special = you.item_description[IDESC_POTIONS][item.sub_type]; + + switch (item.special % 14) + { + case 0: //"clear potion" + default: + item.colour = LIGHTGREY; + break; + case 1: //"blue potion" + case 7: //"inky potion" + item.colour = BLUE; + break; + case 2: //"black potion" + item.colour = DARKGREY; + break; + case 3: //"silvery potion" + case 13: //"white potion" + item.colour = WHITE; + break; + case 4: //"cyan potion" + item.colour = CYAN; + break; + case 5: //"purple potion" + item.colour = MAGENTA; + break; + case 6: //"orange potion" + item.colour = LIGHTRED; + break; + case 8: //"red potion" + item.colour = RED; + break; + case 9: //"yellow potion" + item.colour = YELLOW; + break; + case 10: //"green potion" + item.colour = GREEN; + break; + case 11: //"brown potion" + item.colour = BROWN; + break; + case 12: //"pink potion" + item.colour = LIGHTMAGENTA; + break; + } + break; + + case OBJ_FOOD: + switch (item.sub_type) + { + case FOOD_BEEF_JERKY: + case FOOD_BREAD_RATION: + case FOOD_LYCHEE: + case FOOD_MEAT_RATION: + case FOOD_RAMBUTAN: + case FOOD_SAUSAGE: + case FOOD_SULTANA: + item.colour = BROWN; + break; + case FOOD_BANANA: + case FOOD_CHEESE: + case FOOD_HONEYCOMB: + case FOOD_LEMON: + case FOOD_PIZZA: + case FOOD_ROYAL_JELLY: + item.colour = YELLOW; + break; + case FOOD_PEAR: + item.colour = LIGHTGREEN; + break; + case FOOD_CHOKO: + case FOOD_SNOZZCUMBER: + item.colour = GREEN; + break; + case FOOD_APRICOT: + case FOOD_ORANGE: + item.colour = LIGHTRED; + break; + case FOOD_STRAWBERRY: + item.colour = RED; + break; + case FOOD_APPLE: + item.colour = (coinflip() ? RED : GREEN); + break; + case FOOD_GRAPE: + item.colour = (coinflip() ? MAGENTA : GREEN); + break; + case FOOD_CHUNK: + // set the appropriate colour of the meat: + temp_value = mons_colour( item.plus ); + item.colour = (temp_value == BLACK) ? LIGHTRED : temp_value; + break; + default: + item.colour = BROWN; + } + break; + + case OBJ_JEWELLERY: + /* unrandarts have already been coloured */ + if (is_unrandom_artefact( item )) + break; + else if (is_random_artefact( item )) + { + item.colour = random_colour(); + break; + } + + item.colour = YELLOW; + item.special = you.item_description[IDESC_RINGS][item.sub_type]; + + switchnum = item.special % 13; + + switch (switchnum) + { + case 0: + case 5: + item.colour = BROWN; + break; + case 1: + case 8: + case 11: + item.colour = LIGHTGREY; + break; + case 2: + case 6: + item.colour = YELLOW; + break; + case 3: + case 4: + item.colour = CYAN; + break; + case 7: + item.colour = BROWN; + break; + case 9: + case 10: + item.colour = WHITE; + break; + case 12: + item.colour = GREEN; + break; + case 13: + item.colour = LIGHTCYAN; + break; + } + + if (item.sub_type >= AMU_RAGE) + { + switch (switchnum) + { + case 0: //"zirconium amulet" + case 9: //"ivory amulet" + case 11: //"platinum amulet" + item.colour = WHITE; + break; + case 1: //"sapphire amulet" + item.colour = LIGHTBLUE; + break; + case 2: //"golden amulet" + case 6: //"brass amulet" + item.colour = YELLOW; + break; + case 3: //"emerald amulet" + item.colour = GREEN; + break; + case 4: //"garnet amulet" + case 8: //"ruby amulet" + item.colour = RED; + break; + case 5: //"bronze amulet" + case 7: //"copper amulet" + item.colour = BROWN; + break; + case 10: //"bone amulet" + item.colour = LIGHTGREY; + break; + case 12: //"jade amulet" + item.colour = GREEN; + break; + case 13: //"plastic amulet" + item.colour = random_colour(); + } + } + + // blackened - same for both rings and amulets + if (item.special / 13 == 5) + item.colour = DARKGREY; + break; + + case OBJ_SCROLLS: + item.colour = LIGHTGREY; + item.special = you.item_description[IDESC_SCROLLS][item.sub_type]; + item.plus = you.item_description[IDESC_SCROLLS_II][item.sub_type]; + break; + + case OBJ_BOOKS: + switch (item.special % 10) + { + case 0: + case 1: + default: + item.colour = random_colour(); + break; + case 2: + item.colour = (one_chance_in(3) ? BROWN : DARKGREY); + break; + case 3: + item.colour = CYAN; + break; + case 4: + item.colour = LIGHTGREY; + break; + } + break; + + case OBJ_STAVES: + item.colour = BROWN; + break; + + case OBJ_ORBS: + item.colour = LIGHTMAGENTA; + break; + + case OBJ_MISCELLANY: + switch (item.sub_type) + { + case MISC_BOTTLED_EFREET: + case MISC_STONE_OF_EARTH_ELEMENTALS: + item.colour = BROWN; + break; + + case MISC_AIR_ELEMENTAL_FAN: + case MISC_CRYSTAL_BALL_OF_ENERGY: + case MISC_CRYSTAL_BALL_OF_FIXATION: + case MISC_CRYSTAL_BALL_OF_SEEING: + case MISC_DISC_OF_STORMS: + case MISC_HORN_OF_GERYON: + case MISC_LANTERN_OF_SHADOWS: + item.colour = LIGHTGREY; + break; + + case MISC_LAMP_OF_FIRE: + item.colour = YELLOW; + break; + + case MISC_BOX_OF_BEASTS: + item.colour = DARKGREY; + break; + + case MISC_RUNE_OF_ZOT: + switch (item.plus) + { + case RUNE_DIS: // iron + item.colour = CYAN; + break; + + case RUNE_COCYTUS: // icy + item.colour = LIGHTBLUE; + break; + + case RUNE_TARTARUS: // bone + item.colour = WHITE; + break; + + case RUNE_SLIME_PITS: // slimy + item.colour = GREEN; + break; + + case RUNE_SNAKE_PIT: // serpentine + case RUNE_ELVEN_HALLS: // elven + item.colour = LIGHTGREEN; + break; + + case RUNE_VAULTS: // silver + item.colour = LIGHTGREY; + break; + + case RUNE_TOMB: // golden + item.colour = YELLOW; + break; + + case RUNE_SWAMP: // decaying + item.colour = BROWN; + break; + + // These two are hardly unique, but since colour isn't used for + // stacking, so we don't have to worry to much about this. -- bwr + case RUNE_DEMONIC: // random pandemonium demonlords + case RUNE_ABYSSAL: // random in abyss + item.colour = random_colour(); + break; + + case RUNE_MNOLEG: // glowing + item.colour = coinflip() ? MAGENTA : LIGHTMAGENTA; + break; + + case RUNE_LOM_LOBON: // magical + item.colour = BLUE; + break; + + case RUNE_CEREBOV: // fiery + item.colour = coinflip() ? RED : LIGHTRED; + break; + + case RUNE_GEHENNA: // obsidian + case RUNE_GLOORX_VLOQ: // dark + default: + item.colour = DARKGREY; + break; + } + break; + + case MISC_EMPTY_EBONY_CASKET: + item.colour = DARKGREY; + break; + + case MISC_DECK_OF_SUMMONINGS: + case MISC_DECK_OF_WONDERS: + case MISC_DECK_OF_TRICKS: + case MISC_DECK_OF_POWER: + default: + item.colour = random_colour(); + break; + } + break; + + case OBJ_CORPSES: + // set the appropriate colour of the body: + temp_value = mons_colour( item.plus ); + item.colour = (temp_value == BLACK) ? LIGHTRED : temp_value; + break; + + case OBJ_GOLD: + item.colour = YELLOW; + break; + } +} // end item_colour() + +// Checks how rare a weapon is. Many of these have special routines for +// placement, especially those with a rarity of zero. Chance is out of 10. +static char rare_weapon(unsigned char w_type) +{ + + // zero value weapons must be placed specially -- see items() {dlb} + if (is_demonic(w_type)) + return 0; + + switch (w_type) + { + case WPN_CLUB: + case WPN_DAGGER: + return 10; + case WPN_HAND_AXE: + case WPN_FALCHION: + case WPN_MACE: + case WPN_QUARTERSTAFF: + return 9; + case WPN_BOW: + case WPN_FLAIL: + case WPN_HAMMER: + case WPN_SABRE: + case WPN_SHORT_SWORD: + case WPN_SLING: + case WPN_SPEAR: + return 8; + case WPN_LONG_SWORD: + case WPN_MORNINGSTAR: + case WPN_WAR_AXE: + return 7; + case WPN_BATTLEAXE: + case WPN_CROSSBOW: + case WPN_GREAT_SWORD: + case WPN_SCIMITAR: + case WPN_TRIDENT: + return 6; + case WPN_GLAIVE: + case WPN_HALBERD: + case WPN_BLOWGUN: + return 5; + case WPN_BROAD_AXE: + case WPN_HAND_CROSSBOW: + case WPN_SPIKED_FLAIL: + case WPN_WHIP: + return 4; + case WPN_GREAT_MACE: + return 3; + case WPN_ANCUS: + case WPN_GREAT_FLAIL: + case WPN_SCYTHE: + return 2; + case WPN_GIANT_CLUB: + case WPN_GIANT_SPIKED_CLUB: + return 1; + // zero value weapons must be placed specially -- see items() {dlb} + case WPN_DOUBLE_SWORD: + case WPN_EVENINGSTAR: + case WPN_EXECUTIONERS_AXE: + case WPN_KATANA: + case WPN_KNIFE: + case WPN_QUICK_BLADE: + case WPN_TRIPLE_SWORD: + return 0; + + default: + // should not happen now that calls are bounded by NUM_WEAPONS {dlb} + return -1; + } +} // end rare_weapon() + +//jmf: generate altar based on where you are, or possibly randomly +static int pick_an_altar(void) +{ + int altar_type = 0; + int temp_rand; // probability determination {dlb} + + if (player_in_branch( BRANCH_SLIME_PITS ) + || player_in_branch( BRANCH_ECUMENICAL_TEMPLE ) + || you.level_type == LEVEL_LABYRINTH) + { + // no extra altars in temple, none at all in slime pits or labyrinth + altar_type = DNGN_FLOOR; + } + else if (you.level_type == LEVEL_DUNGEON && !one_chance_in(5)) + { + switch (you.where_are_you) + { + case BRANCH_CRYPT: + altar_type = (coinflip() ? DNGN_ALTAR_KIKUBAAQUDGHA + : DNGN_ALTAR_YREDELEMNUL); + break; + + case BRANCH_ORCISH_MINES: // violent gods + temp_rand = random2(5); + + altar_type = ((temp_rand == 0) ? DNGN_ALTAR_VEHUMET : + (temp_rand == 1) ? DNGN_ALTAR_MAKHLEB : + (temp_rand == 2) ? DNGN_ALTAR_OKAWARU : + (temp_rand == 3) ? DNGN_ALTAR_TROG + : DNGN_ALTAR_XOM); + break; + + case BRANCH_VAULTS: // "lawful" gods + temp_rand = random2(7); + + altar_type = ((temp_rand == 0) ? DNGN_ALTAR_ELYVILON : + (temp_rand == 1) ? DNGN_ALTAR_SIF_MUNA : + (temp_rand == 2) ? DNGN_ALTAR_SHINING_ONE : + (temp_rand == 3 || temp_rand == 4) ? DNGN_ALTAR_OKAWARU + : DNGN_ALTAR_ZIN); + break; + + case BRANCH_HALL_OF_BLADES: + altar_type = DNGN_ALTAR_OKAWARU; + break; + + case BRANCH_ELVEN_HALLS: // "magic" gods + temp_rand = random2(4); + + altar_type = ((temp_rand == 0) ? DNGN_ALTAR_VEHUMET : + (temp_rand == 1) ? DNGN_ALTAR_SIF_MUNA : + (temp_rand == 2) ? DNGN_ALTAR_XOM + : DNGN_ALTAR_MAKHLEB); + break; + + case BRANCH_TOMB: + altar_type = DNGN_ALTAR_KIKUBAAQUDGHA; + break; + + default: + do + { + altar_type = DNGN_ALTAR_ZIN + random2(NUM_GODS - 1); + } + while (altar_type == DNGN_ALTAR_NEMELEX_XOBEH); + break; + } + } + else + { + // Note: this case includes the pandemonium or the abyss. + temp_rand = random2(9); + + altar_type = ((temp_rand == 0) ? DNGN_ALTAR_ZIN : + (temp_rand == 1) ? DNGN_ALTAR_SHINING_ONE : + (temp_rand == 2) ? DNGN_ALTAR_KIKUBAAQUDGHA : + (temp_rand == 3) ? DNGN_ALTAR_XOM : + (temp_rand == 4) ? DNGN_ALTAR_OKAWARU : + (temp_rand == 5) ? DNGN_ALTAR_MAKHLEB : + (temp_rand == 6) ? DNGN_ALTAR_SIF_MUNA : + (temp_rand == 7) ? DNGN_ALTAR_TROG + : DNGN_ALTAR_ELYVILON); + } + + return (altar_type); +} // end pick_an_altar() + +static void place_altar(void) +{ + int px, py; + int i, j; + int k = 0, l = 0; + int altar_type = pick_an_altar(); + + while(true) + { + rand_px: + + px = 15 + random2(55); + py = 15 + random2(45); + k++; + + if (k == 5000) + return; + + l = 0; + + for (i = px - 2; i < px + 3; i++) + { + for (j = py - 2; j < py + 3; j++) + { + if (grd[i][j] == DNGN_FLOOR) + l++; + + if ((grd[i][j] != DNGN_ROCK_WALL + && grd[i][j] != DNGN_CLOSED_DOOR + && grd[i][j] != DNGN_SECRET_DOOR + && grd[i][j] != DNGN_FLOOR) + || mgrd[i][j] != NON_MONSTER) + { + goto rand_px; + } + } + } + + if (l == 0) + goto rand_px; + + for (i = px - 2; i < px + 3; i++) + { + for (j = py - 2; j < py + 3; j++) + { + grd[i][j] = DNGN_FLOOR; + } + } + + grd[px][py] = altar_type; + + return; + } +} // end place_altar() + +static void place_shops(int level_number) +{ + int temp_rand = 0; // probability determination {dlb} + int timeout = 0; + + unsigned char no_shops = 0; + unsigned char shop_place_x = 0; + unsigned char shop_place_y = 0; + + temp_rand = random2(125); + +#if DEBUG_SHOPS + no_shops = MAX_SHOPS; +#else + no_shops = ((temp_rand > 28) ? 0 : // 76.8% + (temp_rand > 4) ? 1 // 19.2% + : 1 + random2( MAX_SHOPS )); // 4.0% + + if (no_shops == 0 || level_number < 3) + return; +#endif + + for (int i = 0; i < no_shops; i++) + { + timeout = 0; + + do + { + shop_place_x = random2(GXM - 20) + 10; + shop_place_y = random2(GYM - 20) + 10; + + timeout++; + + if (timeout > 20000) + return; + } + while (grd[shop_place_x][shop_place_y] != DNGN_FLOOR); + + place_spec_shop(level_number, shop_place_x, shop_place_y, SHOP_RANDOM); + } +} // end place_shops() + +static void place_spec_shop( int level_number, + unsigned char shop_x, unsigned char shop_y, + unsigned char force_s_type ) +{ + int orb = 0; + int i = 0; + int j = 0; // loop variable + int item_level; + + for (i = 0; i < MAX_SHOPS; i++) + { + if (env.shop[i].type == SHOP_UNASSIGNED) + break; + } + + if (i == MAX_SHOPS) + return; + + for (j = 0; j < 3; j++) + { + env.shop[i].keeper_name[j] = 1 + random2(200); + } + + env.shop[i].level = level_number * 2; + + env.shop[i].type = (force_s_type != SHOP_RANDOM) ? force_s_type + : random2(NUM_SHOPS); + + if (env.shop[i].type == SHOP_FOOD) + { + env.shop[i].greed = 10 + random2(5); + } + else if (env.shop[i].type != SHOP_WEAPON_ANTIQUE + && env.shop[i].type != SHOP_ARMOUR_ANTIQUE + && env.shop[i].type != SHOP_GENERAL_ANTIQUE) + { + env.shop[i].greed = 10 + random2(5) + random2(level_number / 2); + } + else + { + env.shop[i].greed = 15 + random2avg(19, 2) + random2(level_number); + } + + int plojy = 5 + random2avg(12, 3); + + for (j = 0; j < plojy; j++) + { + if (env.shop[i].type != SHOP_WEAPON_ANTIQUE + && env.shop[i].type != SHOP_ARMOUR_ANTIQUE + && env.shop[i].type != SHOP_GENERAL_ANTIQUE) + { + item_level = level_number + random2((level_number + 1) * 2); + } + else + { + item_level = level_number + random2((level_number + 1) * 3); + } + + if (one_chance_in(4)) + item_level = MAKE_GOOD_ITEM; + + // don't generate gold in shops! This used to be possible with + // General Stores (see item_in_shop() below) (GDL) + while(true) + { + orb = items( 1, item_in_shop(env.shop[i].type), OBJ_RANDOM, true, + item_level, 250 ); + + if (orb != NON_ITEM + && mitm[orb].base_type != OBJ_GOLD + && (env.shop[i].type != SHOP_GENERAL_ANTIQUE + || (mitm[orb].base_type != OBJ_MISSILES + && mitm[orb].base_type != OBJ_FOOD))) + { + break; + } + + // reset object and try again + if (orb != NON_ITEM) + { + mitm[orb].base_type = OBJ_UNASSIGNED; + mitm[orb].quantity = 0; + } + } + + if (orb == NON_ITEM) + break; + + // set object 'position' (gah!) & ID status + mitm[orb].x = 0; + mitm[orb].y = 5 + i; + + if (env.shop[i].type != SHOP_WEAPON_ANTIQUE + && env.shop[i].type != SHOP_ARMOUR_ANTIQUE + && env.shop[i].type != SHOP_GENERAL_ANTIQUE) + { + set_ident_flags( mitm[orb], ISFLAG_IDENT_MASK ); + } + } + + env.shop[i].x = shop_x; + env.shop[i].y = shop_y; + + grd[shop_x][shop_y] = DNGN_ENTER_SHOP; +} // end place_spec_shop() + +static unsigned char item_in_shop(unsigned char shop_type) +{ + switch (shop_type) + { + case SHOP_WEAPON: + if (one_chance_in(5)) + return (OBJ_MISSILES); + // *** deliberate fall through here {dlb} *** + case SHOP_WEAPON_ANTIQUE: + return (OBJ_WEAPONS); + + case SHOP_ARMOUR: + case SHOP_ARMOUR_ANTIQUE: + return (OBJ_ARMOUR); + + case SHOP_GENERAL: + case SHOP_GENERAL_ANTIQUE: + return (OBJ_RANDOM); + + case SHOP_JEWELLERY: + return (OBJ_JEWELLERY); + + case SHOP_WAND: + return (OBJ_WANDS); + + case SHOP_BOOK: + return (OBJ_BOOKS); + + case SHOP_FOOD: + return (OBJ_FOOD); + + case SHOP_DISTILLERY: + return (OBJ_POTIONS); + + case SHOP_SCROLL: + return (OBJ_SCROLLS); + } + + return (OBJ_RANDOM); +} // end item_in_shop() + +static void spotty_level(bool seeded, int iterations, bool boxy) +{ + // assumes starting with a level full of rock walls (1) + int i, j, k, l; + + if (!seeded) + { + for (i = DNGN_STONE_STAIRS_DOWN_I; i < DNGN_ROCK_STAIRS_UP; i++) + { + if (i == DNGN_ROCK_STAIRS_DOWN + || (i == DNGN_STONE_STAIRS_UP_I + && !player_in_branch( BRANCH_SLIME_PITS ))) + { + continue; + } + + do + { + j = 10 + random2(GXM - 20); + k = 10 + random2(GYM - 20); + } + while (grd[j][k] != DNGN_ROCK_WALL + && grd[j + 1][k] != DNGN_ROCK_WALL); + + grd[j][k] = i; + + // creating elevators + if (i == DNGN_STONE_STAIRS_DOWN_I + && !player_in_branch( BRANCH_SLIME_PITS )) + { + grd[j + 1][k] = DNGN_STONE_STAIRS_UP_I; + } + + if (grd[j][k - 1] == DNGN_ROCK_WALL) + grd[j][k - 1] = DNGN_FLOOR; + if (grd[j][k + 1] == DNGN_ROCK_WALL) + grd[j][k + 1] = DNGN_FLOOR; + if (grd[j - 1][k] == DNGN_ROCK_WALL) + grd[j - 1][k] = DNGN_FLOOR; + if (grd[j + 1][k] == DNGN_ROCK_WALL) + grd[j + 1][k] = DNGN_FLOOR; + } + } // end if !seeded + + l = iterations; + + // boxy levels have more clearing, so they get fewer iterations: + if (l == 0) + l = 200 + random2( (boxy ? 750 : 1500) ); + + for (i = 0; i < l; i++) + { + do + { + j = random2(GXM - 20) + 10; + k = random2(GYM - 20) + 10; + } + while (grd[j][k] == DNGN_ROCK_WALL + && grd[j - 1][k] == DNGN_ROCK_WALL + && grd[j + 1][k] == DNGN_ROCK_WALL + && grd[j][k - 1] == DNGN_ROCK_WALL + && grd[j][k + 1] == DNGN_ROCK_WALL + && grd[j - 2][k] == DNGN_ROCK_WALL + && grd[j + 2][k] == DNGN_ROCK_WALL + && grd[j][k - 2] == DNGN_ROCK_WALL + && grd[j][k + 2] == DNGN_ROCK_WALL); + + if (grd[j][k] == DNGN_ROCK_WALL) + grd[j][k] = DNGN_FLOOR; + if (grd[j][k - 1] == DNGN_ROCK_WALL) + grd[j][k - 1] = DNGN_FLOOR; + if (grd[j][k + 1] == DNGN_ROCK_WALL) + grd[j][k + 1] = DNGN_FLOOR; + if (grd[j - 1][k] == DNGN_ROCK_WALL) + grd[j - 1][k] = DNGN_FLOOR; + if (grd[j + 1][k] == DNGN_ROCK_WALL) + grd[j + 1][k] = DNGN_FLOOR; + + if (boxy) + { + if (grd[j - 1][k - 1] == DNGN_ROCK_WALL) + grd[j - 1][k - 1] = DNGN_FLOOR; + if (grd[j + 1][k + 1] == DNGN_ROCK_WALL) + grd[j + 1][k + 1] = DNGN_FLOOR; + if (grd[j - 1][k + 1] == DNGN_ROCK_WALL) + grd[j - 1][k + 1] = DNGN_FLOOR; + if (grd[j + 1][k - 1] == DNGN_ROCK_WALL) + grd[j + 1][k - 1] = DNGN_FLOOR; + } + } +} // end spotty_level() + +static void bigger_room(void) +{ + unsigned char i, j; + + for (i = 10; i < (GXM - 10); i++) + { + for (j = 10; j < (GYM - 10); j++) + { + if (grd[i][j] == DNGN_ROCK_WALL) + grd[i][j] = DNGN_FLOOR; + } + } + + many_pools(DNGN_DEEP_WATER); + + if (one_chance_in(3)) + { + if (coinflip()) + build_river( DNGN_DEEP_WATER ); + else + build_lake( DNGN_DEEP_WATER ); + } + + int pair_count = coinflip() ? 4 : 3; + + for (j = 0; j < pair_count; j++) + { + for (i = 0; i < 2; i++) + { + place_specific_stair( j + ((i==0) ? DNGN_STONE_STAIRS_DOWN_I + : DNGN_STONE_STAIRS_UP_I) ); + } + } +} // end bigger_room() + +// various plan_xxx functions +static void plan_main(int level_number, char force_plan) +{ + // possible values for do_stairs: + // 0 - stairs already done + // 1 - stairs already done, do spotty + // 2 - no stairs + // 3 - no stairs, do spotty + char do_stairs = 0; + unsigned char special_grid = (one_chance_in(3) ? DNGN_METAL_WALL + : DNGN_STONE_WALL); + int i,j; + + if (!force_plan) + force_plan = 1 + random2(12); + + do_stairs = ((force_plan == 1) ? plan_1() : + (force_plan == 2) ? plan_2() : + (force_plan == 3) ? plan_3() : + (force_plan == 4) ? plan_4(0, 0, 0, 0, 99) : + (force_plan == 5) ? (one_chance_in(9) ? plan_5() + : plan_3()) : + (force_plan == 6) ? plan_6(level_number) + : plan_3()); + + if (do_stairs == 3 || do_stairs == 1) + spotty_level(true, 0, coinflip()); + + if (do_stairs == 2 || do_stairs == 3) + { + int pair_count = coinflip()?4:3; + + for (j = 0; j < pair_count; j++) + { + for (i = 0; i < 2; i++) + { + place_specific_stair( j + ((i==0) ? DNGN_STONE_STAIRS_DOWN_I + : DNGN_STONE_STAIRS_UP_I) ); + } + } + } + + if (one_chance_in(20)) + replace_area(0,0,GXM-1,GYM-1,DNGN_ROCK_WALL,special_grid); +} // end plan_main() + +static char plan_1(void) +{ + int temp_rand = 0; // probability determination {dlb} + + unsigned char width = (10 - random2(7)); // value range of [4,10] {dlb} + + replace_area(10, 10, (GXM - 10), (10 + width), DNGN_ROCK_WALL, DNGN_FLOOR); + replace_area(10, (60 - width), (GXM - 10), (GYM - 10), + DNGN_ROCK_WALL, DNGN_FLOOR); + replace_area(10, 10, (10 + width), (GYM - 10), DNGN_ROCK_WALL, DNGN_FLOOR); + replace_area((60 - width), 10, (GXM - 10), (GYM - 10), + DNGN_ROCK_WALL, DNGN_FLOOR); + + // possible early returns {dlb}: + temp_rand = random2(4); + + if (temp_rand > 2) // 25% chance {dlb} + return 3; + else if (temp_rand > 1) // 25% chance {dlb} + return 2; + else // 50% chance {dlb} + { + unsigned char width2 = (coinflip()? (1 + random2(5)) : 5); + + replace_area(10, (35 - width2), (GXM - 10), (35 + width2), + DNGN_ROCK_WALL, DNGN_FLOOR); + replace_area((40 - width2), 10, (40 + width2), (GYM - 10), + DNGN_ROCK_WALL, DNGN_FLOOR); + } + + // possible early returns {dlb}: + temp_rand = random2(4); + + if (temp_rand > 2) // 25% chance {dlb} + return 3; + else if (temp_rand > 1) // 25% chance {dlb} + return 2; + else // 50% chance {dlb} + { + temp_rand = random2(15); + + if (temp_rand > 7) // 7 in 15 odds {dlb} + { + spec_room sr = { false, false, 0,0,0,0 }; + sr.x1 = 25; + sr.y1 = 25; + sr.x2 = (GXM - 25); + sr.y2 = (GYM - 25); + + int oblique_max = 0; + if (coinflip()) + oblique_max = 5 + random2(20); + + temp_rand = random2(7); + + unsigned char floor_type = ((temp_rand > 1) ? DNGN_FLOOR : // 5/7 + (temp_rand > 0) ? DNGN_DEEP_WATER// 1/7 + : DNGN_LAVA); // 1/7 + octa_room(sr, oblique_max, floor_type); + } + } + + // final return {dlb}: + return (one_chance_in(5) ? 3 : 2); +} // end plan_1() + +// just a cross: +static char plan_2(void) +{ + char width2 = (5 - random2(5)); // value range of [1,5] {dlb} + + replace_area(10, (35 - width2), (GXM - 10), (35 + width2), + DNGN_ROCK_WALL, DNGN_FLOOR); + replace_area((40 - width2), 10, (40 + width2), (GYM - 10), + DNGN_ROCK_WALL, DNGN_FLOOR); + + return (one_chance_in(4) ? 2 : 3); +} // end plan_2() + +static char plan_3(void) +{ + + /* Draws a room, then another and links them together, then another and etc + Of course, this can easily end up looking just like a make_trail level. + */ + int i; + char cnx, cny; + char roomsss = 30 + random2(90); + + bool exclusive = (one_chance_in(10) ? false : true); + bool exclusive2 = coinflip(); + + char romx1[30], romy1[30], romx2[30], romy2[30]; + + char which_room = 0; + + for (i = 0; i < roomsss; i++) + { + romx1[which_room] = 10 + random2(50); + romy1[which_room] = 10 + random2(40); + romx2[which_room] = romx1[which_room] + 2 + random2(8); + romy2[which_room] = romy1[which_room] + 2 + random2(8); + + if (exclusive) + { + for (cnx = romx1[which_room] - 1; cnx < romx2[which_room] + 1; + cnx++) + { + for (cny = romy1[which_room] - 1; cny < romy2[which_room] + 1; + cny++) + { + if (grd[cnx][cny] != DNGN_ROCK_WALL) + goto continuing; + } + } + } + + replace_area(romx1[which_room], romy1[which_room], romx2[which_room], + romy2[which_room], DNGN_ROCK_WALL, DNGN_FLOOR); + + if (which_room > 0 && !exclusive2) + { + const int rx1 = romx1[which_room]; + const int rx2 = romx2[which_room]; + const int prev_rx1 = romx1[which_room - 1]; + const int prev_rx2 = romx2[which_room - 1]; + + const int ry1 = romy1[which_room]; + const int ry2 = romy2[which_room]; + const int prev_ry1 = romy1[which_room - 1]; + const int prev_ry2 = romy2[which_room - 1]; + + join_the_dots( rx1 + random2( rx2 - rx1 ), + ry1 + random2( ry2 - ry1 ), + prev_rx1 + random2( prev_rx2 - prev_rx1 ), + prev_ry1 + random2( prev_ry2 - prev_ry1 ), + 0, 0, 0, 0 ); + } + + which_room++; + + if (which_room >= 29) + break; + + continuing: + continue; + } + + if (exclusive2) + { + for (i = 0; i < which_room; i++) + { + if (i > 0) + { + const int rx1 = romx1[i]; + const int rx2 = romx2[i]; + const int prev_rx1 = romx1[i - 1]; + const int prev_rx2 = romx2[i - 1]; + + const int ry1 = romy1[i]; + const int ry2 = romy2[i]; + const int prev_ry1 = romy1[i - 1]; + const int prev_ry2 = romy2[i - 1]; + + join_the_dots( rx1 + random2( rx2 - rx1 ), + ry1 + random2( ry2 - ry1 ), + prev_rx1 + random2( prev_rx2 - prev_rx1 ), + prev_ry1 + random2( prev_ry2 - prev_ry1 ), + 0, 0, 0, 0 ); + } + } + } + + return 2; +} // end plan_3() + +static char plan_4(char forbid_x1, char forbid_y1, char forbid_x2, + char forbid_y2, unsigned char force_wall) +{ + // a more chaotic version of city level + int temp_rand; // req'd for probability checking + + int number_boxes = 5000; + unsigned char drawing = DNGN_ROCK_WALL; + char b1x, b1y, b2x, b2y; + char cnx, cny; + int i; + + temp_rand = random2(81); + + number_boxes = ((temp_rand > 48) ? 4000 : // odds: 32 in 81 {dlb} + (temp_rand > 24) ? 3000 : // odds: 24 in 81 {dlb} + (temp_rand > 8) ? 5000 : // odds: 16 in 81 {dlb} + (temp_rand > 0) ? 2000 // odds: 8 in 81 {dlb} + : 1000); // odds: 1 in 81 {dlb} + + if (force_wall != 99) + drawing = force_wall; + else + { + temp_rand = random2(18); + + drawing = ((temp_rand > 7) ? DNGN_ROCK_WALL : // odds: 10 in 18 {dlb} + (temp_rand > 2) ? DNGN_STONE_WALL // odds: 5 in 18 {dlb} + : DNGN_METAL_WALL); // odds: 3 in 18 {dlb} + } + + replace_area(10, 10, (GXM - 10), (GYM - 10), DNGN_ROCK_WALL, DNGN_FLOOR); + + // replace_area can also be used to fill in: + for (i = 0; i < number_boxes; i++) + { + + b1x = 11 + random2(45); + b1y = 11 + random2(35); + + b2x = b1x + 3 + random2(7) + random2(5); + b2y = b1y + 3 + random2(7) + random2(5); + + if (forbid_x1 != 0 || forbid_x2 != 0) + { + if (b1x <= forbid_x2 && b1x >= forbid_x1 + && b1y <= forbid_y2 && b1y >= forbid_y1) + { + goto continuing; + } + else if (b2x <= forbid_x2 && b2x >= forbid_x1 + && b2y <= forbid_y2 && b2y >= forbid_y1) + { + goto continuing; + } + } + + for (cnx = b1x - 1; cnx < b2x + 1; cnx++) + { + for (cny = b1y - 1; cny < b2y + 1; cny++) + { + if (grd[cnx][cny] != DNGN_FLOOR) + goto continuing; + } + } + + if (force_wall == 99) + { + // NB: comparison reversal here - combined + temp_rand = random2(1200); + + // probabilities *not meant* to sum to one! {dlb} + if (temp_rand < 417) // odds: 261 in 1200 {dlb} + drawing = DNGN_ROCK_WALL; + else if (temp_rand < 156) // odds: 116 in 1200 {dlb} + drawing = DNGN_STONE_WALL; + else if (temp_rand < 40) // odds: 40 in 1200 {dlb} + drawing = DNGN_METAL_WALL; + } + + temp_rand = random2(210); + + if (temp_rand > 71) // odds: 138 in 210 {dlb} + replace_area(b1x, b1y, b2x, b2y, DNGN_FLOOR, drawing); + else // odds: 72 in 210 {dlb} + box_room(b1x, b2x - 1, b1y, b2y - 1, drawing); + + continuing: + continue; + } + + if (forbid_x1 == 0 && one_chance_in(4)) // a market square + { + spec_room sr = { false, false, 0, 0, 0, 0 }; + sr.x1 = 25; + sr.y1 = 25; + sr.x2 = 55; + sr.y2 = 45; + + int oblique_max = 0; + if (!one_chance_in(4)) + oblique_max = 5 + random2(20); // used elsewhere {dlb} + + unsigned char feature = DNGN_FLOOR; + if (one_chance_in(10)) + feature = coinflip()? DNGN_DEEP_WATER : DNGN_LAVA; + + octa_room(sr, oblique_max, feature); + } + + return 2; +} // end plan_4() + +static char plan_5(void) +{ + unsigned char imax = 5 + random2(20); // value range of [5,24] {dlb} + + for (unsigned char i = 0; i < imax; i++) + { + join_the_dots( random2(GXM - 20) + 10, random2(GYM - 20) + 10, + random2(GXM - 20) + 10, random2(GYM - 20) + 10, + 0, 0, 0, 0 ); + } + + if (!one_chance_in(4)) + spotty_level(true, 100, coinflip()); + + return 2; +} // end plan_5() + +static char plan_6(int level_number) +{ + spec_room sr = { false, false, 0,0,0,0 }; + + // circle of standing stones (well, kind of) + sr.x1 = 10; + sr.x2 = (GXM - 10); + sr.y1 = 10; + sr.y2 = (GYM - 10); + + octa_room(sr, 14, DNGN_FLOOR); + + replace_area(23, 23, 26, 26, DNGN_FLOOR, DNGN_STONE_WALL); + replace_area(23, 47, 26, 50, DNGN_FLOOR, DNGN_STONE_WALL); + replace_area(55, 23, 58, 26, DNGN_FLOOR, DNGN_STONE_WALL); + replace_area(55, 47, 58, 50, DNGN_FLOOR, DNGN_STONE_WALL); + replace_area(39, 20, 43, 23, DNGN_FLOOR, DNGN_STONE_WALL); + replace_area(39, 50, 43, 53, DNGN_FLOOR, DNGN_STONE_WALL); + replace_area(20, 30, 23, 33, DNGN_FLOOR, DNGN_STONE_WALL); + replace_area(20, 40, 23, 43, DNGN_FLOOR, DNGN_STONE_WALL); + replace_area(58, 30, 61, 33, DNGN_FLOOR, DNGN_STONE_WALL); + replace_area(58, 40, 61, 43, DNGN_FLOOR, DNGN_STONE_WALL); + + grd[35][32] = DNGN_STONE_WALL; + grd[46][32] = DNGN_STONE_WALL; + grd[35][40] = DNGN_STONE_WALL; + grd[46][40] = DNGN_STONE_WALL; + + grd[69][34] = DNGN_STONE_STAIRS_DOWN_I; + grd[69][35] = DNGN_STONE_STAIRS_DOWN_II; + grd[69][36] = DNGN_STONE_STAIRS_DOWN_III; + + grd[10][34] = DNGN_STONE_STAIRS_UP_I; + grd[10][35] = DNGN_STONE_STAIRS_UP_II; + grd[10][36] = DNGN_STONE_STAIRS_UP_III; + + // This "back door" is often one of the easier ways to get out of + // pandemonium... the easiest is to use the banish spell. + // + // Note, that although "level_number > 20" will work for most + // trips to pandemonium (through regular portals), it won't work + // for demonspawn who gate themselves there. -- bwr + if (((player_in_branch( BRANCH_MAIN_DUNGEON ) && level_number > 20) + || you.level_type == LEVEL_PANDEMONIUM) + && (coinflip() || you.mutation[ MUT_PANDEMONIUM ])) + { + grd[40][36] = DNGN_ENTER_ABYSS; + grd[41][36] = DNGN_ENTER_ABYSS; + } + + return 0; +} // end plan_6() + +static bool octa_room(spec_room &sr, int oblique_max, unsigned char type_floor) +{ + int x,y; + + // hack - avoid lava in the crypt {gdl} + if ((player_in_branch( BRANCH_CRYPT ) || player_in_branch( BRANCH_TOMB )) + && type_floor == DNGN_LAVA) + { + type_floor = DNGN_SHALLOW_WATER; + } + + int oblique = oblique_max; + + // check octagonal room for special; avoid if exists + for (x = sr.x1; x < sr.x2; x++) + { + for (y = sr.y1 + oblique; y < sr.y2 - oblique; y++) + { + if (grd[x][y] == DNGN_BUILDER_SPECIAL_WALL) + return false; + } + + if (oblique > 0) + oblique--; + + if (x > sr.x2 - oblique_max) + oblique += 2; + } + + oblique = oblique_max; + + + for (x = sr.x1; x < sr.x2; x++) + { + for (y = sr.y1 + oblique; y < sr.y2 - oblique; y++) + { + if (grd[x][y] == DNGN_ROCK_WALL) + grd[x][y] = type_floor; + + if (grd[x][y] == DNGN_FLOOR && type_floor == DNGN_SHALLOW_WATER) + grd[x][y] = DNGN_SHALLOW_WATER; + + if (type_floor >= DNGN_LAST_SOLID_TILE + && grd[x][y] == DNGN_CLOSED_DOOR) + { + grd[x][y] = DNGN_FLOOR; // ick + } + } + + if (oblique > 0) + oblique--; + + if (x > sr.x2 - oblique_max) + oblique += 2; + } + + return true; +} // end octa_room() + +static void labyrinth_level(int level_number) +{ + int temp_rand; // probability determination {dlb} + + int keep_lx = 0, keep_ly = 0; + int keep_lx2 = 0, keep_ly2 = 0; + char start_point_x = 10; + char start_point_y = 10; + char going_x = 1; + char going_y = (coinflip() ? 0 : 1); + bool do_2 = false; + int clear_space = 1; + unsigned char traps_put2 = 0; + + if (coinflip()) + { + start_point_x = (GXM - 10); + going_x = -1; + } + + if (coinflip()) + { + start_point_y = (GYM - 10); + + if (going_y == 1) + going_y = -1; + } + + int lx = start_point_x; + int ly = start_point_y; + + if (going_y) + goto do_y; + + do_x: + traps_put2 = 0; + clear_space = 0; // ( coinflip()? 3 : 2 ); + + do + { + lx += going_x; + + if (grd[lx][ly] == DNGN_ROCK_WALL) + grd[lx][ly] = DNGN_FLOOR; + } + while (lx < (GXM - 8) && lx > 8 + && grd[lx + going_x * (2 + clear_space)][ly] == DNGN_ROCK_WALL); + + going_x = 0; + + if (ly < 32) + going_y = 1; + else if (ly > 37) + going_y = -1; + else + goto finishing; + + do_y: // if (going_y != 0) + if (do_2) + { + lx = keep_lx2; + ly = keep_ly2; + } + + // do_2 = false is the problem + if (coinflip()) + { + clear_space = 0; + do_2 = false; + } + else + { + clear_space = 2; + do_2 = true; + } + + do + { + ly += going_y; + + if (grd[lx][ly] == DNGN_ROCK_WALL) + grd[lx][ly] = DNGN_FLOOR; + } + while (ly < (GYM - 8) && ly > 8 + && grd[lx][ly + going_y * (2 + clear_space)] == DNGN_ROCK_WALL); + + keep_lx = lx; + keep_ly = ly; + + if (lx < 37) + going_x = 1; + else if (lx > 42) + going_x = -1; + + if (ly < 33) + ly += 2; + else if (ly > 37) + ly -= 2; + + clear_space = ((!do_2) ? 6 : 2); + + do + { + lx += going_x; + + if (grd[lx][ly] == DNGN_ROCK_WALL) + grd[lx][ly] = DNGN_FLOOR; + } + while (lx < (GXM - 8) && lx > 8 + && grd[lx + going_x * (2 + clear_space)][ly] == DNGN_ROCK_WALL); + + if (do_2) + { + keep_lx2 = lx; + keep_ly2 = ly; + } + + lx = keep_lx; + ly = keep_ly; + + going_y = 0; + + if (lx < 37) + going_x = 1; + else if (lx > 42) + going_x = -1; + else + goto finishing; + + goto do_x; + + finishing: + start_point_x = 10 + random2(GXM - 20); + + int treasure_item = 0; + + unsigned char glopop = OBJ_RANDOM; // used in calling items() {dlb} + + int num_items = 8 + random2avg(9, 2); + for (int i = 0; i < num_items; i++) + { + temp_rand = random2(11); + + glopop = ((temp_rand == 0 || temp_rand == 9) ? OBJ_WEAPONS : + (temp_rand == 1 || temp_rand == 10) ? OBJ_ARMOUR : + (temp_rand == 2) ? OBJ_MISSILES : + (temp_rand == 3) ? OBJ_WANDS : + (temp_rand == 4) ? OBJ_MISCELLANY : + (temp_rand == 5) ? OBJ_SCROLLS : + (temp_rand == 6) ? OBJ_JEWELLERY : + (temp_rand == 7) ? OBJ_BOOKS + /* (temp_rand == 8) */ : OBJ_STAVES); + + treasure_item = items( 1, glopop, OBJ_RANDOM, true, + level_number * 3, 250 ); + + if (treasure_item != NON_ITEM) + { + mitm[treasure_item].x = lx; + mitm[treasure_item].y = ly; + } + } + + mons_place( MONS_MINOTAUR, BEH_SLEEP, MHITNOT, true, lx, ly ); + + grd[lx][ly] = DNGN_ROCK_STAIRS_UP; + + link_items(); + + // turn rock walls into undiggable stone or metal: + temp_rand = random2(50); + + unsigned char wall_xform = ((temp_rand > 10) ? DNGN_STONE_WALL // 78.0% + : DNGN_METAL_WALL); // 22.0% + + replace_area(0,0,GXM-1,GYM-1,DNGN_ROCK_WALL,wall_xform); + +} // end labyrinth_level() + +static bool is_wall(int x, int y) +{ + unsigned char feat = grd[x][y]; + + switch (feat) + { + case DNGN_ROCK_WALL: + case DNGN_STONE_WALL: + case DNGN_METAL_WALL: + case DNGN_GREEN_CRYSTAL_WALL: + case DNGN_WAX_WALL: + return true; + default: + return false; + } +} + + +static int box_room_door_spot(int x, int y) +{ + // if there is a door near us embedded in rock, we have to be a door too. + if ((grd[x-1][y] == DNGN_CLOSED_DOOR && is_wall(x-1,y-1) && is_wall(x-1,y+1)) + || (grd[x+1][y] == DNGN_CLOSED_DOOR && is_wall(x+1,y-1) && is_wall(x+1,y+1)) + || (grd[x][y-1] == DNGN_CLOSED_DOOR && is_wall(x-1,y-1) && is_wall(x+1,y-1)) + || (grd[x][y+1] == DNGN_CLOSED_DOOR && is_wall(x-1,y+1) && is_wall(x+1,y+1))) + { + grd[x][y] = DNGN_CLOSED_DOOR; + return 2; + } + + // to be a good spot for a door, we need non-wall on two sides and + // wall on two sides. + bool nor = is_wall(x, y-1); + bool sou = is_wall(x, y+1); + bool eas = is_wall(x-1, y); + bool wes = is_wall(x+1, y); + + if (nor == sou && eas == wes && nor != eas) + return 1; + + return 0; +} + +static int box_room_doors( int bx1, int bx2, int by1, int by2, int new_doors) +{ + int good_doors[200]; // 1 == good spot, 2 == door placed! + int spot; + int i,j; + int doors_placed = new_doors; + + // sanity + if ( 2 * ( (bx2 - bx1) + (by2-by1) ) > 200) + return 0; + + // go through, building list of good door spots, and replacing wall + // with door if we're about to block off another door. + int spot_count = 0; + + // top & bottom + for(i=bx1+1; i 0 && spot_count > 0) + { + spot = random2(spot_count); + if (good_doors[spot] != 1) + continue; + + j = 0; + for(i=bx1+1; i 45) ? 2 : + ((temp_rand > 22) ? 1 : 3); + + // small rooms don't have as many doors + if ((bx2-bx1)*(by2-by1) < 36) + new_doors--; + + new_doors -= doors_placed; + if (new_doors > 0) + box_room_doors(bx1, bx2, by1, by2, new_doors); +} + +static void city_level(int level_number) +{ + int temp_rand; // probability determination {dlb} + int wall_type; // remember, can have many wall types in one level + int wall_type_room; // simplifies logic of innermost loop {dlb} + + int xs = 0, ys = 0; + int x1 = 0, x2 = 0; + int y1 = 0, y2 = 0; + int i,j; + + temp_rand = random2(8); + + wall_type = ((temp_rand > 4) ? DNGN_ROCK_WALL : // 37.5% {dlb} + (temp_rand > 1) ? DNGN_STONE_WALL // 37.5% {dlb} + : DNGN_METAL_WALL); // 25.0% {dlb} + + if (one_chance_in(100)) + wall_type = DNGN_GREEN_CRYSTAL_WALL; + + make_box( 7, 7, GXM-7, GYM-7, DNGN_FLOOR ); + + for (i = 0; i < 5; i++) + { + for (j = 0; j < 4; j++) + { + xs = 8 + (i * 13); + ys = 8 + (j * 14); + x1 = xs + random2avg(5, 2); + y1 = ys + random2avg(5, 2); + x2 = xs + 11 - random2avg(5, 2); + y2 = ys + 11 - random2avg(5, 2); + + temp_rand = random2(280); + + if (temp_rand > 39) // 85.7% draw room(s) {dlb} + { + wall_type_room = ((temp_rand > 63) ? wall_type : // 77.1% + (temp_rand > 54) ? DNGN_STONE_WALL : // 3.2% + (temp_rand > 45) ? DNGN_ROCK_WALL // 3.2% + : DNGN_METAL_WALL); // 2.1% + + if (one_chance_in(250)) + wall_type_room = DNGN_GREEN_CRYSTAL_WALL; + + box_room(x1, x2, y1, y2, wall_type_room); + + // inner room - neat. + if (x2 - x1 > 5 && y2 - y1 > 5 && one_chance_in(8)) + { + box_room(x1 + 2, x2 - 2, y1 + 2, y2 - 2, wall_type); + + // treasure area.. neat. + if (one_chance_in(3)) + treasure_area(level_number, x1 + 3, x2 - 3, y1 + 3, y2 - 3); + } + } + } + } + + int stair_count = coinflip() ? 2 : 1; + + for (j = 0; j < stair_count; j++) + { + for (i = 0; i < 2; i++) + { + place_specific_stair( j + ((i==0) ? DNGN_STONE_STAIRS_DOWN_I + : DNGN_STONE_STAIRS_UP_I) ); + } + } + +} // end city_level() + +static bool treasure_area(int level_number, unsigned char ta1_x, + unsigned char ta2_x, unsigned char ta1_y, + unsigned char ta2_y) +{ + int x_count = 0; + int y_count = 0; + int item_made = 0; + + ta2_x++; + ta2_y++; + + if (ta2_x <= ta1_x || ta2_y <= ta1_y) + return false; + + if ((ta2_x - ta1_x) * (ta2_y - ta1_y) >= 40) + return false; + + for (x_count = ta1_x; x_count < ta2_x; x_count++) + { + for (y_count = ta1_y; y_count < ta2_y; y_count++) + { + if (grd[x_count][y_count] != DNGN_FLOOR || coinflip()) + continue; + + item_made = items( 1, OBJ_RANDOM, OBJ_RANDOM, true, + random2( level_number * 2 ), 250 ); + + if (item_made != NON_ITEM) + { + mitm[item_made].x = x_count; + mitm[item_made].y = y_count; + } + } + } + + return true; +} // end treasure_area() + +static void diamond_rooms(int level_number) +{ + char numb_diam = 1 + random2(10); + char type_floor = DNGN_DEEP_WATER; + int runthru = 0; + int i, oblique_max; + + // I guess no diamond rooms in either of these places {dlb}: + if (player_in_branch( BRANCH_DIS ) || player_in_branch( BRANCH_TARTARUS )) + return; + + if (level_number > 5 + random2(5) && coinflip()) + type_floor = DNGN_SHALLOW_WATER; + + if (level_number > 10 + random2(5) && coinflip()) + type_floor = DNGN_DEEP_WATER; + + if (level_number > 17 && coinflip()) + type_floor = DNGN_LAVA; + + if (level_number > 10 && one_chance_in(15)) + type_floor = (coinflip()? DNGN_STONE_WALL : DNGN_ROCK_WALL); + + if (level_number > 12 && one_chance_in(20)) + type_floor = DNGN_METAL_WALL; + + if (player_in_branch( BRANCH_GEHENNA )) + type_floor = DNGN_LAVA; + else if (player_in_branch( BRANCH_COCYTUS )) + type_floor = DNGN_DEEP_WATER; + + for (i = 0; i < numb_diam; i++) + { + spec_room sr = { false, false, 0, 0, 0, 0 }; + + sr.x1 = 8 + random2(43); + sr.y1 = 8 + random2(35); + sr.x2 = sr.x1 + 5 + random2(15); + sr.y2 = sr.y1 + 5 + random2(10); + + oblique_max = (sr.x2 - sr.x1) / 2; //random2(20) + 5; + + if (!octa_room(sr, oblique_max, type_floor)) + { + runthru++; + if (runthru > 9) + { + runthru = 0; + } + else + { + i--; + continue; + } + } + } // end "for(bk...)" +} // end diamond_rooms() + +static void big_room(int level_number) +{ + unsigned char type_floor = DNGN_FLOOR; + unsigned char type_2 = DNGN_FLOOR; + int i, j, k, l; + + spec_room sr = { false, false, 0, 0, 0, 0 }; + int oblique; + + if (one_chance_in(4)) + { + oblique = 5 + random2(20); + + sr.x1 = 8 + random2(30); + sr.y1 = 8 + random2(22); + sr.x2 = sr.x1 + 20 + random2(10); + sr.y2 = sr.y1 + 20 + random2(8); + + // usually floor, except at higher levels + if (!one_chance_in(5) || level_number < 8 + random2(8)) + { + octa_room(sr, oblique, DNGN_FLOOR); + return; + } + + // default is lava. + type_floor = DNGN_LAVA; + + if (level_number > 7) + { + type_floor = ((random2(level_number) < 14) ? DNGN_DEEP_WATER + : DNGN_LAVA); + } + + octa_room(sr, oblique, type_floor); + } + + // what now? + sr.x1 = 8 + random2(30); + sr.y1 = 8 + random2(22); + sr.x2 = sr.x1 + 20 + random2(10); + sr.y2 = sr.y1 + 20 + random2(8); + + // check for previous special + if (find_in_area(sr.x1, sr.y1, sr.x2, sr.y2, DNGN_BUILDER_SPECIAL_WALL)) + return; + + if (level_number > 7 && one_chance_in(4)) + { + type_floor = ((random2(level_number) < 14) ? DNGN_DEEP_WATER + : DNGN_LAVA); + } + + // make the big room. + replace_area(sr.x1, sr.y1, sr.x2, sr.y2, DNGN_ROCK_WALL, type_floor); + replace_area(sr.x1, sr.y1, sr.x2, sr.y2, DNGN_CLOSED_DOOR, type_floor); + + if (type_floor == DNGN_FLOOR) + type_2 = DNGN_ROCK_WALL + random2(4); + + // no lava in the Crypt or Tomb, thanks! + if (player_in_branch( BRANCH_CRYPT ) || player_in_branch( BRANCH_TOMB )) + { + if (type_floor == DNGN_LAVA) + type_floor = DNGN_SHALLOW_WATER; + + if (type_2 == DNGN_LAVA) + type_2 = DNGN_SHALLOW_WATER; + } + + // sometimes make it a chequerboard + if (one_chance_in(4)) + { + chequerboard( sr, type_floor, type_floor, type_2 ); + } + // sometimes make an inside room w/ stone wall. + else if (one_chance_in(6)) + { + i = sr.x1; + j = sr.y1; + k = sr.x2; + l = sr.y2; + + do + { + i += 2 + random2(3); + j += 2 + random2(3); + k -= 2 + random2(3); + l -= 2 + random2(3); + // check for too small + if (i >= k - 3) + break; + if (j >= l - 3) + break; + + box_room(i, k, j, l, DNGN_STONE_WALL); + + } + while (level_number < 1500); // ie forever + } +} // end big_room() + +// helper function for chequerboard rooms +// note that box boundaries are INclusive +static void chequerboard( spec_room &sr, unsigned char target, + unsigned char floor1, unsigned char floor2 ) +{ + int i, j; + + if (sr.x2 < sr.x1 || sr.y2 < sr.y1) + return; + + for (i = sr.x1; i <= sr.x2; i++) + { + for (j = sr.y1; j <= sr.y2; j++) + { + if (grd[i][j] == target) + grd[i][j] = (((i + j) % 2) ? floor2 : floor1); + } + } +} // end chequerboard() + +static void roguey_level(int level_number, spec_room &sr) +{ + int bcount_x, bcount_y; + int cn = 0; + int i; + + FixedVector < unsigned char, 30 > rox1; + FixedVector < unsigned char, 30 > rox2; + FixedVector < unsigned char, 30 > roy1; + FixedVector < unsigned char, 30 > roy2; + + for (bcount_y = 0; bcount_y < 5; bcount_y++) + { + for (bcount_x = 0; bcount_x < 5; bcount_x++) + { + // rooms: + rox1[cn] = bcount_x * 13 + 8 + random2(4); + roy1[cn] = bcount_y * 11 + 8 + random2(4); + + rox2[cn] = rox1[cn] + 3 + random2(8); + roy2[cn] = roy1[cn] + 3 + random2(6); + + // bounds + if (rox2[cn] > GXM-8) + rox2[cn] = GXM-8; + + cn++; + } + } + + cn = 0; + + for (i = 0; i < 25; i++) + { + replace_area( rox1[i], roy1[i], rox2[i], roy2[i], + DNGN_ROCK_WALL, DNGN_FLOOR ); + + // inner room? + if (rox2[i] - rox1[i] > 5 && roy2[i] - roy1[i] > 5) + { + if (random2(100 - level_number) < 3) + { + if (!one_chance_in(4)) + { + box_room( rox1[i] + 2, rox2[i] - 2, roy1[i] + 2, + roy2[i] - 2, (coinflip() ? DNGN_STONE_WALL + : DNGN_ROCK_WALL) ); + } + else + { + box_room( rox1[i] + 2, rox2[i] - 2, roy1[i] + 2, + roy2[i] - 2, DNGN_METAL_WALL ); + } + + if (coinflip()) + { + treasure_area( level_number, rox1[i] + 3, rox2[i] - 3, + roy1[i] + 3, roy2[i] - 3 ); + } + } + } + } // end "for i" + + // Now, join them together: + FixedVector < char, 2 > pos; + FixedVector < char, 2 > jpos; + + char doing = 0; + + char last_room = 0; + int bp; + + for (bp = 0; bp < 2; bp++) + { + for (i = 0; i < 25; i++) + { + if (bp == 0 && (!(i % 5) || i == 0)) + continue; + + if (bp == 1 && i < 5) + continue; + + switch (bp) + { + case 0: + last_room = i - 1; + pos[0] = rox1[i]; // - 1; + pos[1] = roy1[i] + random2(roy2[i] - roy1[i]); + jpos[0] = rox2[last_room]; // + 1; + jpos[1] = roy1[last_room] + + random2(roy2[last_room] - roy1[last_room]); + break; + + case 1: + last_room = i - 5; + pos[1] = roy1[i]; // - 1; + pos[0] = rox1[i] + random2(rox2[i] - rox1[i]); + jpos[1] = roy2[last_room]; // + 1; + jpos[0] = rox1[last_room] + + random2(rox2[last_room] - rox1[last_room]); + break; + } + + while (pos[0] != jpos[0] || pos[1] != jpos[1]) + { + doing = (coinflip()? 1 : 0); + + if (pos[doing] < jpos[doing]) + pos[doing]++; + else if (pos[doing] > jpos[doing]) + pos[doing]--; + + if (grd[pos[0]][pos[1]] == DNGN_ROCK_WALL) + grd[pos[0]][pos[1]] = DNGN_FLOOR; + } + + if (grd[pos[0]][pos[1]] == DNGN_FLOOR) + { + if ((grd[pos[0] + 1][pos[1]] == DNGN_ROCK_WALL + && grd[pos[0] - 1][pos[1]] == DNGN_ROCK_WALL) + || (grd[pos[0]][pos[1] + 1] == DNGN_ROCK_WALL + && grd[pos[0]][pos[1] - 1] == DNGN_ROCK_WALL)) + { + grd[pos[0]][pos[1]] = 103; + } + } + } // end "for bp, for i" + } + + // is one of them a special room? + if (level_number > 8 && one_chance_in(10)) + { + int spec_room_done = random2(25); + + sr.created = true; + sr.hooked_up = true; + sr.x1 = rox1[spec_room_done]; + sr.x2 = rox2[spec_room_done]; + sr.y1 = roy1[spec_room_done]; + sr.y2 = roy2[spec_room_done]; + special_room( level_number, sr ); + + // make the room 'special' so it doesn't get overwritten + // by something else (or put monsters in walls, etc..). + + // top + replace_area(sr.x1-1, sr.y1-1, sr.x2+1,sr.y1-1, DNGN_ROCK_WALL, DNGN_BUILDER_SPECIAL_WALL); + replace_area(sr.x1-1, sr.y1-1, sr.x2+1,sr.y1-1, DNGN_FLOOR, DNGN_BUILDER_SPECIAL_FLOOR); + replace_area(sr.x1-1, sr.y1-1, sr.x2+1,sr.y1-1, DNGN_CLOSED_DOOR, DNGN_BUILDER_SPECIAL_FLOOR); + + // bottom + replace_area(sr.x1-1, sr.y2+1, sr.x2+1,sr.y2+1, DNGN_ROCK_WALL, DNGN_BUILDER_SPECIAL_WALL); + replace_area(sr.x1-1, sr.y2+1, sr.x2+1,sr.y2+1, DNGN_FLOOR, DNGN_BUILDER_SPECIAL_FLOOR); + replace_area(sr.x1-1, sr.y2+1, sr.x2+1,sr.y2+1, DNGN_CLOSED_DOOR, DNGN_BUILDER_SPECIAL_FLOOR); + + // left + replace_area(sr.x1-1, sr.y1-1, sr.x1-1, sr.y2+1, DNGN_ROCK_WALL, DNGN_BUILDER_SPECIAL_WALL); + replace_area(sr.x1-1, sr.y1-1, sr.x1-1, sr.y2+1, DNGN_FLOOR, DNGN_BUILDER_SPECIAL_FLOOR); + replace_area(sr.x1-1, sr.y1-1, sr.x1-1, sr.y2+1, DNGN_CLOSED_DOOR, DNGN_BUILDER_SPECIAL_FLOOR); + + // right + replace_area(sr.x2+1, sr.y1-1, sr.x2+1, sr.y2+1, DNGN_ROCK_WALL, DNGN_BUILDER_SPECIAL_WALL); + replace_area(sr.x2+1, sr.y1-1, sr.x2+1, sr.y2+1, DNGN_FLOOR, DNGN_BUILDER_SPECIAL_FLOOR); + replace_area(sr.x2+1, sr.y1-1, sr.x2+1, sr.y2+1, DNGN_CLOSED_DOOR, DNGN_BUILDER_SPECIAL_FLOOR); + } + + int stair_count = coinflip() ? 2 : 1; + + for (int j = 0; j < stair_count; j++) + { + for (i = 0; i < 2; i++) + { + place_specific_stair(j + ((i==0) ? DNGN_STONE_STAIRS_DOWN_I + : DNGN_STONE_STAIRS_UP_I)); + } + } +} // end roguey_level() + +static void morgue(spec_room &sr) +{ + int temp_rand = 0; // probability determination {dlb} + int x,y; + + for (x = sr.x1; x <= sr.x2; x++) + { + for (y = sr.y1; y <= sr.y2; y++) + { + if (grd[x][y] == DNGN_FLOOR || grd[x][y] == DNGN_BUILDER_SPECIAL_FLOOR) + { + int mon_type; + temp_rand = random2(24); + + mon_type = ((temp_rand > 11) ? MONS_ZOMBIE_SMALL : // 50.0% + (temp_rand > 7) ? MONS_WIGHT : // 16.7% + (temp_rand > 3) ? MONS_NECROPHAGE : // 16.7% + (temp_rand > 0) ? MONS_WRAITH // 12.5% + : MONS_VAMPIRE); // 4.2% + + mons_place( mon_type, BEH_SLEEP, MHITNOT, true, x, y ); + } + } + } +} // end morgue() + +static bool place_specific_trap(unsigned char spec_x, unsigned char spec_y, + unsigned char spec_type) +{ + if (spec_type == TRAP_RANDOM) + spec_type = random2(NUM_TRAPS); + + for (int tcount = 0; tcount < MAX_TRAPS; tcount++) + { + if (env.trap[tcount].type == TRAP_UNASSIGNED) + { + env.trap[tcount].type = spec_type; + env.trap[tcount].x = spec_x; + env.trap[tcount].y = spec_y; + grd[spec_x][spec_y] = DNGN_UNDISCOVERED_TRAP; + return true; + } + + if (tcount >= MAX_TRAPS - 1) + return false; + } + + return false; +} // end place_specific_trap() + +void define_zombie( int mid, int ztype, int cs, int power ) +{ + int mons_sec2 = 0; + int zombie_size = 0; + bool ignore_rarity = false; + int test, cls; + + if (power > 27) + power = 27; + + // set size based on zombie class (cs) + switch(cs) + { + case MONS_ZOMBIE_SMALL: + case MONS_SIMULACRUM_SMALL: + case MONS_SKELETON_SMALL: + zombie_size = 1; + break; + + case MONS_ZOMBIE_LARGE: + case MONS_SIMULACRUM_LARGE: + case MONS_SKELETON_LARGE: + zombie_size = 2; + break; + + case MONS_SPECTRAL_THING: + zombie_size = -1; + break; + + default: + // this should NEVER happen. + perror("\ncreate_zombie() got passed incorrect zombie type!\n"); + end(0); + break; + } + + // that is, random creature from which to fashion undead + if (ztype == 250) + { + // how OOD this zombie can be. + int relax = 5; + + // pick an appropriate creature to make a zombie out of, + // levelwise. The old code was generating absolutely + // incredible OOD zombies. + while(true) + { + // this limit can be updated if mons->number goes >8 bits.. + test = random2(182); // not guaranteed to be valid, so.. + cls = mons_charclass(test); + if (cls == MONS_PROGRAM_BUG) + continue; + + // on certain branches, zombie creation will fail if we use + // the mons_rarity() functions, because (for example) there + // are NO zombifiable "native" abyss creatures. Other branches + // where this is a problem are hell levels and the crypt. + // we have to watch for summoned zombies on other levels, too, + // such as the Temple, HoB, and Slime Pits. + if (you.level_type != LEVEL_DUNGEON + || player_in_hell() + || player_in_branch( BRANCH_HALL_OF_ZOT ) + || player_in_branch( BRANCH_VESTIBULE_OF_HELL ) + || player_in_branch( BRANCH_ECUMENICAL_TEMPLE ) + || player_in_branch( BRANCH_CRYPT ) + || player_in_branch( BRANCH_TOMB ) + || player_in_branch( BRANCH_HALL_OF_BLADES ) + || player_in_branch( BRANCH_SNAKE_PIT ) + || player_in_branch( BRANCH_SLIME_PITS ) + || one_chance_in(1000)) + { + ignore_rarity = true; + } + + // don't make out-of-rarity zombies when we don't have to + if (!ignore_rarity && mons_rarity(cls) == 0) + continue; + + // monster class must be zombifiable + if (!mons_zombie_size(cls)) + continue; + + // if skeleton, monster must have a skeleton + if ((cs == MONS_SKELETON_SMALL || cs == MONS_SKELETON_LARGE) + && !mons_skeleton(cls)) + { + continue; + } + + // size must match, but you can make a spectral thing out of anything. + if (mons_zombie_size(cls) != zombie_size && zombie_size >= 0) + continue; + + // hack -- non-dungeon zombies are always made out of nastier + // monsters + if (you.level_type != LEVEL_DUNGEON && mons_power(cls) > 8) + break; + + // check for rarity.. and OOD - identical to mons_place() + int level, diff, chance; + + level = mons_level( cls ) - 4; + diff = level - power; + + chance = (ignore_rarity) ? 100 + : mons_rarity(cls) - (diff * diff) / 2; + + if (power > level - relax && power < level + relax + && random2avg(100, 2) <= chance) + { + break; + } + + // every so often, we'll relax the OOD restrictions. Avoids + // infinite loops (if we don't do this, things like creating + // a large skeleton on level 1 may hang the game! + if (one_chance_in(5)) + relax++; + } + + // set type and secondary appropriately + menv[mid].number = cls; + mons_sec2 = cls; + } + else + { + menv[mid].number = mons_charclass(ztype); + mons_sec2 = menv[mid].number; + } + + menv[mid].type = menv[mid].number; + + define_monster(mid); + + menv[mid].hit_points = hit_points( menv[mid].hit_dice, 6, 5 ); + menv[mid].max_hit_points = menv[mid].hit_points; + + menv[mid].armour_class -= 2; + + if (menv[mid].armour_class < 0) + menv[mid].armour_class = 0; + + menv[mid].evasion -= 5; + + if (menv[mid].evasion < 0) + menv[mid].evasion = 0; + + menv[mid].speed -= 2; + + if (menv[mid].speed < 3) + menv[mid].speed = 3; + + menv[mid].speed_increment = 70; + menv[mid].number = mons_sec2; + + if (cs == MONS_ZOMBIE_SMALL || cs == MONS_ZOMBIE_LARGE) + { + menv[mid].type = ((mons_zombie_size(menv[mid].number) == 2) + ? MONS_ZOMBIE_LARGE : MONS_ZOMBIE_SMALL); + } + else if (cs == MONS_SKELETON_SMALL || cs == MONS_SKELETON_LARGE) + { + menv[mid].hit_points = hit_points( menv[mid].hit_dice, 5, 4 ); + menv[mid].max_hit_points = menv[mid].hit_points; + + menv[mid].armour_class -= 4; + + if (menv[mid].armour_class < 0) + menv[mid].armour_class = 0; + + menv[mid].evasion -= 2; + + if (menv[mid].evasion < 0) + menv[mid].evasion = 0; + + menv[mid].type = ((mons_zombie_size( menv[mid].number ) == 2) + ? MONS_SKELETON_LARGE : MONS_SKELETON_SMALL); + } + else if (cs == MONS_SIMULACRUM_SMALL || cs == MONS_SIMULACRUM_LARGE) + { + // Simulacrum aren't tough, but you can create piles of them. -- bwr + menv[mid].hit_points = hit_points( menv[mid].hit_dice, 1, 4 ); + menv[mid].max_hit_points = menv[mid].hit_points; + menv[mid].type = ((mons_zombie_size( menv[mid].number ) == 2) + ? MONS_SIMULACRUM_LARGE : MONS_SIMULACRUM_SMALL); + } + else if (cs == MONS_SPECTRAL_THING) + { + menv[mid].hit_points = hit_points( menv[mid].hit_dice, 4, 4 ); + menv[mid].max_hit_points = menv[mid].hit_points; + menv[mid].armour_class += 4; + menv[mid].type = MONS_SPECTRAL_THING; + } + + menv[mid].number = mons_sec2; +} // end define_zombie() + +#ifdef USE_RIVERS + +static void build_river( unsigned char river_type ) //mv +{ + int i,j; + int y, width; + + if (player_in_branch( BRANCH_CRYPT ) || player_in_branch( BRANCH_TOMB )) + return; + + // if (one_chance_in(10)) + // build_river(river_type); + + // Made rivers less wide... min width five rivers were too annoying. -- bwr + width = 3 + random2(4); + y = 10 - width + random2avg( GYM-10, 3 ); + + for (i = 5; i < (GXM - 5); i++) + { + if (one_chance_in(3)) y++; + if (one_chance_in(3)) y--; + if (coinflip()) width++; + if (coinflip()) width--; + + if (width < 2) width = 2; + if (width > 6) width = 6; + + for (j = y; j < y+width ; j++) + { + if (j >= 5 && j <= GYM - 5) + { + // Note that vaults might have been created in this area! + // So we'll avoid the silliness of orcs/royal jelly on + // lava and deep water grids. -- bwr + if (!one_chance_in(200) + // && grd[i][j] == DNGN_FLOOR + && mgrd[i][j] == NON_MONSTER + && igrd[i][j] == NON_ITEM) + { + if (width == 2 && river_type == DNGN_DEEP_WATER + && coinflip()) + { + grd[i][j] = DNGN_SHALLOW_WATER; + } + else + grd[i][j] = river_type; + } + } + } + } +} // end build_river() + +static void build_lake(unsigned char lake_type) //mv +{ + int i, j; + int x1, y1, x2, y2; + + if (player_in_branch( BRANCH_CRYPT ) || player_in_branch( BRANCH_TOMB )) + return; + + // if (one_chance_in (10)) + // build_lake(lake_type); + + x1 = 5 + random2(GXM - 30); + y1 = 5 + random2(GYM - 30); + x2 = x1 + 4 + random2(16); + y2 = y1 + 8 + random2(12); + // mpr("lake"); + + for (j = y1; j < y2; j++) + { + if (coinflip()) x1 += random2(3); + if (coinflip()) x1 -= random2(3); + if (coinflip()) x2 += random2(3); + if (coinflip()) x2 -= random2(3); + + // mv: this does much more worse effects + // if (coinflip()) x1 = x1 -2 + random2(5); + // if (coinflip()) x2 = x2 -2 + random2(5); + + if ((j-y1) < ((y2-y1) / 2)) + { + x2 += random2(3); + x1 -= random2(3); + } + else + { + x2 -= random2(3); + x1 += random2(3); + } + + for (i = x1; i < x2 ; i++) + { + if ((j >= 5 && j <= GYM - 5) && (i >= 5 && i <= GXM - 5)) + { + // Note that vaults might have been created in this area! + // So we'll avoid the silliness of monsters and items + // on lava and deep water grids. -- bwr + if (!one_chance_in(200) + // && grd[i][j] == DNGN_FLOOR + && mgrd[i][j] == NON_MONSTER + && igrd[i][j] == NON_ITEM) + { + grd[i][j] = lake_type; + } + } + } + } +} // end lake() + +#endif // USE_RIVERS -- cgit v1.2.3-54-g00ecf