| 
									
										
										
										
											2024-08-16 19:57:04 +01:00
										 |  |  | from collections import Counter | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-05 07:31:31 -05:00
										 |  |  | from BaseClasses import ItemClassification | 
					
						
							|  |  |  | from .Locations import level_locations, all_level_locations, standard_level_locations, shop_locations | 
					
						
							| 
									
										
										
										
											2023-03-08 05:22:14 -05:00
										 |  |  | from .Options import TriforceLocations, StartingPosition | 
					
						
							| 
									
										
										
										
											2023-03-05 07:31:31 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | # Swords are in starting_weapons | 
					
						
							|  |  |  | overworld_items = { | 
					
						
							|  |  |  |     "Letter": 1, | 
					
						
							|  |  |  |     "Power Bracelet": 1, | 
					
						
							|  |  |  |     "Heart Container": 1, | 
					
						
							|  |  |  |     "Sword": 1 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Bomb, Arrow, 1 Small Key and Red Water of Life are in guaranteed_shop_items | 
					
						
							|  |  |  | shop_items = { | 
					
						
							|  |  |  |     "Magical Shield": 3, | 
					
						
							|  |  |  |     "Food": 2, | 
					
						
							|  |  |  |     "Small Key": 1, | 
					
						
							|  |  |  |     "Candle": 1, | 
					
						
							|  |  |  |     "Recovery Heart": 1, | 
					
						
							|  |  |  |     "Blue Ring": 1, | 
					
						
							|  |  |  |     "Water of Life (Blue)": 1 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Magical Rod and Red Candle are in starting_weapons, Triforce Fragments are added in its section of get_pool_core | 
					
						
							|  |  |  | major_dungeon_items = { | 
					
						
							|  |  |  |     "Heart Container": 8, | 
					
						
							|  |  |  |     "Bow": 1, | 
					
						
							|  |  |  |     "Boomerang": 1, | 
					
						
							|  |  |  |     "Magical Boomerang": 1, | 
					
						
							|  |  |  |     "Raft": 1, | 
					
						
							|  |  |  |     "Stepladder": 1, | 
					
						
							|  |  |  |     "Recorder": 1, | 
					
						
							|  |  |  |     "Magical Key": 1, | 
					
						
							|  |  |  |     "Book of Magic": 1, | 
					
						
							|  |  |  |     "Silver Arrow": 1, | 
					
						
							|  |  |  |     "Red Ring": 1 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | minor_dungeon_items = { | 
					
						
							|  |  |  |     "Bomb": 23, | 
					
						
							|  |  |  |     "Small Key": 45, | 
					
						
							|  |  |  |     "Five Rupees": 17 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | take_any_items = { | 
					
						
							|  |  |  |     "Heart Container": 4 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Map/Compasses: 18 | 
					
						
							|  |  |  | # Reasoning: Adding some variety to the vanilla game. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | map_compass_replacements = { | 
					
						
							|  |  |  |     "Fairy": 6, | 
					
						
							|  |  |  |     "Clock": 3, | 
					
						
							|  |  |  |     "Water of Life (Red)": 1, | 
					
						
							|  |  |  |     "Water of Life (Blue)": 2, | 
					
						
							|  |  |  |     "Bomb": 2, | 
					
						
							|  |  |  |     "Small Key": 2, | 
					
						
							|  |  |  |     "Five Rupees": 2 | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2024-08-16 19:57:04 +01:00
										 |  |  | basic_pool = Counter() | 
					
						
							|  |  |  | basic_pool.update(overworld_items) | 
					
						
							|  |  |  | basic_pool.update(shop_items) | 
					
						
							|  |  |  | basic_pool.update(major_dungeon_items) | 
					
						
							|  |  |  | basic_pool.update(map_compass_replacements) | 
					
						
							| 
									
										
										
										
											2023-03-05 07:31:31 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | starting_weapons = ["Sword", "White Sword", "Magical Sword", "Magical Rod", "Red Candle"] | 
					
						
							|  |  |  | guaranteed_shop_items = ["Small Key", "Bomb", "Water of Life (Red)", "Arrow"] | 
					
						
							|  |  |  | starting_weapon_locations = ["Starting Sword Cave", "Letter Cave", "Armos Knights"] | 
					
						
							|  |  |  | dangerous_weapon_locations = [ | 
					
						
							|  |  |  |     "Level 1 Compass", "Level 2 Bomb Drop (Keese)", "Level 3 Key Drop (Zols Entrance)", "Level 3 Compass"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def generate_itempool(tlozworld): | 
					
						
							|  |  |  |     (pool, placed_items) = get_pool_core(tlozworld) | 
					
						
							|  |  |  |     tlozworld.multiworld.itempool.extend([tlozworld.multiworld.create_item(item, tlozworld.player) for item in pool]) | 
					
						
							|  |  |  |     for (location_name, item) in placed_items.items(): | 
					
						
							|  |  |  |         location = tlozworld.multiworld.get_location(location_name, tlozworld.player) | 
					
						
							|  |  |  |         location.place_locked_item(tlozworld.multiworld.create_item(item, tlozworld.player)) | 
					
						
							|  |  |  |         if item == "Bomb": | 
					
						
							|  |  |  |             location.item.classification = ItemClassification.progression | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def get_pool_core(world): | 
					
						
							| 
									
										
										
										
											2024-07-24 08:00:16 -04:00
										 |  |  |     random = world.random | 
					
						
							| 
									
										
										
										
											2023-03-05 07:31:31 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     pool = [] | 
					
						
							|  |  |  |     placed_items = {} | 
					
						
							|  |  |  |     minor_items = dict(minor_dungeon_items) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Guaranteed Shop Items | 
					
						
							|  |  |  |     reserved_store_slots = random.sample(shop_locations[0:9], 4) | 
					
						
							|  |  |  |     for location, item in zip(reserved_store_slots, guaranteed_shop_items): | 
					
						
							|  |  |  |         placed_items[location] = item | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Starting Weapon | 
					
						
							| 
									
										
										
										
											2023-05-08 16:36:35 -04:00
										 |  |  |     start_weapon_locations = starting_weapon_locations.copy() | 
					
						
							| 
									
										
										
										
											2023-12-28 08:17:23 -05:00
										 |  |  |     final_starting_weapons = [weapon for weapon in starting_weapons | 
					
						
							| 
									
										
										
										
											2024-01-14 22:47:32 -05:00
										 |  |  |                               if weapon not in world.options.non_local_items] | 
					
						
							| 
									
										
										
										
											2023-12-28 08:17:23 -05:00
										 |  |  |     if not final_starting_weapons: | 
					
						
							|  |  |  |         final_starting_weapons = starting_weapons | 
					
						
							|  |  |  |     starting_weapon = random.choice(final_starting_weapons) | 
					
						
							| 
									
										
										
										
											2024-01-14 22:47:32 -05:00
										 |  |  |     if world.options.StartingPosition == StartingPosition.option_safe: | 
					
						
							| 
									
										
										
										
											2023-05-08 16:36:35 -04:00
										 |  |  |         placed_items[start_weapon_locations[0]] = starting_weapon | 
					
						
							| 
									
										
										
										
											2024-01-14 22:47:32 -05:00
										 |  |  |     elif world.options.StartingPosition in \ | 
					
						
							| 
									
										
										
										
											2023-03-08 05:22:14 -05:00
										 |  |  |             [StartingPosition.option_unsafe, StartingPosition.option_dangerous]: | 
					
						
							| 
									
										
										
										
											2024-01-14 22:47:32 -05:00
										 |  |  |         if world.options.StartingPosition == StartingPosition.option_dangerous: | 
					
						
							| 
									
										
										
										
											2023-03-05 07:31:31 -05:00
										 |  |  |             for location in dangerous_weapon_locations: | 
					
						
							| 
									
										
										
										
											2024-01-14 22:47:32 -05:00
										 |  |  |                 if world.options.ExpandedPool or "Drop" not in location: | 
					
						
							| 
									
										
										
										
											2023-05-08 16:36:35 -04:00
										 |  |  |                     start_weapon_locations.append(location) | 
					
						
							|  |  |  |         placed_items[random.choice(start_weapon_locations)] = starting_weapon | 
					
						
							| 
									
										
										
										
											2023-03-05 07:31:31 -05:00
										 |  |  |     else: | 
					
						
							|  |  |  |         pool.append(starting_weapon) | 
					
						
							|  |  |  |     for other_weapons in starting_weapons: | 
					
						
							|  |  |  |         if other_weapons != starting_weapon: | 
					
						
							|  |  |  |             pool.append(other_weapons) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Triforce Fragments | 
					
						
							|  |  |  |     fragment = "Triforce Fragment" | 
					
						
							| 
									
										
										
										
											2024-01-14 22:47:32 -05:00
										 |  |  |     if world.options.ExpandedPool: | 
					
						
							| 
									
										
										
										
											2023-03-05 07:31:31 -05:00
										 |  |  |         possible_level_locations = [location for location in all_level_locations | 
					
						
							|  |  |  |                                     if location not in level_locations[8]] | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         possible_level_locations = [location for location in standard_level_locations | 
					
						
							|  |  |  |                                     if location not in level_locations[8]] | 
					
						
							| 
									
										
										
										
											2023-12-09 22:23:40 -05:00
										 |  |  |     for location in placed_items.keys(): | 
					
						
							|  |  |  |         if location in possible_level_locations: | 
					
						
							|  |  |  |             possible_level_locations.remove(location) | 
					
						
							| 
									
										
										
										
											2023-03-05 07:31:31 -05:00
										 |  |  |     for level in range(1, 9): | 
					
						
							| 
									
										
										
										
											2024-01-14 22:47:32 -05:00
										 |  |  |         if world.options.TriforceLocations == TriforceLocations.option_vanilla: | 
					
						
							| 
									
										
										
										
											2023-03-05 07:31:31 -05:00
										 |  |  |             placed_items[f"Level {level} Triforce"] = fragment | 
					
						
							| 
									
										
										
										
											2024-01-14 22:47:32 -05:00
										 |  |  |         elif world.options.TriforceLocations == TriforceLocations.option_dungeons: | 
					
						
							| 
									
										
										
										
											2023-03-05 07:31:31 -05:00
										 |  |  |             placed_items[possible_level_locations.pop(random.randint(0, len(possible_level_locations) - 1))] = fragment | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             pool.append(fragment) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Finish Pool | 
					
						
							|  |  |  |     final_pool = basic_pool | 
					
						
							| 
									
										
										
										
											2024-01-14 22:47:32 -05:00
										 |  |  |     if world.options.ExpandedPool: | 
					
						
							| 
									
										
										
										
											2024-08-16 19:57:04 +01:00
										 |  |  |         final_pool = Counter() | 
					
						
							|  |  |  |         final_pool.update(basic_pool) | 
					
						
							|  |  |  |         final_pool.update(minor_items) | 
					
						
							|  |  |  |         final_pool.update(take_any_items) | 
					
						
							| 
									
										
										
										
											2023-03-05 07:31:31 -05:00
										 |  |  |         final_pool["Five Rupees"] -= 1 | 
					
						
							|  |  |  |     for item in final_pool.keys(): | 
					
						
							|  |  |  |         for i in range(0, final_pool[item]): | 
					
						
							|  |  |  |             pool.append(item) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return pool, placed_items |