2017-12-17 00:25:46 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  collections  import  OrderedDict  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  json  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  logging  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  random  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  time  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-25 15:58:35 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  BaseClasses  import  World ,  CollectionState ,  Item  
						 
					
						
							
								
									
										
										
										
											2017-12-13 09:51:53 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  Regions  import  create_regions ,  mark_light_world_regions  
						 
					
						
							
								
									
										
										
										
											2017-05-25 12:09:50 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  EntranceShuffle  import  link_entrances  
						 
					
						
							
								
									
										
										
										
											2017-11-13 00:29:42 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  Rom  import  patch_rom ,  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  
						 
					
						
							
								
									
										
										
										
											2017-12-17 00:25:46 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  Fill  import  distribute_items_cutoff ,  distribute_items_staleness ,  distribute_items_restrictive ,  flood_items  
						 
					
						
							
								
									
										
										
										
											2017-11-10 04:17:28 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  ItemList  import  generate_itempool  
						 
					
						
							
								
									
										
										
										
											2017-11-28 09:36:32 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  Utils  import  output_path  
						 
					
						
							
								
									
										
										
										
											2017-05-15 20:28:04 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-02 16:15:25 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								__version__  =  ' 0.5.1-dev '  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								logic_hash  =  [ 117 ,  227 ,  77 ,  12 ,  94 ,  219 ,  67 ,  70 ,  58 ,  42 ,  7 ,  75 ,  132 ,  55 ,  130 ,  97 ,  235 ,  46 ,  206 ,  185 ,  243 ,  64 ,  109 ,  161 ,  107 ,  91 ,  224 ,  142 ,  25 ,  84 ,  4 ,  78 ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              160 ,  245 ,  143 ,  18 ,  251 ,  114 ,  165 ,  157 ,  13 ,  26 ,  119 ,  92 ,  188 ,  216 ,  27 ,  39 ,  76 ,  238 ,  152 ,  113 ,  231 ,  193 ,  191 ,  103 ,  118 ,  182 ,  213 ,  134 ,  41 ,  90 ,  246 ,  82 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              57 ,  225 ,  150 ,  139 ,  99 ,  151 ,  184 ,  11 ,  85 ,  209 ,  144 ,  147 ,  47 ,  56 ,  129 ,  247 ,  121 ,  177 ,  79 ,  1 ,  215 ,  207 ,  126 ,  136 ,  105 ,  100 ,  180 ,  5 ,  2 ,  14 ,  153 ,  6 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              163 ,  192 ,  198 ,  88 ,  98 ,  174 ,  149 ,  201 ,  249 ,  200 ,  158 ,  116 ,  196 ,  80 ,  220 ,  31 ,  111 ,  214 ,  194 ,  248 ,  221 ,  167 ,  250 ,  115 ,  38 ,  10 ,  32 ,  218 ,  133 ,  19 ,  253 ,  122 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              239 ,  16 ,  52 ,  48 ,  156 ,  205 ,  127 ,  3 ,  138 ,  237 ,  234 ,  190 ,  37 ,  112 ,  189 ,  86 ,  223 ,  236 ,  195 ,  54 ,  71 ,  181 ,  43 ,  49 ,  226 ,  255 ,  0 ,  135 ,  186 ,  203 ,  175 ,  87 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              21 ,  229 ,  120 ,  124 ,  145 ,  171 ,  252 ,  155 ,  22 ,  62 ,  199 ,  51 ,  35 ,  179 ,  159 ,  44 ,  69 ,  30 ,  172 ,  242 ,  140 ,  74 ,  9 ,  83 ,  183 ,  93 ,  202 ,  137 ,  108 ,  241 ,  173 ,  23 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              164 ,  45 ,  222 ,  232 ,  166 ,  176 ,  230 ,  63 ,  154 ,  96 ,  170 ,  34 ,  66 ,  50 ,  17 ,  211 ,  95 ,  53 ,  208 ,  244 ,  36 ,  123 ,  81 ,  187 ,  106 ,  131 ,  169 ,  29 ,  104 ,  72 ,  101 ,  141 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              68 ,  24 ,  168 ,  125 ,  217 ,  240 ,  15 ,  162 ,  148 ,  8 ,  40 ,  102 ,  33 ,  89 ,  128 ,  61 ,  210 ,  204 ,  73 ,  228 ,  59 ,  146 ,  28 ,  110 ,  233 ,  178 ,  254 ,  65 ,  197 ,  20 ,  212 ,  60 ] 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-25 21:41:37 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-20 14:07:40 +02: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 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-28 04:54:14 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    world  =  World ( args . shuffle ,  args . logic ,  args . mode ,  args . difficulty ,  args . timer ,  args . progressive ,  args . goal ,  args . algorithm ,  not  args . nodungeonitems ,  args . beatableonly ,  args . shuffleganon ,  args . quickswap ,  args . fastmenu ,  args . disablemusic ,  args . keysanity ) 
							 
						 
					
						
							
								
									
										
										
										
											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 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											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 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-15 20:28:04 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    create_regions ( world ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-04 14:23:57 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    create_dungeons ( world ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-15 20:28:04 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-20 14:07:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    logger . info ( ' Shuffling the World about. ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-07-18 12:44:13 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    link_entrances ( world ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-13 09:51:53 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    mark_light_world_regions ( world ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-20 14:07:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    logger . info ( ' Calculating Access Rules. ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-07-18 12:44:13 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    set_rules ( world ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-20 14:07:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-08-05 17:52:18 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    logger . info ( ' Generating Item Pool. ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    generate_itempool ( world ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											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 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-09 04:45:13 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  args . algorithm  ==  ' 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 ' : 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 16:34:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        distribute_items_restrictive ( world ,  random . randint ( 0 ,  15 ) ,  shuffled_locations ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-11 18:05:06 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    elif  args . algorithm  ==  ' balanced ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        distribute_items_restrictive ( world ,  random . randint ( 0 ,  15 ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-03 21:28:02 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-20 14:07:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    logger . info ( ' Calculating playthrough. ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-07-18 12:44:13 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    create_playthrough ( 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 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-11 18:05:06 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    outfilebase  =  ' ER_ %s _ %s - %s - %s %s _ %s - %s %s %s %s %s %s _ %s '  %  ( world . logic ,  world . difficulty ,  world . mode ,  world . goal ,  " "  if  world . timer  in  [ ' none ' ,  ' display ' ]  else  " - "  +  world . timer ,  world . shuffle ,  world . algorithm ,  " -keysanity "  if  world . keysanity  else  " " ,  " -progressives_ "  +  world . progressive  if  world . progressive  in  [ ' off ' ,  ' random ' ]  else  " " ,  " -fastmenu "  if  world . fastmenu  else  " " ,  " -quickswap "  if  world . quickswap  else  " " ,  " -shuffleganon "  if  world . shuffle_ganon  else  " " ,  world . seed ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-20 14:07:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-06-04 13:09:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  not  args . suppress_rom : 
							 
						 
					
						
							
								
									
										
										
										
											2017-07-14 14:37:34 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  args . jsonout : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            rom  =  JsonRom ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            rom  =  LocalRom ( args . rom ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-01 19:43:46 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        patch_rom ( world ,  rom ,  bytearray ( logic_hash ) ,  args . heartbeep ,  sprite ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-07-16 23:20:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  args . jsonout : 
							 
						 
					
						
							
								
									
										
										
										
											2017-07-18 12:44:13 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            print ( json . dumps ( { ' patch ' :  rom . patches ,  ' spoiler ' :  world . spoiler . to_json ( ) } ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-07-16 23:20:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-28 09:36:32 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            rom . write_to_file ( args . jsonout  or  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 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    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 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  copy_world ( world ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # ToDo: Not good yet 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-28 04:54:14 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ret  =  World ( world . shuffle ,  world . logic ,  world . mode ,  world . difficulty ,  world . timer ,  world . progressive ,  world . goal ,  world . algorithm ,  world . place_dungeon_items ,  world . check_beatable_only ,  world . shuffle_ganon ,  world . quickswap ,  world . fastmenu ,  world . disable_music ,  world . keysanity ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ret . required_medallions  =  list ( world . required_medallions ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-26 09:52:38 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ret . swamp_patch_required  =  world . swamp_patch_required 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-01 19:08:46 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ret . ganon_at_pyramid  =  world . ganon_at_pyramid 
							 
						 
					
						
							
								
									
										
										
										
											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 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    create_regions ( ret ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 12:16:07 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    create_dungeons ( ret ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # connect copied world 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  region  in  world . regions : 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-13 09:51:53 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        copied_region  =  ret . get_region ( region . name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        copied_region . is_light_world  =  region . is_light_world 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        for  entrance  in  region . entrances : 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-13 09:51:53 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            ret . get_entrance ( entrance . name ) . 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 : 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 12:16:07 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            item  =  Item ( location . item . name ,  location . item . advancement ,  location . item . priority ,  location . item . type ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            ret . get_location ( location . name ) . item  =  item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            item . location  =  ret . get_location ( location . name ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-17 14:40:37 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  location . event : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ret . get_location ( location . name ) . event  =  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 : 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 12:16:07 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        ret . itempool . append ( Item ( item . name ,  item . advancement ,  item . priority ,  item . type ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # copy progress items in state 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ret . state . prog_items  =  list ( world . state . prog_items ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-07-17 22:29:32 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    set_rules ( ret ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  ret 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								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-04 14:44:23 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # in treasure hunt and pedestal goals, ganon is invincible 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-01 19:07:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  world . goal  in  [ ' pedestal ' ,  ' triforcehunt ' ] : 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-26 09:53:34 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        world . get_location ( ' Ganon ' ) . item  =  None 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +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 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  world . check_beatable_only  and  not  world . can_beat_game ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        raise  RuntimeError ( ' Cannot beat game. Something went terribly wrong here! ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # get locations containing progress items 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-28 18:34:37 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    prog_locations  =  [ location  for  location  in  world . get_locations ( )  if  location . item  is  not  None  and  ( location . item . advancement  or  ( location . item . key  and  world . keysanity ) ) ] 
							 
						 
					
						
							
								
									
										
										
										
											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 ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-17 14:40:37 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            state . collect ( location . item ,  True ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        collection_spheres . append ( sphere ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-17 00:25:46 -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 : 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-17 00:25:46 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            logging . getLogger ( ' ' ) . debug ( ' The following items could not be reached:  %s ' ,  [ ' %s  at  %s '  %  ( location . item . name ,  location . name )  for  location  in  sphere_candidates ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-23 22:15:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  not  world . check_beatable_only : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                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 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  sphere  in  reversed ( collection_spheres ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        to_delete  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  location  in  sphere : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # we remove the item at location and check if game is still beatable 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-17 00:25:46 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            logging . getLogger ( ' ' ) . debug ( ' Checking if  %s  is required to beat the game. ' ,  location . item . name ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-16 21:23:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            old_item  =  location . item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            location . item  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            state . remove ( old_item ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  world . can_beat_game ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                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 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # we are now down to just the required progress items in collection_spheres in a minimum number of spheres. As a cleanup, we right trim empty spheres (can happen if we have multiple triforces) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    collection_spheres  =  [ sphere  for  sphere  in  collection_spheres  if  sphere ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-06-04 16:15:59 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # store the required locations for statistical analysis 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    old_world . required_locations  =  [ location . name  for  sphere  in  collection_spheres  for  location  in  sphere ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											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 ) ] )