| 
									
										
										
										
											2023-03-05 07:31:31 -05:00
										 |  |  | from typing import TYPE_CHECKING | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-24 19:58:54 -04:00
										 |  |  | from worlds.generic.Rules import add_rule | 
					
						
							| 
									
										
										
										
											2024-03-03 11:59:31 -05:00
										 |  |  | from .Locations import food_locations, shop_locations, gleeok_locations | 
					
						
							| 
									
										
										
										
											2023-03-05 07:31:31 -05:00
										 |  |  | from .ItemPool import dangerous_weapon_locations | 
					
						
							| 
									
										
										
										
											2023-03-08 05:22:14 -05:00
										 |  |  | from .Options import StartingPosition | 
					
						
							| 
									
										
										
										
											2023-03-05 07:31:31 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | if TYPE_CHECKING: | 
					
						
							|  |  |  |     from . import TLoZWorld | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def set_rules(tloz_world: "TLoZWorld"): | 
					
						
							|  |  |  |     player = tloz_world.player | 
					
						
							|  |  |  |     world = tloz_world.multiworld | 
					
						
							| 
									
										
										
										
											2024-01-14 22:47:32 -05:00
										 |  |  |     options = tloz_world.options | 
					
						
							| 
									
										
										
										
											2023-03-05 07:31:31 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Boss events for a nicer spoiler log play through | 
					
						
							|  |  |  |     for level in range(1, 9): | 
					
						
							|  |  |  |         boss = world.get_location(f"Level {level} Boss", player) | 
					
						
							|  |  |  |         boss_event = world.get_location(f"Level {level} Boss Status", player) | 
					
						
							|  |  |  |         status = tloz_world.create_event(f"Boss {level} Defeated") | 
					
						
							|  |  |  |         boss_event.place_locked_item(status) | 
					
						
							|  |  |  |         add_rule(boss_event, lambda state, b=boss: state.can_reach(b, "Location", player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # No dungeons without weapons except for the dangerous weapon locations if we're dangerous, no unsafe dungeons | 
					
						
							|  |  |  |     for i, level in enumerate(tloz_world.levels[1:10]): | 
					
						
							|  |  |  |         for location in level.locations: | 
					
						
							| 
									
										
										
										
											2024-01-14 22:47:32 -05:00
										 |  |  |             if options.StartingPosition < StartingPosition.option_dangerous \ | 
					
						
							| 
									
										
										
										
											2023-03-08 05:22:14 -05:00
										 |  |  |                     or location.name not in dangerous_weapon_locations: | 
					
						
							| 
									
										
										
										
											2023-03-05 07:31:31 -05:00
										 |  |  |                 add_rule(world.get_location(location.name, player), | 
					
						
							|  |  |  |                          lambda state: state.has_group("weapons", player)) | 
					
						
							| 
									
										
										
										
											2024-05-02 17:49:39 -04:00
										 |  |  |             #  This part of the loop sets up an expected amount of defense needed for each dungeon | 
					
						
							| 
									
										
										
										
											2023-03-05 07:31:31 -05:00
										 |  |  |             if i > 0:  # Don't need an extra heart for Level 1 | 
					
						
							|  |  |  |                 add_rule(world.get_location(location.name, player), | 
					
						
							|  |  |  |                          lambda state, hearts=i: state.has("Heart Container", player, hearts) or | 
					
						
							|  |  |  |                                        (state.has("Blue Ring", player) and | 
					
						
							|  |  |  |                                         state.has("Heart Container", player, int(hearts / 2))) or | 
					
						
							|  |  |  |                                        (state.has("Red Ring", player) and | 
					
						
							| 
									
										
										
										
											2023-03-30 09:29:06 -04:00
										 |  |  |                                         state.has("Heart Container", player, int(hearts / 4)))) | 
					
						
							|  |  |  |             if "Pols Voice" in location.name:  # This enemy needs specific weapons | 
					
						
							|  |  |  |                 add_rule(world.get_location(location.name, player), | 
					
						
							|  |  |  |                          lambda state: state.has_group("swords", player) or state.has("Bow", player)) | 
					
						
							| 
									
										
										
										
											2023-03-05 07:31:31 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # No requiring anything in a shop until we can farm for money | 
					
						
							|  |  |  |     for location in shop_locations: | 
					
						
							|  |  |  |         add_rule(world.get_location(location, player), | 
					
						
							|  |  |  |                  lambda state: state.has_group("weapons", player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Everything from 4 on up has dark rooms | 
					
						
							|  |  |  |     for level in tloz_world.levels[4:]: | 
					
						
							|  |  |  |         for location in level.locations: | 
					
						
							|  |  |  |             add_rule(world.get_location(location.name, player), | 
					
						
							|  |  |  |                      lambda state: state.has_group("candles", player) | 
					
						
							| 
									
										
										
										
											2024-04-27 19:49:59 -04:00
										 |  |  |                                    or (state.has("Magical Rod", player) and state.has("Book of Magic", player))) | 
					
						
							| 
									
										
										
										
											2023-03-05 07:31:31 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Everything from 5 on up has gaps | 
					
						
							|  |  |  |     for level in tloz_world.levels[5:]: | 
					
						
							|  |  |  |         for location in level.locations: | 
					
						
							|  |  |  |             add_rule(world.get_location(location.name, player), | 
					
						
							|  |  |  |                      lambda state: state.has("Stepladder", player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     add_rule(world.get_location("Level 5 Boss", player), | 
					
						
							|  |  |  |              lambda state: state.has("Recorder", player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     add_rule(world.get_location("Level 6 Boss", player), | 
					
						
							|  |  |  |              lambda state: state.has("Bow", player) and state.has_group("arrows", player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     add_rule(world.get_location("Level 7 Item (Red Candle)", player), | 
					
						
							|  |  |  |              lambda state: state.has("Recorder", player)) | 
					
						
							|  |  |  |     add_rule(world.get_location("Level 7 Boss", player), | 
					
						
							|  |  |  |              lambda state: state.has("Recorder", player)) | 
					
						
							| 
									
										
										
										
											2024-01-14 22:47:32 -05:00
										 |  |  |     if options.ExpandedPool: | 
					
						
							| 
									
										
										
										
											2023-03-05 07:31:31 -05:00
										 |  |  |         add_rule(world.get_location("Level 7 Key Drop (Stalfos)", player), | 
					
						
							|  |  |  |                  lambda state: state.has("Recorder", player)) | 
					
						
							|  |  |  |         add_rule(world.get_location("Level 7 Bomb Drop (Digdogger)", player), | 
					
						
							|  |  |  |                  lambda state: state.has("Recorder", player)) | 
					
						
							|  |  |  |         add_rule(world.get_location("Level 7 Rupee Drop (Dodongos)", player), | 
					
						
							|  |  |  |                  lambda state: state.has("Recorder", player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for location in food_locations: | 
					
						
							| 
									
										
										
										
											2024-01-14 22:47:32 -05:00
										 |  |  |         if options.ExpandedPool or "Drop" not in location: | 
					
						
							| 
									
										
										
										
											2023-03-05 07:31:31 -05:00
										 |  |  |             add_rule(world.get_location(location, player), | 
					
						
							|  |  |  |                      lambda state: state.has("Food", player)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-03 11:59:31 -05:00
										 |  |  |     for location in gleeok_locations: | 
					
						
							|  |  |  |         add_rule(world.get_location(location, player), | 
					
						
							|  |  |  |                  lambda state: state.has_group("swords", player) or state.has("Magical Rod", player)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-27 19:49:59 -04:00
										 |  |  |     # Candle access for Level 8 | 
					
						
							|  |  |  |     for location in tloz_world.levels[8].locations: | 
					
						
							|  |  |  |         add_rule(world.get_location(location.name, player), | 
					
						
							|  |  |  |             lambda state: state.has_group("candles", player)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-05 07:31:31 -05:00
										 |  |  |     add_rule(world.get_location("Level 8 Item (Magical Key)", player), | 
					
						
							|  |  |  |              lambda state: state.has("Bow", player) and state.has_group("arrows", player)) | 
					
						
							| 
									
										
										
										
											2024-01-14 22:47:32 -05:00
										 |  |  |     if options.ExpandedPool: | 
					
						
							| 
									
										
										
										
											2023-03-05 07:31:31 -05:00
										 |  |  |         add_rule(world.get_location("Level 8 Bomb Drop (Darknuts North)", player), | 
					
						
							|  |  |  |                  lambda state: state.has("Bow", player) and state.has_group("arrows", player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for location in tloz_world.levels[9].locations: | 
					
						
							|  |  |  |         add_rule(world.get_location(location.name, player), | 
					
						
							|  |  |  |                  lambda state: state.has("Triforce Fragment", player, 8) and | 
					
						
							|  |  |  |                                state.has_group("swords", player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Yes we are looping this range again for Triforce locations. No I can't add it to the boss event loop | 
					
						
							|  |  |  |     for level in range(1, 9): | 
					
						
							|  |  |  |         add_rule(world.get_location(f"Level {level} Triforce", player), | 
					
						
							|  |  |  |                  lambda state, l=level: state.has(f"Boss {l} Defeated", player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Sword, raft, and ladder spots | 
					
						
							|  |  |  |     add_rule(world.get_location("White Sword Pond", player), | 
					
						
							|  |  |  |              lambda state: state.has("Heart Container", player, 2)) | 
					
						
							|  |  |  |     add_rule(world.get_location("Magical Sword Grave", player), | 
					
						
							|  |  |  |              lambda state: state.has("Heart Container", player, 9)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     stepladder_locations = ["Ocean Heart Container", "Level 4 Triforce", "Level 4 Boss", "Level 4 Map"] | 
					
						
							|  |  |  |     stepladder_locations_expanded = ["Level 4 Key Drop (Keese North)"] | 
					
						
							|  |  |  |     for location in stepladder_locations: | 
					
						
							|  |  |  |         add_rule(world.get_location(location, player), | 
					
						
							|  |  |  |                  lambda state: state.has("Stepladder", player)) | 
					
						
							| 
									
										
										
										
											2024-01-14 22:47:32 -05:00
										 |  |  |     if options.ExpandedPool: | 
					
						
							| 
									
										
										
										
											2023-03-05 07:31:31 -05:00
										 |  |  |         for location in stepladder_locations_expanded: | 
					
						
							|  |  |  |             add_rule(world.get_location(location, player), | 
					
						
							|  |  |  |                      lambda state: state.has("Stepladder", player)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-08 05:22:14 -05:00
										 |  |  |     # Don't allow Take Any Items until we can actually get in one | 
					
						
							| 
									
										
										
										
											2024-01-14 22:47:32 -05:00
										 |  |  |     if options.ExpandedPool: | 
					
						
							| 
									
										
										
										
											2023-03-08 05:22:14 -05:00
										 |  |  |         add_rule(world.get_location("Take Any Item Left", player), | 
					
						
							|  |  |  |                  lambda state: state.has_group("candles", player) or | 
					
						
							|  |  |  |                                state.has("Raft", player)) | 
					
						
							|  |  |  |         add_rule(world.get_location("Take Any Item Middle", player), | 
					
						
							|  |  |  |                  lambda state: state.has_group("candles", player) or | 
					
						
							|  |  |  |                                state.has("Raft", player)) | 
					
						
							|  |  |  |         add_rule(world.get_location("Take Any Item Right", player), | 
					
						
							|  |  |  |                  lambda state: state.has_group("candles", player) or | 
					
						
							|  |  |  |                                state.has("Raft", player)) | 
					
						
							| 
									
										
										
										
											2023-03-05 07:31:31 -05:00
										 |  |  |     for location in tloz_world.levels[4].locations: | 
					
						
							|  |  |  |         add_rule(world.get_location(location.name, player), | 
					
						
							|  |  |  |                  lambda state: state.has("Raft", player) or state.has("Recorder", player)) | 
					
						
							|  |  |  |     for location in tloz_world.levels[7].locations: | 
					
						
							|  |  |  |         add_rule(world.get_location(location.name, player), | 
					
						
							|  |  |  |                  lambda state: state.has("Recorder", player)) | 
					
						
							|  |  |  |     for location in tloz_world.levels[8].locations: | 
					
						
							|  |  |  |         add_rule(world.get_location(location.name, player), | 
					
						
							|  |  |  |                  lambda state: state.has("Bow", player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     add_rule(world.get_location("Potion Shop Item Left", player), | 
					
						
							|  |  |  |              lambda state: state.has("Letter", player)) | 
					
						
							|  |  |  |     add_rule(world.get_location("Potion Shop Item Middle", player), | 
					
						
							|  |  |  |              lambda state: state.has("Letter", player)) | 
					
						
							|  |  |  |     add_rule(world.get_location("Potion Shop Item Right", player), | 
					
						
							|  |  |  |              lambda state: state.has("Letter", player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     add_rule(world.get_location("Shield Shop Item Left", player), | 
					
						
							|  |  |  |              lambda state: state.has_group("candles", player) or | 
					
						
							|  |  |  |                            state.has("Bomb", player)) | 
					
						
							|  |  |  |     add_rule(world.get_location("Shield Shop Item Middle", player), | 
					
						
							|  |  |  |              lambda state: state.has_group("candles", player) or | 
					
						
							|  |  |  |                            state.has("Bomb", player)) | 
					
						
							|  |  |  |     add_rule(world.get_location("Shield Shop Item Right", player), | 
					
						
							|  |  |  |              lambda state: state.has_group("candles", player) or | 
					
						
							|  |  |  |                            state.has("Bomb", player)) |