| 
									
										
										
										
											2022-06-20 15:12:13 -04:00
										 |  |  | import typing | 
					
						
							| 
									
										
										
										
											2025-03-22 08:00:07 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-16 02:08:38 -05:00
										 |  |  | from BaseClasses import MultiWorld | 
					
						
							|  |  |  | from worlds.AutoWorld import World | 
					
						
							| 
									
										
										
										
											2022-06-20 15:12:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-22 08:00:07 -04:00
										 |  |  | from .Names import LocationName | 
					
						
							|  |  |  | from .Options import GateBossPlando | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | speed_characters_1 = "sonic vs shadow 1" | 
					
						
							|  |  |  | speed_characters_2 = "sonic vs shadow 2" | 
					
						
							|  |  |  | mech_characters_1 = "tails vs eggman 1" | 
					
						
							|  |  |  | mech_characters_2 = "tails vs eggman 2" | 
					
						
							|  |  |  | hunt_characters_1 = "knuckles vs rouge 1" | 
					
						
							|  |  |  | big_foot = "big foot" | 
					
						
							|  |  |  | hot_shot = "hot shot" | 
					
						
							|  |  |  | flying_dog = "flying dog" | 
					
						
							|  |  |  | egg_golem_sonic = "egg golem (sonic)" | 
					
						
							|  |  |  | egg_golem_eggman = "egg golem (eggman)" | 
					
						
							|  |  |  | king_boom_boo = "king boom boo" | 
					
						
							| 
									
										
										
										
											2022-06-20 15:12:13 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | gate_bosses_no_requirements_table = { | 
					
						
							|  |  |  |     speed_characters_1: 0, | 
					
						
							|  |  |  |     speed_characters_2: 1, | 
					
						
							|  |  |  |     mech_characters_1: 2, | 
					
						
							|  |  |  |     mech_characters_2: 3, | 
					
						
							|  |  |  |     hunt_characters_1: 4, | 
					
						
							|  |  |  |     big_foot: 5, | 
					
						
							|  |  |  |     hot_shot: 6, | 
					
						
							|  |  |  |     flying_dog: 7, | 
					
						
							|  |  |  |     egg_golem_sonic: 8, | 
					
						
							|  |  |  |     egg_golem_eggman: 9, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | gate_bosses_with_requirements_table = { | 
					
						
							|  |  |  |     king_boom_boo: 10, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-27 17:38:58 -04:00
										 |  |  | extra_boss_rush_bosses_table = { | 
					
						
							|  |  |  |     speed_characters_1: 11, | 
					
						
							|  |  |  |     speed_characters_2: 12, | 
					
						
							|  |  |  |     mech_characters_1: 13, | 
					
						
							|  |  |  |     mech_characters_2: 14, | 
					
						
							|  |  |  |     hunt_characters_1: 15, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-20 15:12:13 -04:00
										 |  |  | all_gate_bosses_table = { | 
					
						
							|  |  |  |     **gate_bosses_no_requirements_table, | 
					
						
							|  |  |  |     **gate_bosses_with_requirements_table, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-22 08:00:07 -04:00
										 |  |  | boss_id_to_name = { | 
					
						
							|  |  |  |     0: "Sonic vs Shadow 1", | 
					
						
							|  |  |  |     1: "Sonic vs Shadow 2", | 
					
						
							|  |  |  |     2: "Tails vs Eggman 1", | 
					
						
							|  |  |  |     3: "Tails vs Eggman 2", | 
					
						
							|  |  |  |     4: "Knuckles vs Rouge 1", | 
					
						
							|  |  |  |     5: "F-6t BIG FOOT", | 
					
						
							|  |  |  |     6: "B-3x HOT SHOT", | 
					
						
							|  |  |  |     7: "R-1/A FLYING DOG", | 
					
						
							|  |  |  |     8: "Egg Golem (Sonic)", | 
					
						
							|  |  |  |     9: "Egg Golem (Eggman)", | 
					
						
							|  |  |  |     10: "King Boom Boo", | 
					
						
							|  |  |  |     11: "Sonic vs Shadow 1", | 
					
						
							|  |  |  |     12: "Sonic vs Shadow 2", | 
					
						
							|  |  |  |     13: "Tails vs Eggman 1", | 
					
						
							|  |  |  |     14: "Tails vs Eggman 2", | 
					
						
							|  |  |  |     15: "Knuckles vs Rouge 1", | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-20 15:12:13 -04:00
										 |  |  | def get_boss_name(boss: int): | 
					
						
							| 
									
										
										
										
											2025-03-22 08:00:07 -04:00
										 |  |  |     return boss_id_to_name[boss] | 
					
						
							| 
									
										
										
										
											2022-06-20 15:12:13 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def boss_has_requirement(boss: int): | 
					
						
							|  |  |  |     return boss >= len(gate_bosses_no_requirements_table) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-22 08:00:07 -04:00
										 |  |  | def get_gate_bosses(world: World): | 
					
						
							| 
									
										
										
										
											2022-06-20 15:12:13 -04:00
										 |  |  |     selected_bosses: typing.List[int] = [] | 
					
						
							|  |  |  |     boss_gates: typing.List[int] = [] | 
					
						
							|  |  |  |     available_bosses: typing.List[str] = list(gate_bosses_no_requirements_table.keys()) | 
					
						
							| 
									
										
										
										
											2025-03-22 08:00:07 -04:00
										 |  |  |     world.random.shuffle(available_bosses) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     gate_boss_plando: typing.Union[int, str] = world.options.gate_boss_plando.value | 
					
						
							|  |  |  |     plando_bosses = ["None", "None", "None", "None", "None"] | 
					
						
							|  |  |  |     if isinstance(gate_boss_plando, str): | 
					
						
							|  |  |  |         # boss plando | 
					
						
							|  |  |  |         options = gate_boss_plando.split(";") | 
					
						
							|  |  |  |         gate_boss_plando = GateBossPlando.options[options.pop()] | 
					
						
							|  |  |  |         for option in options: | 
					
						
							|  |  |  |             if "-" in option: | 
					
						
							|  |  |  |                 loc, boss = option.split("-") | 
					
						
							|  |  |  |                 boss_num = LocationName.boss_gate_names[loc] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if boss_num >= world.options.number_of_level_gates.value: | 
					
						
							|  |  |  |                     # Don't reject bosses plando'd into gate bosses that won't exist | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if boss in plando_bosses: | 
					
						
							|  |  |  |                     # TODO: Raise error here. Duplicates not allowed | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 plando_bosses[boss_num] = boss | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if boss in available_bosses: | 
					
						
							|  |  |  |                     available_bosses.remove(boss) | 
					
						
							| 
									
										
										
										
											2022-06-20 15:12:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-16 02:08:38 -05:00
										 |  |  |     for x in range(world.options.number_of_level_gates): | 
					
						
							| 
									
										
										
										
											2025-03-22 08:00:07 -04:00
										 |  |  |         if ("king boom boo" not in selected_bosses) and ("king boom boo" not in available_bosses) and ((x + 1) / world.options.number_of_level_gates) > 0.5: | 
					
						
							| 
									
										
										
										
											2022-06-20 15:12:13 -04:00
										 |  |  |             available_bosses.extend(gate_bosses_with_requirements_table) | 
					
						
							| 
									
										
										
										
											2025-03-22 08:00:07 -04:00
										 |  |  |             world.random.shuffle(available_bosses) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         chosen_boss = available_bosses[0] | 
					
						
							|  |  |  |         if plando_bosses[x] != "None": | 
					
						
							|  |  |  |             available_bosses.append(plando_bosses[x]) | 
					
						
							|  |  |  |             chosen_boss = plando_bosses[x] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         selected_bosses.append(all_gate_bosses_table[chosen_boss]) | 
					
						
							| 
									
										
										
										
											2022-06-20 15:12:13 -04:00
										 |  |  |         boss_gates.append(x + 1) | 
					
						
							| 
									
										
										
										
											2025-03-22 08:00:07 -04:00
										 |  |  |         available_bosses.remove(chosen_boss) | 
					
						
							| 
									
										
										
										
											2022-06-20 15:12:13 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     bosses: typing.Dict[int, int] = dict(zip(boss_gates, selected_bosses)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return bosses | 
					
						
							| 
									
										
										
										
											2023-06-27 17:38:58 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-22 08:00:07 -04:00
										 |  |  | def get_boss_rush_bosses(world: World): | 
					
						
							| 
									
										
										
										
											2023-06-27 17:38:58 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-16 02:08:38 -05:00
										 |  |  |     if world.options.boss_rush_shuffle == 0: | 
					
						
							| 
									
										
										
										
											2023-06-27 17:38:58 -04:00
										 |  |  |         boss_list_o = list(range(0, 16)) | 
					
						
							|  |  |  |         boss_list_s = [5, 2, 0, 10, 8, 4, 3, 1, 6, 13, 7, 11, 9, 15, 14, 12] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return dict(zip(boss_list_o, boss_list_s)) | 
					
						
							| 
									
										
										
										
											2023-11-16 02:08:38 -05:00
										 |  |  |     elif world.options.boss_rush_shuffle == 1: | 
					
						
							| 
									
										
										
										
											2023-06-27 17:38:58 -04:00
										 |  |  |         boss_list_o = list(range(0, 16)) | 
					
						
							|  |  |  |         boss_list_s = boss_list_o.copy() | 
					
						
							| 
									
										
										
										
											2025-03-22 08:00:07 -04:00
										 |  |  |         world.random.shuffle(boss_list_s) | 
					
						
							| 
									
										
										
										
											2023-06-27 17:38:58 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return dict(zip(boss_list_o, boss_list_s)) | 
					
						
							| 
									
										
										
										
											2023-11-16 02:08:38 -05:00
										 |  |  |     elif world.options.boss_rush_shuffle == 2: | 
					
						
							| 
									
										
										
										
											2023-06-27 17:38:58 -04:00
										 |  |  |         boss_list_o = list(range(0, 16)) | 
					
						
							| 
									
										
										
										
											2025-03-22 08:00:07 -04:00
										 |  |  |         boss_list_s = [world.random.choice(boss_list_o) for i in range(0, 16)] | 
					
						
							| 
									
										
										
										
											2023-06-27 17:38:58 -04:00
										 |  |  |         if 10 not in boss_list_s: | 
					
						
							| 
									
										
										
										
											2025-03-22 08:00:07 -04:00
										 |  |  |             boss_list_s[world.random.randint(0, 15)] = 10 | 
					
						
							| 
									
										
										
										
											2023-06-27 17:38:58 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return dict(zip(boss_list_o, boss_list_s)) | 
					
						
							| 
									
										
										
										
											2023-11-16 02:08:38 -05:00
										 |  |  |     elif world.options.boss_rush_shuffle == 3: | 
					
						
							| 
									
										
										
										
											2023-06-27 17:38:58 -04:00
										 |  |  |         boss_list_o = list(range(0, 16)) | 
					
						
							| 
									
										
										
										
											2025-03-22 08:00:07 -04:00
										 |  |  |         boss_list_s = [world.random.choice(boss_list_o)] * len(boss_list_o) | 
					
						
							| 
									
										
										
										
											2023-06-27 17:38:58 -04:00
										 |  |  |         if 10 not in boss_list_s: | 
					
						
							| 
									
										
										
										
											2025-03-22 08:00:07 -04:00
										 |  |  |             boss_list_s[world.random.randint(0, 15)] = 10 | 
					
						
							| 
									
										
										
										
											2023-06-27 17:38:58 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return dict(zip(boss_list_o, boss_list_s)) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         return dict() |