2017-12-17 00:25:46 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  collections  import  OrderedDict  
						 
					
						
							
								
									
										
										
										
											2018-02-17 18:38:54 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  copy  
						 
					
						
							
								
									
										
										
										
											2018-01-06 16:25:14 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  itertools  import  zip_longest  
						 
					
						
							
								
									
										
										
										
											2017-12-17 00:25:46 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  json  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  logging  
						 
					
						
							
								
									
										
										
										
											2019-05-30 01:10:16 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  os  
						 
					
						
							
								
									
										
										
										
											2017-12-17 00:25:46 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  random  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  time  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-22 22:51:54 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  BaseClasses  import  World ,  CollectionState ,  Item ,  Region ,  Location ,  Shop  
						 
					
						
							
								
									
										
										
										
											2017-12-13 09:51:53 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  Regions  import  create_regions ,  mark_light_world_regions  
						 
					
						
							
								
									
										
										
										
											2019-07-27 09:13:13 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  InvertedRegions  import  create_inverted_regions ,  mark_dark_world_regions  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  EntranceShuffle  import  link_entrances ,  link_inverted_entrances  
						 
					
						
							
								
									
										
										
										
											2019-05-30 01:10:16 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  Rom  import  patch_rom ,  get_enemizer_patch ,  apply_rom_settings ,  Sprite ,  LocalRom ,  JsonRom  
						 
					
						
							
								
									
										
										
										
											2017-05-15 20:28:04 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								from  Rules  import  set_rules  
						 
					
						
							
								
									
										
										
										
											2017-10-15 13:52:42 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  Dungeons  import  create_dungeons ,  fill_dungeons ,  fill_dungeons_restrictive  
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  Fill  import  distribute_items_cutoff ,  distribute_items_staleness ,  distribute_items_restrictive ,  flood_items ,  balance_multiworld_progression  
						 
					
						
							
								
									
										
										
										
											2019-04-18 16:11:11 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  ItemList  import  generate_itempool ,  difficulties ,  fill_prizes  
						 
					
						
							
								
									
										
										
										
											2017-11-28 09:36:32 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  Utils  import  output_path  
						 
					
						
							
								
									
										
										
										
											2017-05-15 20:28:04 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-08-24 15:38:22 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								__version__  =  ' 0.6.3-pre '  
						 
					
						
							
								
									
										
										
										
											2019-04-29 16:11:23 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-25 15:58:35 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  main ( args ,  seed = None ) :  
						 
					
						
							
								
									
										
										
										
											2017-05-20 14:07:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    start  =  time . clock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-15 20:28:04 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # initialize the world 
							 
						 
					
						
							
								
									
										
										
										
											2019-08-10 19:37:26 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    world  =  World ( args . multi ,  args . shuffle ,  args . logic ,  args . mode ,  args . swords ,  args . difficulty ,  args . item_functionality ,  args . timer ,  args . progressive ,  args . goal ,  args . algorithm ,  not  args . nodungeonitems ,  args . accessibility ,  args . shuffleganon ,  args . quickswap ,  args . fastmenu ,  args . disablemusic ,  args . keysanity ,  args . retro ,  args . custom ,  args . customitemarray ,  args . shufflebosses ,  args . hints ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-20 14:07:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    logger  =  logging . getLogger ( ' ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  seed  is  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        random . seed ( None ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        world . seed  =  random . randint ( 0 ,  999999999 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else : 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-30 07:33:23 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        world . seed  =  int ( seed ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-20 14:07:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    random . seed ( world . seed ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-08-11 08:55:38 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    world . crystals_needed_for_ganon  =  random . randint ( 0 ,  7 )  if  args . crystals_ganon  ==  ' random '  else  int ( args . crystals_ganon ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    world . crystals_needed_for_gt  =  random . randint ( 0 ,  7 )  if  args . crystals_gt  ==  ' random '  else  int ( args . crystals_gt ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    world . rom_seeds  =  { player :  random . randint ( 0 ,  999999999 )  for  player  in  range ( 1 ,  world . players  +  1 ) } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-17 00:25:46 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    logger . info ( ' ALttP Entrance Randomizer Version  %s   -  Seed:  %s \n \n ' ,  __version__ ,  world . seed ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-20 14:07:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-04 01:06:22 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    world . difficulty_requirements  =  difficulties [ world . difficulty ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-07-27 09:13:13 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  world . mode  !=  ' inverted ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  player  in  range ( 1 ,  world . players  +  1 ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            create_regions ( world ,  player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            create_dungeons ( world ,  player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  player  in  range ( 1 ,  world . players  +  1 ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            create_inverted_regions ( world ,  player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            create_dungeons ( world ,  player ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-15 20:28:04 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-20 14:07:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    logger . info ( ' Shuffling the World about. ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-07-27 09:13:13 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  world . mode  !=  ' inverted ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  player  in  range ( 1 ,  world . players  +  1 ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            link_entrances ( world ,  player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        mark_light_world_regions ( world ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  player  in  range ( 1 ,  world . players  +  1 ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            link_inverted_entrances ( world ,  player ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-07-27 09:13:13 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        mark_dark_world_regions ( world ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-20 14:07:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 16:11:11 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    logger . info ( ' Generating Item Pool. ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    for  player  in  range ( 1 ,  world . players  +  1 ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        generate_itempool ( world ,  player ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 16:11:11 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-20 14:07:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    logger . info ( ' Calculating Access Rules. ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    for  player  in  range ( 1 ,  world . players  +  1 ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        set_rules ( world ,  player ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-20 14:07:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 16:11:11 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    logger . info ( ' Placing Dungeon Prizes. ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-05 17:52:18 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 16:11:11 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    fill_prizes ( world ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-05 17:52:18 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-06-23 21:32:31 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    logger . info ( ' Placing Dungeon Items. ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-20 14:07:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 16:34:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    shuffled_locations  =  None 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-02 20:01:52 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  args . algorithm  in  [ ' balanced ' ,  ' vt26 ' ]  or  args . keysanity : 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 16:34:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        shuffled_locations  =  world . get_unfilled_locations ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        random . shuffle ( shuffled_locations ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        fill_dungeons_restrictive ( world ,  shuffled_locations ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 13:52:42 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        fill_dungeons ( world ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-20 14:07:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    logger . info ( ' Fill the world. ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-25 15:58:35 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  args . algorithm  ==  ' flood ' : 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-20 14:07:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        flood_items ( world )   # different algo, biased towards early game progress items 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-03 21:28:02 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    elif  args . algorithm  ==  ' vt21 ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        distribute_items_cutoff ( world ,  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    elif  args . algorithm  ==  ' vt22 ' : 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-04 16:15:59 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        distribute_items_cutoff ( world ,  0.66 ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-03 21:28:02 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    elif  args . algorithm  ==  ' freshness ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        distribute_items_staleness ( world ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-01 19:07:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    elif  args . algorithm  ==  ' vt25 ' : 
							 
						 
					
						
							
								
									
										
										
										
											2017-07-20 11:22:35 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        distribute_items_restrictive ( world ,  0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 13:52:42 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    elif  args . algorithm  ==  ' vt26 ' : 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-01 21:36:30 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        distribute_items_restrictive ( world ,  gt_filler ( world ) ,  shuffled_locations ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-11 18:05:06 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    elif  args . algorithm  ==  ' balanced ' : 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-01 21:36:30 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        distribute_items_restrictive ( world ,  gt_filler ( world ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-03 21:28:02 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  world . players  >  1 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        logger . info ( ' Balancing multiworld progression. ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        balance_multiworld_progression ( world ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-20 14:07:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    logger . info ( ' Patching ROM. ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-26 18:39:32 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  args . sprite  is  not  None : 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-17 00:25:46 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  isinstance ( args . sprite ,  Sprite ) : 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-08 19:28:22 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            sprite  =  args . sprite 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            sprite  =  Sprite ( args . sprite ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-26 18:39:32 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        sprite  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-08-10 19:37:26 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    outfilebase  =  ' ER_ %s _ %s - %s - %s - %s %s _ %s - %s %s %s %s %s _ %s '  %  ( world . logic ,  world . difficulty ,  world . difficulty_adjustments ,  world . mode ,  world . goal ,  " "  if  world . timer  in  [ ' none ' ,  ' display ' ]  else  " - "  +  world . timer ,  world . shuffle ,  world . algorithm ,  " -keysanity "  if  world . keysanity  else  " " ,  " -retro "  if  world . retro  else  " " ,  " -prog_ "  +  world . progressive  if  world . progressive  in  [ ' off ' ,  ' random ' ]  else  " " ,  " -nohints "  if  not  world . hints  else  " " ,  world . seed ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-20 14:07:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-05-30 01:10:16 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    use_enemizer  =  args . enemizercli  and  ( args . shufflebosses  !=  ' none '  or  args . shuffleenemies  or  args . enemy_health  !=  ' default '  or  args . enemy_health  !=  ' default '  or  args . enemy_damage  or  args . shufflepalette  or  args . shufflepots ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    jsonout  =  { } 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-04 13:09:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  not  args . suppress_rom : 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  world . players  >  1 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            raise  NotImplementedError ( " Multiworld rom writes have not been implemented " ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-07-14 14:37:34 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            player  =  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-05-30 01:10:16 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            local_rom  =  None 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  args . jsonout : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                rom  =  JsonRom ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else : 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-30 01:10:16 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                if  use_enemizer : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    local_rom  =  LocalRom ( args . rom ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    rom  =  JsonRom ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    rom  =  LocalRom ( args . rom ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-07-11 17:46:57 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            patch_rom ( world ,  player ,  rom ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-30 01:10:16 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            enemizer_patch  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  use_enemizer : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                enemizer_patch  =  get_enemizer_patch ( world ,  player ,  rom ,  args . rom ,  args . enemizercli ,  args . shuffleenemies ,  args . enemy_health ,  args . enemy_damage ,  args . shufflepalette ,  args . shufflepots ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  args . jsonout : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                jsonout [ ' patch ' ]  =  rom . patches 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-30 01:10:16 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                if  use_enemizer : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    jsonout [ ' enemizer '  %  player ]  =  enemizer_patch 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            else : 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-30 01:10:16 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                if  use_enemizer : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    local_rom . patch_enemizer ( rom . patches ,  os . path . join ( os . path . dirname ( args . enemizercli ) ,  " enemizerBasePatch.json " ) ,  enemizer_patch ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    rom  =  local_rom 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                apply_rom_settings ( rom ,  args . heartbeep ,  args . heartcolor ,  world . quickswap ,  world . fastmenu ,  world . disable_music ,  sprite ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                rom . write_to_file ( output_path ( ' %s .sfc '  %  outfilebase ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-04 13:09:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-07-16 23:20:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  args . create_spoiler  and  not  args . jsonout : 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-28 09:36:32 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        world . spoiler . to_file ( output_path ( ' %s _Spoiler.txt '  %  outfilebase ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-20 14:07:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  not  args . skip_playthrough : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        logger . info ( ' Calculating playthrough. ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        create_playthrough ( world ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  args . jsonout : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        print ( json . dumps ( { * * jsonout ,  ' spoiler ' :  world . spoiler . to_json ( ) } ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    elif  args . create_spoiler  and  not  args . skip_playthrough : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        world . spoiler . to_file ( output_path ( ' %s _Spoiler.txt '  %  outfilebase ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-20 14:07:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    logger . info ( ' Done. Enjoy. ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-17 00:25:46 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    logger . debug ( ' Total Time:  %s ' ,  time . clock ( )  -  start ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-15 20:28:04 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  world 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-01 21:36:30 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  gt_filler ( world ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  world . goal  ==  ' triforcehunt ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  random . randint ( 15 ,  50 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  random . randint ( 0 ,  15 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  copy_world ( world ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # ToDo: Not good yet 
							 
						 
					
						
							
								
									
										
										
										
											2019-08-10 19:37:26 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ret  =  World ( world . players ,  world . shuffle ,  world . logic ,  world . mode ,  world . swords ,  world . difficulty ,  world . difficulty_adjustments ,  world . timer ,  world . progressive ,  world . goal ,  world . algorithm ,  world . place_dungeon_items ,  world . accessibility ,  world . shuffle_ganon ,  world . quickswap ,  world . fastmenu ,  world . disable_music ,  world . keysanity ,  world . retro ,  world . custom ,  world . customitemarray ,  world . boss_shuffle ,  world . hints ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ret . required_medallions  =  world . required_medallions . copy ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ret . swamp_patch_required  =  world . swamp_patch_required . copy ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ret . ganon_at_pyramid  =  world . ganon_at_pyramid . copy ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ret . powder_patch_required  =  world . powder_patch_required . copy ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ret . ganonstower_vanilla  =  world . ganonstower_vanilla . copy ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-04 13:10:22 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ret . treasure_hunt_count  =  world . treasure_hunt_count 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ret . treasure_hunt_icon  =  world . treasure_hunt_icon 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ret . sewer_light_cone  =  world . sewer_light_cone 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ret . light_world_light_cone  =  world . light_world_light_cone 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ret . dark_world_light_cone  =  world . dark_world_light_cone 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-19 21:31:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ret . seed  =  world . seed 
							 
						 
					
						
							
								
									
										
										
										
											2017-07-17 23:13:39 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ret . can_access_trock_eyebridge  =  world . can_access_trock_eyebridge 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 16:11:11 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ret . can_access_trock_front  =  world . can_access_trock_front 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ret . can_access_trock_big_chest  =  world . can_access_trock_big_chest 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ret . can_access_trock_middle  =  world . can_access_trock_middle 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-02 00:39:53 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ret . can_take_damage  =  world . can_take_damage 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-04 01:06:22 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ret . difficulty_requirements  =  world . difficulty_requirements 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-24 16:16:50 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ret . fix_fake_world  =  world . fix_fake_world 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ret . lamps_needed_for_dark_rooms  =  world . lamps_needed_for_dark_rooms 
							 
						 
					
						
							
								
									
										
										
										
											2019-08-11 08:55:38 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ret . crystals_needed_for_ganon  =  world . crystals_needed_for_ganon 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ret . crystals_needed_for_gt  =  world . crystals_needed_for_gt 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-07-27 09:13:13 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  world . mode  !=  ' inverted ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  player  in  range ( 1 ,  world . players  +  1 ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            create_regions ( ret ,  player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            create_dungeons ( ret ,  player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  player  in  range ( 1 ,  world . players  +  1 ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            create_inverted_regions ( ret ,  player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            create_dungeons ( ret ,  player ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-22 23:18:40 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    copy_dynamic_regions_and_locations ( world ,  ret ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-17 18:38:54 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-26 13:12:20 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # copy bosses 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  dungeon  in  world . dungeons : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  level ,  boss  in  dungeon . bosses . items ( ) : 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            ret . get_dungeon ( dungeon . name ,  dungeon . player ) . bosses [ level ]  =  boss 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-26 13:12:20 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-17 18:38:54 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    for  shop  in  world . shops : 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        copied_shop  =  ret . get_region ( shop . region . name ,  shop . region . player ) . shop 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-17 18:38:54 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        copied_shop . active  =  shop . active 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        copied_shop . inventory  =  copy . copy ( shop . inventory ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # connect copied world 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  region  in  world . regions : 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        copied_region  =  ret . get_region ( region . name ,  region . player ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-13 09:51:53 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        copied_region . is_light_world  =  region . is_light_world 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-27 17:17:03 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        copied_region . is_dark_world  =  region . is_dark_world 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        for  entrance  in  region . entrances : 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            ret . get_entrance ( entrance . name ,  entrance . player ) . connect ( copied_region ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # fill locations 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  location  in  world . get_locations ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  location . item  is  not  None : 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            item  =  Item ( location . item . name ,  location . item . advancement ,  location . item . priority ,  location . item . type ,  player  =  location . item . player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ret . get_location ( location . name ,  location . player ) . item  =  item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            item . location  =  ret . get_location ( location . name ,  location . player ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-17 14:40:37 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  location . event : 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            ret . get_location ( location . name ,  location . player ) . event  =  True 
							 
						 
					
						
							
								
									
										
										
										
											2019-08-04 12:32:35 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  location . locked : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ret . get_location ( location . name ,  location . player ) . locked  =  True 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # copy remaining itempool. No item in itempool should have an assigned location 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  item  in  world . itempool : 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        ret . itempool . append ( Item ( item . name ,  item . advancement ,  item . priority ,  item . type ,  player  =  item . player ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # copy progress items in state 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-13 18:17:16 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ret . state . prog_items  =  world . state . prog_items . copy ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-08-10 15:30:14 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ret . precollected_items  =  world . precollected_items . copy ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-11 00:18:30 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ret . state . stale  =  { player :  True  for  player  in  range ( 1 ,  world . players  +  1 ) } 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    for  player  in  range ( 1 ,  world . players  +  1 ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        set_rules ( ret ,  player ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-07-17 22:29:32 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  ret 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-22 23:18:40 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  copy_dynamic_regions_and_locations ( world ,  ret ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  region  in  world . dynamic_regions : 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        new_reg  =  Region ( region . name ,  region . type ,  region . hint_text ,  region . player ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-08-17 15:11:25 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        new_reg . world  =  ret 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-22 23:18:40 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        ret . regions . append ( new_reg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ret . dynamic_regions . append ( new_reg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # Note: ideally exits should be copied here, but the current use case (Take anys) do not require this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  region . shop : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            new_reg . shop  =  Shop ( new_reg ,  region . shop . room_id ,  region . shop . type ,  region . shop . shopkeeper_config ,  region . shop . replaceable ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ret . shops . append ( new_reg . shop ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  location  in  world . dynamic_locations : 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        new_reg  =  ret . get_region ( location . parent_region . name ,  location . parent_region . player ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-08-17 15:11:25 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        new_loc  =  Location ( location . player ,  location . name ,  location . address ,  location . crystal ,  location . hint_text ,  new_reg ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-22 23:18:40 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        new_reg . locations . append ( new_loc ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-08-17 15:11:25 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ret . clear_location_cache ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-22 23:18:40 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  create_playthrough ( world ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # create a copy as we will modify it 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-04 16:15:59 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    old_world  =  world 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    world  =  copy_world ( world ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-26 09:53:34 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-06-23 22:15:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # if we only check for beatable, we can do this sanity check first before writing down spheres 
							 
						 
					
						
							
								
									
										
										
										
											2019-08-04 17:40:13 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  world . accessibility  ==  ' none '  and  not  world . can_beat_game ( ) : 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-23 22:15:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        raise  RuntimeError ( ' Cannot beat game. Something went terribly wrong here! ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # get locations containing progress items 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-02 20:01:16 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    prog_locations  =  [ location  for  location  in  world . get_filled_locations ( )  if  location . item . advancement ] 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-01 15:55:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    state_cache  =  [ None ] 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    collection_spheres  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    state  =  CollectionState ( world ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    sphere_candidates  =  list ( prog_locations ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-26 09:55:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    logging . getLogger ( ' ' ) . debug ( ' Building up collection spheres. ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    while  sphere_candidates : 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-28 18:34:37 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  not  world . keysanity : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            state . sweep_for_events ( key_only = True ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-24 11:11:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        sphere  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # build up spheres of collection radius. Everything in each sphere is independent from each other in dependencies and only depends on lower spheres 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  location  in  sphere_candidates : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  state . can_reach ( location ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                sphere . append ( location ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  location  in  sphere : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            sphere_candidates . remove ( location ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-01 15:55:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            state . collect ( location . item ,  True ,  location ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-17 14:40:37 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        collection_spheres . append ( sphere ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-01 15:55:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        state_cache . append ( state . copy ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-26 09:55:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-01 15:55:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        logging . getLogger ( ' ' ) . debug ( ' Calculated sphere  %i , containing  %i  of  %i  progress items. ' ,  len ( collection_spheres ) ,  len ( sphere ) ,  len ( prog_locations ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-26 09:55:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  not  sphere : 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            logging . getLogger ( ' ' ) . debug ( ' The following items could not be reached:  %s ' ,  [ ' %s  (Player  %d ) at  %s  (Player  %d ) '  %  ( location . item . name ,  location . item . player ,  location . name ,  location . player )  for  location  in  sphere_candidates ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-08-04 17:40:13 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  not  world . accessibility  ==  ' none ' : 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-23 22:15:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                raise  RuntimeError ( ' Not all progression items reachable. Something went terribly wrong here. ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                break 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-26 09:55:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # in the second phase, we cull each sphere such that the game is still beatable, reducing each range of influence to the bare minimum required inside it 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-01 15:55:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    for  num ,  sphere  in  reversed ( list ( enumerate ( collection_spheres ) ) ) : 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        to_delete  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  location  in  sphere : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # we remove the item at location and check if game is still beatable 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            logging . getLogger ( ' ' ) . debug ( ' Checking if  %s  (Player  %d ) is required to beat the game. ' ,  location . item . name ,  location . item . player ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            old_item  =  location . item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            location . item  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            state . remove ( old_item ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-11 00:12:09 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  world . can_beat_game ( state_cache [ num ] ) : 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                to_delete . append ( location ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # still required, got to keep it around 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                location . item  =  old_item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # cull entries in spheres for spoiler walkthrough at end 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  location  in  to_delete : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            sphere . remove ( location ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-06 14:25:49 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # we are now down to just the required progress items in collection_spheres. Unfortunately 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # the previous pruning stage could potentially have made certain items dependant on others 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # in the same or later sphere (because the location had 2 ways to access but the item originally 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # used to access it was deemed not required.) So we need to do one final sphere collection pass 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # to build up the correct spheres 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    required_locations  =  [ item  for  sphere  in  collection_spheres  for  item  in  sphere ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    state  =  CollectionState ( world ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    collection_spheres  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  required_locations : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  not  world . keysanity : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            state . sweep_for_events ( key_only = True ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        sphere  =  list ( filter ( state . can_reach ,  required_locations ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  location  in  sphere : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            required_locations . remove ( location ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            state . collect ( location . item ,  True ,  location ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        collection_spheres . append ( sphere ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        logging . getLogger ( ' ' ) . debug ( ' Calculated final sphere  %i , containing  %i  of  %i  progress items. ' ,  len ( collection_spheres ) ,  len ( sphere ) ,  len ( required_locations ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  not  sphere : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            raise  RuntimeError ( ' Not all required items reachable. Something went terribly wrong here. ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-06-04 16:15:59 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # store the required locations for statistical analysis 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    old_world . required_locations  =  [ ( location . name ,  location . player )  for  sphere  in  collection_spheres  for  location  in  sphere ] 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-04 16:15:59 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-01 15:55:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  flist_to_iter ( node ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        while  node : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            value ,  node  =  node 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            yield  value 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-06 16:25:14 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  get_path ( state ,  region ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        reversed_path_as_flist  =  state . path . get ( region ,  ( region ,  None ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        string_path_flat  =  reversed ( list ( map ( str ,  flist_to_iter ( reversed_path_as_flist ) ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # Now we combine the flat string list into (region, exit) pairs 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        pathsiter  =  iter ( string_path_flat ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        pathpairs  =  zip_longest ( pathsiter ,  pathsiter ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  list ( pathpairs ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    old_world . spoiler . paths  =  dict ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  player  in  range ( 1 ,  world . players  +  1 ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        old_world . spoiler . paths . update ( {  str ( location )  :  get_path ( state ,  location . parent_region )  for  sphere  in  collection_spheres  for  location  in  sphere  if  location . player  ==  player } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  _ ,  path  in  dict ( old_world . spoiler . paths ) . items ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  any ( exit  ==  ' Pyramid Fairy '  for  ( _ ,  exit )  in  path ) : 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-27 09:13:13 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                if  world . mode  !=  ' inverted ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    old_world . spoiler . paths [ str ( world . get_region ( ' Big Bomb Shop ' ,  player ) ) ]  =  get_path ( state ,  world . get_region ( ' Big Bomb Shop ' ,  player ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    old_world . spoiler . paths [ str ( world . get_region ( ' Inverted Big Bomb Shop ' ,  player ) ) ]  =  get_path ( state ,  world . get_region ( ' Inverted Big Bomb Shop ' ,  player ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-01 15:55:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # we can finally output our playthrough 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-18 20:43:37 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    old_world . spoiler . playthrough  =  OrderedDict ( [ ( str ( i  +  1 ) ,  { str ( location ) :  str ( location . item )  for  location  in  sphere } )  for  i ,  sphere  in  enumerate ( collection_spheres ) ] )