| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  | from __future__ import annotations | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-21 20:17:24 +01:00
										 |  |  | import logging | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  | import typing | 
					
						
							|  |  |  | from collections import Counter | 
					
						
							| 
									
										
										
										
											2021-02-21 20:17:24 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | logger = logging.getLogger("Hollow Knight") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-15 13:31:33 +02:00
										 |  |  | from .Items import item_table, lookup_type_to_names | 
					
						
							| 
									
										
										
										
											2021-02-24 06:02:51 +01:00
										 |  |  | from .Regions import create_regions | 
					
						
							|  |  |  | from .Rules import set_rules | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  | from .Options import hollow_knight_options, hollow_knight_randomize_options | 
					
						
							|  |  |  | from .ExtractedData import locations, starts, multi_locations, location_to_region_lookup, \ | 
					
						
							|  |  |  |     event_names, item_effects, connectors, one_ways | 
					
						
							| 
									
										
										
										
											2021-02-21 20:17:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-18 18:19:21 +01:00
										 |  |  | from BaseClasses import Region, Entrance, Location, MultiWorld, Item, RegionType | 
					
						
							| 
									
										
										
										
											2021-07-15 13:31:33 +02:00
										 |  |  | from ..AutoWorld import World, LogicMixin | 
					
						
							| 
									
										
										
										
											2021-02-21 20:17:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  | white_palace_locations = { | 
					
						
							|  |  |  |     "Soul_Totem-Path_of_Pain_Below_Thornskip", | 
					
						
							|  |  |  |     "Soul_Totem-White_Palace_Final", | 
					
						
							|  |  |  |     "Lore_Tablet-Path_of_Pain_Entrance", | 
					
						
							|  |  |  |     "Soul_Totem-Path_of_Pain_Left_of_Lever", | 
					
						
							|  |  |  |     "Soul_Totem-Path_of_Pain_Hidden", | 
					
						
							|  |  |  |     "Soul_Totem-Path_of_Pain_Entrance", | 
					
						
							|  |  |  |     "Soul_Totem-Path_of_Pain_Final", | 
					
						
							|  |  |  |     "Soul_Totem-White_Palace_Entrance", | 
					
						
							|  |  |  |     "Soul_Totem-Path_of_Pain_Below_Lever", | 
					
						
							|  |  |  |     "Lore_Tablet-Palace_Throne", | 
					
						
							|  |  |  |     "Soul_Totem-Path_of_Pain_Second", | 
					
						
							|  |  |  |     "Soul_Totem-White_Palace_Left", | 
					
						
							|  |  |  |     "Lore_Tablet-Palace_Workshop", | 
					
						
							|  |  |  |     "Soul_Totem-White_Palace_Hub", | 
					
						
							|  |  |  |     "Journal_Entry-Seal_of_Binding", | 
					
						
							|  |  |  |     "Soul_Totem-White_Palace_Right", | 
					
						
							|  |  |  |     "King_Fragment", | 
					
						
							|  |  |  |     # Events: | 
					
						
							|  |  |  |     "Palace_Entrance_Lantern_Lit", | 
					
						
							|  |  |  |     "Palace_Left_Lantern_Lit", | 
					
						
							|  |  |  |     "Palace_Right_Lantern_Lit", | 
					
						
							|  |  |  |     "Warp-Path_of_Pain_Complete", | 
					
						
							|  |  |  |     "Defeated_Path_of_Pain_Arena", | 
					
						
							|  |  |  |     "Palace_Atrium_Gates_Opened", | 
					
						
							|  |  |  |     "Completed_Path_of_Pain", | 
					
						
							|  |  |  |     "Warp-White_Palace_Atrium_to_Palace_Grounds", | 
					
						
							|  |  |  |     "Warp-White_Palace_Entrance_to_Palace_Grounds", | 
					
						
							|  |  |  |     # Event-Regions: | 
					
						
							|  |  |  |     "White_Palace_03_hub", | 
					
						
							|  |  |  |     "White_Palace_13", | 
					
						
							|  |  |  |     "White_Palace_01", | 
					
						
							|  |  |  |     # Event-Transitions: | 
					
						
							|  |  |  |     "White_Palace_12[bot1]", "White_Palace_12[bot1]", "White_Palace_03_hub[bot1]", "White_Palace_16[left2]", | 
					
						
							|  |  |  |     "White_Palace_16[left2]", "White_Palace_11[door2]", "White_Palace_11[door2]", "White_Palace_18[top1]", | 
					
						
							|  |  |  |     "White_Palace_18[top1]", "White_Palace_15[left1]", "White_Palace_15[left1]", "White_Palace_05[left2]", | 
					
						
							|  |  |  |     "White_Palace_05[left2]", "White_Palace_14[bot1]", "White_Palace_14[bot1]", "White_Palace_13[left2]", | 
					
						
							|  |  |  |     "White_Palace_13[left2]", "White_Palace_03_hub[left1]", "White_Palace_03_hub[left1]", "White_Palace_15[right2]", | 
					
						
							|  |  |  |     "White_Palace_15[right2]", "White_Palace_06[top1]", "White_Palace_06[top1]", "White_Palace_03_hub[bot1]", | 
					
						
							|  |  |  |     "White_Palace_08[right1]", "White_Palace_08[right1]", "White_Palace_03_hub[right1]", "White_Palace_03_hub[right1]", | 
					
						
							|  |  |  |     "White_Palace_01[right1]", "White_Palace_01[right1]", "White_Palace_08[left1]", "White_Palace_08[left1]", | 
					
						
							|  |  |  |     "White_Palace_19[left1]", "White_Palace_19[left1]", "White_Palace_04[right2]", "White_Palace_04[right2]", | 
					
						
							|  |  |  |     "White_Palace_01[left1]", "White_Palace_01[left1]", "White_Palace_17[right1]", "White_Palace_17[right1]", | 
					
						
							|  |  |  |     "White_Palace_07[bot1]", "White_Palace_07[bot1]", "White_Palace_20[bot1]", "White_Palace_20[bot1]", | 
					
						
							|  |  |  |     "White_Palace_03_hub[left2]", "White_Palace_03_hub[left2]", "White_Palace_18[right1]", "White_Palace_18[right1]", | 
					
						
							|  |  |  |     "White_Palace_05[right1]", "White_Palace_05[right1]", "White_Palace_17[bot1]", "White_Palace_17[bot1]", | 
					
						
							|  |  |  |     "White_Palace_09[right1]", "White_Palace_09[right1]", "White_Palace_16[left1]", "White_Palace_16[left1]", | 
					
						
							|  |  |  |     "White_Palace_13[left1]", "White_Palace_13[left1]", "White_Palace_06[bot1]", "White_Palace_06[bot1]", | 
					
						
							|  |  |  |     "White_Palace_15[right1]", "White_Palace_15[right1]", "White_Palace_06[left1]", "White_Palace_06[left1]", | 
					
						
							|  |  |  |     "White_Palace_05[right2]", "White_Palace_05[right2]", "White_Palace_04[top1]", "White_Palace_04[top1]", | 
					
						
							|  |  |  |     "White_Palace_19[top1]", "White_Palace_19[top1]", "White_Palace_14[right1]", "White_Palace_14[right1]", | 
					
						
							|  |  |  |     "White_Palace_03_hub[top1]", "White_Palace_03_hub[top1]", "Grubfather_2", "White_Palace_13[left3]", | 
					
						
							|  |  |  |     "White_Palace_13[left3]", "White_Palace_02[left1]", "White_Palace_02[left1]", "White_Palace_12[right1]", | 
					
						
							|  |  |  |     "White_Palace_12[right1]", "White_Palace_07[top1]", "White_Palace_07[top1]", "White_Palace_05[left1]", | 
					
						
							|  |  |  |     "White_Palace_05[left1]", "White_Palace_13[right1]", "White_Palace_13[right1]", "White_Palace_01[top1]", | 
					
						
							|  |  |  |     "White_Palace_01[top1]", | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-18 18:19:21 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-11 14:22:44 +02:00
										 |  |  | class HKWorld(World): | 
					
						
							|  |  |  |     game: str = "Hollow Knight" | 
					
						
							| 
									
										
										
										
											2021-06-26 11:18:12 -05:00
										 |  |  |     options = hollow_knight_options | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |     item_name_to_id = {name: data.id for name, data in item_table.items()} | 
					
						
							|  |  |  |     location_name_to_id = {location_name: location_id for location_id, location_name in | 
					
						
							|  |  |  |                            enumerate(locations, start=0x1000000)} | 
					
						
							| 
									
										
										
										
											2021-07-12 18:05:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-27 14:52:33 +02:00
										 |  |  |     hidden = True | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |     ranges: typing.Dict[str, typing.Tuple[int, int]] | 
					
						
							|  |  |  |     shops = {"Egg_Shop": "egg", "Grubfather": "grub", "Seer": "essence", "Salubra_(Requires_Charms)": "charm"} | 
					
						
							|  |  |  |     charm_costs: typing.List[int] | 
					
						
							|  |  |  |     data_version = 2 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     allow_white_palace = False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, world, player): | 
					
						
							|  |  |  |         super(HKWorld, self).__init__(world, player) | 
					
						
							|  |  |  |         self.created_multi_locations: typing.Dict[str, int] = Counter() | 
					
						
							|  |  |  |         self.ranges = {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def generate_early(self): | 
					
						
							|  |  |  |         world = self.world | 
					
						
							|  |  |  |         self.charm_costs = world.random_charm_costs[self.player].get_costs(world.random) | 
					
						
							|  |  |  |         world.exclude_locations[self.player].value.update(white_palace_locations) | 
					
						
							|  |  |  |         world.local_items[self.player].value.add("Mimic_Grub") | 
					
						
							|  |  |  |         for vendor, unit in self.shops.items(): | 
					
						
							|  |  |  |             mini = getattr(world, f"minimum_{unit}_price")[self.player] | 
					
						
							|  |  |  |             maxi = getattr(world, f"maximum_{unit}_price")[self.player] | 
					
						
							|  |  |  |             # if minimum > maximum, set minimum to maximum | 
					
						
							|  |  |  |             mini.value = min(mini.value, maxi.value) | 
					
						
							|  |  |  |             self.ranges[unit] = mini.value, maxi.value | 
					
						
							|  |  |  |         world.push_precollected(HKItem(starts[world.start_location[self.player].current_key], | 
					
						
							|  |  |  |                                        True, None, "Event", self.player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def create_regions(self): | 
					
						
							|  |  |  |         menu_region: Region = create_region(self.world, self.player, 'Menu') | 
					
						
							|  |  |  |         self.world.regions.append(menu_region) | 
					
						
							| 
									
										
										
										
											2021-08-27 14:52:33 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-26 11:18:12 -05:00
										 |  |  |         # Link regions | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |         for event_name in event_names: | 
					
						
							|  |  |  |             loc = HKLocation(self.player, event_name, None, menu_region) | 
					
						
							|  |  |  |             loc.place_locked_item(HKItem(event_name, | 
					
						
							|  |  |  |                                          self.allow_white_palace or event_name not in white_palace_locations, | 
					
						
							|  |  |  |                                          None, "Event", self.player)) | 
					
						
							|  |  |  |             menu_region.locations.append(loc) | 
					
						
							|  |  |  |         for entry_transition, exit_transition in connectors.items(): | 
					
						
							|  |  |  |             if exit_transition: | 
					
						
							|  |  |  |                 # if door logic fulfilled -> award vanilla target as event | 
					
						
							|  |  |  |                 loc = HKLocation(self.player, entry_transition, None, menu_region) | 
					
						
							|  |  |  |                 loc.place_locked_item(HKItem(exit_transition, | 
					
						
							|  |  |  |                                              self.allow_white_palace or exit_transition not in white_palace_locations, | 
					
						
							|  |  |  |                                              None, "Event", self.player)) | 
					
						
							|  |  |  |                 menu_region.locations.append(loc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def create_items(self): | 
					
						
							|  |  |  |         # Generate item pool and associated locations (paired in HK) | 
					
						
							|  |  |  |         pool: typing.List[HKItem] = [] | 
					
						
							|  |  |  |         geo_replace: typing.Set[str] = set() | 
					
						
							|  |  |  |         if self.world.RemoveSpellUpgrades[self.player]: | 
					
						
							|  |  |  |             geo_replace.add("Abyss_Shriek") | 
					
						
							|  |  |  |             geo_replace.add("Shade_Soul") | 
					
						
							|  |  |  |             geo_replace.add("Descending_Dark") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for option_key, option in hollow_knight_randomize_options.items(): | 
					
						
							|  |  |  |             if getattr(self.world, option_key)[self.player]: | 
					
						
							|  |  |  |                 for item_name, location_name in zip(option.items, option.locations): | 
					
						
							|  |  |  |                     if item_name in geo_replace: | 
					
						
							|  |  |  |                         item_name = "Geo_Rock-Default" | 
					
						
							|  |  |  |                     if location_name in white_palace_locations: | 
					
						
							|  |  |  |                         self.create_location(location_name).place_locked_item(self.create_item(item_name)) | 
					
						
							|  |  |  |                     else: | 
					
						
							|  |  |  |                         self.create_location(location_name) | 
					
						
							|  |  |  |                         pool.append(self.create_item(item_name)) | 
					
						
							| 
									
										
										
										
											2021-06-26 11:18:12 -05:00
										 |  |  |             else: | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |                 for item_name, location_name in zip(option.items, option.locations): | 
					
						
							|  |  |  |                     item = self.create_item(item_name) | 
					
						
							|  |  |  |                     if location_name == "Start": | 
					
						
							|  |  |  |                         self.world.push_precollected(item) | 
					
						
							|  |  |  |                     else: | 
					
						
							|  |  |  |                         self.create_location(location_name).place_locked_item(item) | 
					
						
							|  |  |  |         for i in range(self.world.egg_shop_slots[self.player].value): | 
					
						
							|  |  |  |             self.create_location("Egg_Shop") | 
					
						
							|  |  |  |             pool.append(self.create_item("Geo_Rock-Default")) | 
					
						
							|  |  |  |         if not self.allow_white_palace: | 
					
						
							|  |  |  |             loc = self.world.get_location("King_Fragment", self.player) | 
					
						
							|  |  |  |             if loc.item and loc.item.name == loc.name: | 
					
						
							|  |  |  |                 loc.item.advancement = False | 
					
						
							| 
									
										
										
										
											2021-06-26 11:18:12 -05:00
										 |  |  |         self.world.itempool += pool | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def set_rules(self): | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |         world = self.world | 
					
						
							|  |  |  |         player = self.player | 
					
						
							|  |  |  |         if world.logic[player] != 'nologic': | 
					
						
							|  |  |  |             world.completion_condition[player] = lambda state: state.has('DREAMER', player, 3) | 
					
						
							|  |  |  |         set_rules(self) | 
					
						
							| 
									
										
										
										
											2021-06-26 11:18:12 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |     def fill_slot_data(self): | 
					
						
							| 
									
										
										
										
											2021-06-26 11:18:12 -05:00
										 |  |  |         slot_data = {} | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         options = slot_data["options"] = {} | 
					
						
							| 
									
										
										
										
											2021-06-26 11:18:12 -05:00
										 |  |  |         for option_name in self.options: | 
					
						
							|  |  |  |             option = getattr(self.world, option_name)[self.player] | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |             options[option_name] = int(option.value) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # 32 bit int | 
					
						
							|  |  |  |         slot_data["seed"] = self.world.slot_seeds[self.player].randint(-2147483647, 2147483646) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for shop, unit in self.shops.items(): | 
					
						
							|  |  |  |             slot_data[f"{unit}_costs"] = { | 
					
						
							|  |  |  |                 f"{shop}_{i}": | 
					
						
							|  |  |  |                     self.world.get_location(f"{shop}_{i}", self.player).cost | 
					
						
							|  |  |  |                 for i in range(1, 1 + self.created_multi_locations[shop]) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         slot_data["notch_costs"] = self.charm_costs | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-26 11:18:12 -05:00
										 |  |  |         return slot_data | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |     def create_item(self, name: str) -> HKItem: | 
					
						
							| 
									
										
										
										
											2021-07-12 13:54:47 +02:00
										 |  |  |         item_data = item_table[name] | 
					
						
							|  |  |  |         return HKItem(name, item_data.advancement, item_data.id, item_data.type, self.player) | 
					
						
							| 
									
										
										
										
											2021-02-21 20:17:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |     def create_location(self, name: str) -> HKLocation: | 
					
						
							|  |  |  |         unit = self.shops.get(name, None) | 
					
						
							|  |  |  |         if unit: | 
					
						
							|  |  |  |             cost = self.world.random.randint(*self.ranges[unit]) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             cost = 0 | 
					
						
							|  |  |  |         if name in multi_locations: | 
					
						
							|  |  |  |             self.created_multi_locations[name] += 1 | 
					
						
							|  |  |  |             name += f"_{self.created_multi_locations[name]}" | 
					
						
							| 
									
										
										
										
											2021-07-21 18:08:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |         region = self.world.get_region("Menu", self.player) | 
					
						
							|  |  |  |         loc = HKLocation(self.player, name, self.location_name_to_id[name], region) | 
					
						
							|  |  |  |         if unit: | 
					
						
							|  |  |  |             loc.unit = unit | 
					
						
							|  |  |  |             loc.cost = cost | 
					
						
							|  |  |  |         region.locations.append(loc) | 
					
						
							|  |  |  |         return loc | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def collect(self, state, item: HKItem) -> bool: | 
					
						
							|  |  |  |         change = super(HKWorld, self).collect(state, item) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for effect_name, effect_value in item_effects.get(item.name, {}).items(): | 
					
						
							|  |  |  |             state.prog_items[effect_name, item.player] += effect_value | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return change | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def remove(self, state, item: HKItem) -> bool: | 
					
						
							|  |  |  |         change = super(HKWorld, self).remove(state, item) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for effect_name, effect_value in item_effects.get(item.name, {}).items(): | 
					
						
							|  |  |  |             if state.prog_items[effect_name, item.player] == effect_value: | 
					
						
							|  |  |  |                 del state.prog_items[effect_name, item.player] | 
					
						
							|  |  |  |             state.prog_items[effect_name, item.player] -= effect_value | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return change | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def create_region(world: MultiWorld, player: int, name: str, location_names=None, exits=None) -> Region: | 
					
						
							| 
									
										
										
										
											2022-03-18 18:19:21 +01:00
										 |  |  |     ret = Region(name, RegionType.Generic, name, player) | 
					
						
							| 
									
										
										
										
											2021-02-24 06:02:51 +01:00
										 |  |  |     ret.world = world | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |     if location_names: | 
					
						
							|  |  |  |         for location in location_names: | 
					
						
							|  |  |  |             loc_id = HKWorld.location_name_to_id.get(location, None) | 
					
						
							| 
									
										
										
										
											2021-02-24 06:02:51 +01:00
										 |  |  |             location = HKLocation(player, location, loc_id, ret) | 
					
						
							|  |  |  |             ret.locations.append(location) | 
					
						
							|  |  |  |     if exits: | 
					
						
							|  |  |  |         for exit in exits: | 
					
						
							|  |  |  |             ret.exits.append(Entrance(player, exit, ret)) | 
					
						
							|  |  |  |     return ret | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-21 20:17:24 +01:00
										 |  |  | class HKLocation(Location): | 
					
						
							|  |  |  |     game: str = "Hollow Knight" | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |     cost: int = 0 | 
					
						
							|  |  |  |     unit: typing.Optional[str] = None | 
					
						
							| 
									
										
										
										
											2021-02-21 20:17:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |     def __init__(self, player: int, name: str, code=None, parent=None): | 
					
						
							|  |  |  |         super(HKLocation, self).__init__(player, name, code if code else None, parent) | 
					
						
							| 
									
										
										
										
											2021-02-21 20:17:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-21 20:17:24 +01:00
										 |  |  | class HKItem(Item): | 
					
						
							| 
									
										
										
										
											2021-02-22 11:18:53 +01:00
										 |  |  |     game = "Hollow Knight" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 00:47:17 +01:00
										 |  |  |     def __init__(self, name, advancement, code, type, player: int = None): | 
					
						
							| 
									
										
										
										
											2022-03-18 18:19:21 +01:00
										 |  |  |         super(HKItem, self).__init__(name, advancement, code if code else None, player) | 
					
						
							| 
									
										
										
										
											2021-03-21 00:47:17 +01:00
										 |  |  |         self.type = type | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |         if name == "Mimic_Grub": | 
					
						
							|  |  |  |             self.trap = True | 
					
						
							| 
									
										
										
										
											2021-02-21 20:17:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-24 06:02:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  | class HKLogicMixin(LogicMixin): | 
					
						
							|  |  |  |     world: MultiWorld | 
					
						
							| 
									
										
										
										
											2021-02-21 20:17:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |     def _hk_notches(self, player: int, *notches: int) -> int: | 
					
						
							|  |  |  |         return sum(self.world.worlds[player].charm_costs[notch] for notch in notches) | 
					
						
							| 
									
										
										
										
											2021-07-15 13:31:33 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |     def _kh_option(self, player: int, option_name: str) -> int: | 
					
						
							|  |  |  |         if option_name == "RandomizeCharmNotches": | 
					
						
							|  |  |  |             return self.world.random_charm_costs[player] != -1 | 
					
						
							|  |  |  |         return getattr(self.world, option_name)[player].value | 
					
						
							| 
									
										
										
										
											2021-07-15 13:31:33 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |     def _kh_start(self, player, start_location: str) -> bool: | 
					
						
							|  |  |  |         return self.world.start_location[player] == start_location |