2017-05-25 13:58:35 +00:00
from Items import ItemFactory
2017-10-15 16:16:07 +00:00
from BaseClasses import Dungeon
2017-05-15 18:28:04 +00:00
import random
2017-10-15 16:16:07 +00:00
def create_dungeons ( world ) :
def make_dungeon ( name , dungeon_regions , big_key , small_keys , dungeon_items ) :
dungeon = Dungeon ( name , dungeon_regions , big_key , small_keys , dungeon_items )
for region in dungeon . regions :
world . get_region ( region ) . dungeon = dungeon
return dungeon
ES = make_dungeon ( ' Hyrule Castle ' , [ ' Hyrule Castle ' , ' Sewers ' , ' Sewers (Dark) ' , ' Sanctuary ' ] , None , [ ItemFactory ( ' Small Key (Escape) ' ) ] , [ ItemFactory ( ' Map (Escape) ' ) ] )
EP = make_dungeon ( ' Eastern Palace ' , [ ' Eastern Palace ' ] , ItemFactory ( ' Big Key (Eastern Palace) ' ) , [ ] , ItemFactory ( [ ' Map (Eastern Palace) ' , ' Compass (Eastern Palace) ' ] ) )
DP = make_dungeon ( ' Desert Palace ' , [ ' Desert Palace North ' , ' Desert Palace Main ' , ' Desert Palace East ' ] , ItemFactory ( ' Big Key (Desert Palace) ' ) , [ ItemFactory ( ' Small Key (Desert Palace) ' ) ] , ItemFactory ( [ ' Map (Desert Palace) ' , ' Compass (Desert Palace) ' ] ) )
ToH = make_dungeon ( ' Tower of Hera ' , [ ' Tower of Hera (Bottom) ' , ' Tower of Hera (Basement) ' , ' Tower of Hera (Top) ' ] , ItemFactory ( ' Big Key (Tower of Hera) ' ) , [ ItemFactory ( ' Small Key (Tower of Hera) ' ) ] , ItemFactory ( [ ' Map (Tower of Hera) ' , ' Compass (Tower of Hera) ' ] ) )
AT = make_dungeon ( ' Agahnims Tower ' , [ ' Agahnims Tower ' , ' Agahnim 1 ' ] , None , ItemFactory ( [ ' Small Key (Agahnims Tower) ' ] * 2 ) , [ ] )
PoD = make_dungeon ( ' Palace of Darkness ' , [ ' Dark Palace (Entrance) ' , ' Dark Palace (Center) ' , ' Dark Palace (Big Key Chest) ' , ' Dark Palace (Bonk Section) ' , ' Dark Palace (North) ' , ' Dark Palace (Maze) ' , ' Dark Palace (Spike Statue Room) ' , ' Dark Palace (Final Section) ' ] , ItemFactory ( ' Big Key (Palace of Darkness) ' ) , ItemFactory ( [ ' Small Key (Palace of Darkness) ' ] * 6 ) , ItemFactory ( [ ' Map (Palace of Darkness) ' , ' Compass (Palace of Darkness) ' ] ) )
TT = make_dungeon ( ' Thieves Town ' , [ ' Thieves Town (Entrance) ' , ' Thieves Town (Deep) ' , ' Blind Fight ' ] , ItemFactory ( ' Big Key (Thieves Town) ' ) , [ ItemFactory ( ' Small Key (Thieves Town) ' ) ] , ItemFactory ( [ ' Map (Thieves Town) ' , ' Compass (Thieves Town) ' ] ) )
SW = make_dungeon ( ' Skull Woods ' , [ ' Skull Woods Final Section (Entrance) ' , ' Skull Woods First Section ' , ' Skull Woods Second Section ' , ' Skull Woods Final Section (Mothula) ' ] , ItemFactory ( ' Big Key (Skull Woods) ' ) , ItemFactory ( [ ' Small Key (Skull Woods) ' ] * 2 ) , ItemFactory ( [ ' Map (Skull Woods) ' , ' Compass (Skull Woods) ' ] ) )
SP = make_dungeon ( ' Swamp Palace ' , [ ' Swamp Palace (Entrance) ' , ' Swamp Palace (First Room) ' , ' Swamp Palace (Starting Area) ' , ' Swamp Palace (Center) ' , ' Swamp Palace (North) ' ] , ItemFactory ( ' Big Key (Swamp Palace) ' ) , [ ItemFactory ( ' Small Key (Swamp Palace) ' ) ] , ItemFactory ( [ ' Map (Swamp Palace) ' , ' Compass (Swamp Palace) ' ] ) )
IP = make_dungeon ( ' Ice Palace ' , [ ' Ice Palace (Entrance) ' , ' Ice Palace (Main) ' , ' Ice Palace (East) ' , ' Ice Palace (East Top) ' , ' Ice Palace (Kholdstare) ' ] , ItemFactory ( ' Big Key (Ice Palace) ' ) , ItemFactory ( [ ' Small Key (Ice Palace) ' ] * 2 ) , ItemFactory ( [ ' Map (Ice Palace) ' , ' Compass (Ice Palace) ' ] ) )
MM = make_dungeon ( ' Misery Mire ' , [ ' Misery Mire (Entrance) ' , ' Misery Mire (Main) ' , ' Misery Mire (West) ' , ' Misery Mire (Final Area) ' , ' Misery Mire (Vitreous) ' ] , ItemFactory ( ' Big Key (Misery Mire) ' ) , ItemFactory ( [ ' Small Key (Misery Mire) ' ] * 3 ) , ItemFactory ( [ ' Map (Misery Mire) ' , ' Compass (Misery Mire) ' ] ) )
TR = make_dungeon ( ' Turtle Rock ' , [ ' Turtle Rock (Entrance) ' , ' Turtle Rock (First Section) ' , ' Turtle Rock (Chain Chomp Room) ' , ' Turtle Rock (Second Section) ' , ' Turtle Rock (Big Chest) ' , ' Turtle Rock (Roller Switch Room) ' , ' Turtle Rock (Dark Room) ' , ' Turtle Rock (Eye Bridge) ' , ' Turtle Rock (Trinexx) ' ] , ItemFactory ( ' Big Key (Turtle Rock) ' ) , ItemFactory ( [ ' Small Key (Turtle Rock) ' ] * 4 ) , ItemFactory ( [ ' Map (Turtle Rock) ' , ' Compass (Turtle Rock) ' ] ) )
GT = make_dungeon ( ' Ganons Tower ' , [ ' Ganons Tower (Entrance) ' , ' Ganons Tower (Tile Room) ' , ' Ganons Tower (Compass Room) ' , ' Ganons Tower (Hookshot Room) ' , ' Ganons Tower (Map Room) ' , ' Ganons Tower (Firesnake Room) ' , ' Ganons Tower (Teleport Room) ' , ' Ganons Tower (Bottom) ' , ' Ganons Tower (Top) ' , ' Ganons Tower (Before Moldorm) ' , ' Ganons Tower (Moldorm) ' , ' Agahnim 2 ' ] , ItemFactory ( ' Big Key (Ganons Tower) ' ) , ItemFactory ( [ ' Small Key (Ganons Tower) ' ] * 4 ) , ItemFactory ( [ ' Map (Ganons Tower) ' , ' Compass (Ganons Tower) ' ] ) )
world . dungeons = [ TR , ES , EP , DP , ToH , AT , PoD , TT , SW , IP , MM , GT , SP ]
2017-05-15 18:28:04 +00:00
2017-10-15 16:16:07 +00:00
def fill_dungeons ( world ) :
2017-06-23 19:32:31 +00:00
freebes = [ ' [dungeon-A2-1F] Ganons Tower - Map Room ' , ' [dungeon-D1-1F] Dark Palace - Spike Statue Room ' , ' [dungeon-D1-1F] Dark Palace - Big Key Room ' , ' [dungeon-D7-B1] Turtle Rock - Big Key Room ' ]
2017-05-15 18:28:04 +00:00
2017-06-17 12:40:37 +00:00
all_state_base = world . get_all_state ( )
2017-08-05 15:50:47 +00:00
world . push_item ( world . get_location ( ' [dungeon-D3-B1] Skull Woods - South of Big Chest ' ) , ItemFactory ( ' Small Key (Skull Woods) ' ) , False )
world . get_location ( ' [dungeon-D3-B1] Skull Woods - South of Big Chest ' ) . event = True
2017-05-15 18:28:04 +00:00
2017-10-15 16:16:07 +00:00
dungeons = [ ( list ( dungeon . regions ) , dungeon . big_key , list ( dungeon . small_keys ) , list ( dungeon . dungeon_items ) ) for dungeon in world . dungeons ]
2017-07-17 20:26:15 +00:00
2017-08-05 15:51:38 +00:00
loopcnt = 0
while dungeons :
loopcnt + = 1
dungeon_regions , big_key , small_keys , dungeon_items = dungeons . pop ( 0 )
2017-05-15 18:28:04 +00:00
# this is what we need to fill
dungeon_locations = [ location for location in world . get_unfilled_locations ( ) if location . parent_region . name in dungeon_regions ]
random . shuffle ( dungeon_locations )
2017-06-17 12:40:37 +00:00
all_state = all_state_base . copy ( )
2017-05-15 18:28:04 +00:00
# first place big key
if big_key is not None :
bk_location = None
for location in dungeon_locations :
if location . item_rule ( big_key ) :
bk_location = location
break
if bk_location is None :
raise RuntimeError ( ' No suitable location for %s ' % big_key )
world . push_item ( bk_location , big_key , False )
2017-06-17 12:40:37 +00:00
bk_location . event = True
2017-05-15 18:28:04 +00:00
dungeon_locations . remove ( bk_location )
all_state . _clear_cache ( )
2017-08-05 15:51:38 +00:00
big_key = None
2017-05-15 18:28:04 +00:00
# next place small keys
2017-08-05 15:51:38 +00:00
while small_keys :
small_key = small_keys . pop ( )
2017-06-17 12:40:37 +00:00
all_state . sweep_for_events ( )
2017-05-15 18:28:04 +00:00
sk_location = None
for location in dungeon_locations :
2017-07-17 20:26:15 +00:00
if location . name in freebes or ( location . can_reach ( all_state ) and location . item_rule ( small_key ) ) :
2017-05-15 18:28:04 +00:00
sk_location = location
break
if sk_location is None :
2017-08-05 15:51:38 +00:00
# need to retry this later
small_keys . append ( small_key )
dungeons . append ( ( dungeon_regions , big_key , small_keys , dungeon_items ) )
# infinite regression protection
if loopcnt < 30 :
break
else :
raise RuntimeError ( ' No suitable location for %s ' % small_key )
2017-05-15 18:28:04 +00:00
world . push_item ( sk_location , small_key , False )
2017-06-17 12:40:37 +00:00
sk_location . event = True
2017-05-15 18:28:04 +00:00
dungeon_locations . remove ( sk_location )
all_state . _clear_cache ( )
2017-08-05 15:51:38 +00:00
if small_keys :
# key placement not finished, loop again
continue
2017-05-15 18:28:04 +00:00
# next place dungeon items
2017-05-20 12:05:15 +00:00
if world . place_dungeon_items :
2017-05-15 18:28:04 +00:00
for dungeon_item in dungeon_items :
di_location = dungeon_locations . pop ( )
world . push_item ( di_location , dungeon_item , False )
world . state . _clear_cache ( )
2017-05-25 15:47:15 +00:00
2017-10-15 17:52:42 +00:00
def fill_dungeons_restrictive ( world ) :
from Main import fill_restrictive
all_state_base = world . get_all_state ( )
world . push_item ( world . get_location ( ' [dungeon-D3-B1] Skull Woods - South of Big Chest ' ) , ItemFactory ( ' Small Key (Skull Woods) ' ) , False )
world . get_location ( ' [dungeon-D3-B1] Skull Woods - South of Big Chest ' ) . event = True
shuffled_locations = world . get_unfilled_locations ( )
random . shuffle ( shuffled_locations )
dungeon_items = [ item for dungeon in world . dungeons for item in dungeon . all_items ]
#sort in the order Big Key, Small Key, Other before placing dungeon items
sort_order = { " BigKey " : 3 , " SmallKey " : 2 } ;
dungeon_items . sort ( key = lambda item : sort_order . get ( item . type , 1 ) )
fill_restrictive ( world , all_state_base , shuffled_locations , dungeon_items )
world . state . _clear_cache ( )
2017-05-25 15:47:15 +00:00
dungeon_music_addresses = { ' Armos - Pendant ' : [ 0x1559A ] ,
' Lanmolas - Pendant ' : [ 0x1559B , 0x1559C , 0x1559D , 0x1559E ] ,
' Moldorm - Pendant ' : [ 0x155C5 , 0x1107A , 0x10B8C ] ,
' Helmasaur - Crystal ' : [ 0x155B8 ] ,
' Arrghus - Crystal ' : [ 0x155B7 ] ,
' Blind - Crystal ' : [ 0x155C6 ] ,
' Mothula - Crystal ' : [ 0x155BA , 0x155BB , 0x155BC , 0x155BD , 0x15608 , 0x15609 , 0x1560A , 0x1560B ] ,
' Kholdstare - Crystal ' : [ 0x155BF ] ,
' Vitreous - Crystal ' : [ 0x155B9 ] ,
' Trinexx - Crystal ' : [ 0x155C7 , 0x155A7 , 0x155AA , 0x155AB ] }