| 
									
										
										
										
											2025-07-28 00:53:04 -04:00
										 |  |  | from BaseClasses import Region, Item, ItemClassification | 
					
						
							|  |  |  | from .Locations import grinch_locations_to_id, grinch_locations, GrinchLocation | 
					
						
							| 
									
										
										
										
											2025-07-28 23:12:47 -04:00
										 |  |  | from .Items import grinch_items_to_id, GrinchItem, ALL_ITEMS_TABLE, MISC_ITEMS_TABLE | 
					
						
							| 
									
										
										
										
											2025-07-28 00:53:04 -04:00
										 |  |  | from .Regions import connect_regions | 
					
						
							| 
									
										
										
										
											2025-08-30 16:32:56 -04:00
										 |  |  | from .Rules import set_location_rules | 
					
						
							| 
									
										
										
										
											2025-07-26 20:51:05 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-06 23:34:52 -04:00
										 |  |  | from .Client import * | 
					
						
							| 
									
										
										
										
											2025-08-25 19:48:45 -04:00
										 |  |  | from typing import ClassVar | 
					
						
							| 
									
										
										
										
											2025-07-25 19:33:51 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | from worlds.AutoWorld import World | 
					
						
							| 
									
										
										
										
											2025-09-09 00:04:09 -04:00
										 |  |  | import Options | 
					
						
							| 
									
										
										
										
											2025-07-25 19:33:51 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-09 00:23:36 -04:00
										 |  |  | from .Options import GrinchOptions | 
					
						
							| 
									
										
										
										
											2025-07-28 00:53:04 -04:00
										 |  |  | from .Rules import access_rules_dict | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-25 19:33:51 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | class GrinchWorld(World): | 
					
						
							|  |  |  |     game: ClassVar[str] = "The Grinch" | 
					
						
							|  |  |  |     options_dataclass = Options.GrinchOptions | 
					
						
							| 
									
										
										
										
											2025-09-06 16:50:38 -04:00
										 |  |  |     options: Options.GrinchOptions | 
					
						
							| 
									
										
										
										
											2025-07-26 00:30:19 -04:00
										 |  |  |     topology_present = True #not an open world game, very linear | 
					
						
							| 
									
										
										
										
											2025-07-26 20:51:05 -04:00
										 |  |  |     item_name_to_id: ClassVar[dict[str,int]] = grinch_items_to_id() | 
					
						
							| 
									
										
										
										
											2025-07-28 00:53:04 -04:00
										 |  |  |     location_name_to_id: ClassVar[dict[str,int]] = grinch_locations_to_id() | 
					
						
							| 
									
										
										
										
											2025-08-11 20:47:38 -04:00
										 |  |  |     required_client_version = (0, 6, 3) | 
					
						
							| 
									
										
										
										
											2025-07-28 00:53:04 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, *args, **kwargs): #Pulls __init__ function and takes control from there in BaseClasses.py | 
					
						
							|  |  |  |         self.origin_region_name: str = "Mount Crumpit" | 
					
						
							|  |  |  |         super(GrinchWorld, self).__init__(*args, **kwargs) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def generate_early(self) -> None: #Special conditions changed before generation occurs | 
					
						
							| 
									
										
										
										
											2025-09-09 00:04:09 -04:00
										 |  |  |         if self.options.ring_link == 1 and self.options.unlimited_eggs == 1: | 
					
						
							|  |  |  |             raise Options.OptionError("Cannot enable both unlimited rotten eggs and ring links. You can only enable one of these at a time."+ | 
					
						
							|  |  |  |                                       f"The following player's YAML needs to be fixed: {self.player_name}") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 00:53:04 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def create_regions(self): #Generates all regions for the multiworld | 
					
						
							|  |  |  |         for region_name in access_rules_dict.keys(): | 
					
						
							|  |  |  |             self.multiworld.regions.append(Region(region_name, self.player, self.multiworld)) | 
					
						
							|  |  |  |         self.multiworld.regions.append(Region("Mount Crumpit", self.player, self.multiworld)) | 
					
						
							|  |  |  |         for location, data in grinch_locations.items(): | 
					
						
							|  |  |  |             region = self.get_region(data.region) | 
					
						
							|  |  |  |             entry = GrinchLocation(self.player, location, region, data) | 
					
						
							|  |  |  |             if location == "Neutralizing Santa": | 
					
						
							|  |  |  |                 entry.place_locked_item(Item("Goal", ItemClassification.progression, None, self.player)) | 
					
						
							|  |  |  |             region.locations.append(entry) | 
					
						
							|  |  |  |         connect_regions(self) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def create_item(self, item: str) -> GrinchItem: #Creates specific items on demand | 
					
						
							|  |  |  |         if item in ALL_ITEMS_TABLE.keys(): | 
					
						
							|  |  |  |             return GrinchItem(item, self.player, ALL_ITEMS_TABLE[item]) | 
					
						
							|  |  |  |         raise Exception(f"Invalid item name: {item}") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def create_items(self): #Generates all items for the multiworld | 
					
						
							|  |  |  |         self_itempool: list[GrinchItem] = [] | 
					
						
							|  |  |  |         for item, data in ALL_ITEMS_TABLE.items(): | 
					
						
							|  |  |  |             self_itempool.append(self.create_item(item)) | 
					
						
							|  |  |  |             if item == "Heart of Stone": | 
					
						
							|  |  |  |                 for _ in range(3): | 
					
						
							|  |  |  |                     self_itempool.append(self.create_item(item)) | 
					
						
							| 
									
										
										
										
											2025-07-28 23:12:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         #Get number of current unfilled locations | 
					
						
							| 
									
										
										
										
											2025-08-18 16:47:12 -04:00
										 |  |  |         unfilled_locations: int = len(self.multiworld.get_unfilled_locations(self.player)) - len(ALL_ITEMS_TABLE.keys()) - 3 | 
					
						
							| 
									
										
										
										
											2025-07-28 23:12:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         for _ in range(unfilled_locations): | 
					
						
							|  |  |  |             self_itempool.append(self.create_item((self.get_other_filler_item(list(MISC_ITEMS_TABLE.keys()))))) | 
					
						
							| 
									
										
										
										
											2025-07-28 00:53:04 -04:00
										 |  |  |         self.multiworld.itempool += self_itempool | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def set_rules(self): | 
					
						
							|  |  |  |         self.multiworld.completion_condition[self.player] = lambda state: state.has("Goal", self.player) | 
					
						
							| 
									
										
										
										
											2025-08-30 16:32:56 -04:00
										 |  |  |         set_location_rules(self) | 
					
						
							| 
									
										
										
										
											2025-07-28 23:12:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def get_other_filler_item(self, other_filler: list[str]) -> str: | 
					
						
							| 
									
										
										
										
											2025-08-14 00:23:40 -04:00
										 |  |  |         return self.random.choices(other_filler)[0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def fill_slot_data(self): | 
					
						
							|  |  |  |         return { | 
					
						
							|  |  |  |             "give_unlimited_eggs": self.options.unlimited_eggs.value, | 
					
						
							| 
									
										
										
										
											2025-09-08 22:48:43 -04:00
										 |  |  |             "ring_link": self.options.ring_link.value, | 
					
						
							| 
									
										
										
										
											2025-08-16 02:26:25 -04:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def generate_output(self, output_directory: str) -> None: | 
					
						
							|  |  |  |         # print("") | 
					
						
							|  |  |  |         pass |