def _ReadItemsAndLocationsRecursively( self, level_num: LevelNum, room_num: RoomNum, entrance_direction: Direction) -> None: print("Reading room %x" % room_num) if room_num not in Range.VALID_ROOM_NUMBERS: return # No escaping back into the overworld! :) room = self.data_table.GetRoom(level_num, room_num) if room.IsMarkedAsVisited(): return room.MarkAsVisited() item = room.GetItem() if item.IsMajorItem() or item == Item.TRIFORCE: self.item_shuffler.AddLocationAndItem( Location.LevelRoom(level_num, room_num), item) # Staircase cases (bad pun intended) if room.IsItemStaircase(): return # Dead end, no need to traverse further. if room.IsTransportStairway(): for upstairs_room in [ room.GetStairwayRoomLeftExit(), room.GetStairwayRoomRightExit() ]: self._ReadItemsAndLocationsRecursively(level_num, upstairs_room, Direction.STAIRCASE) return # Regular (non-staircase) room case. Check all four cardinal directions, plus "down". for direction in (Direction.WEST, Direction.NORTH, Direction.EAST, Direction.SOUTH): if direction == entrance_direction: continue if room.GetWallType(direction) != WallType.SOLID_WALL: self._ReadItemsAndLocationsRecursively( level_num, RoomNum(room_num + direction), direction.Reverse()) if room.HasStairs(): self._ReadItemsAndLocationsRecursively(level_num, room.GetStairsDestination(), Direction.STAIRCASE)
def _RecursivelyTraverseLevel(self, level_num: LevelNum, room_num: RoomNum, entry_direction: Direction) -> None: log.debug("Visiting level %d room %x" % (level_num, room_num)) if not room_num in Range.VALID_ROOM_NUMBERS: return room = self.data_table.GetRoom(level_num, room_num) if room.IsMarkedAsVisited(): return room.MarkAsVisited() current_location = Location.LevelRoom(level_num, room_num) # An item staircase room is a dead-end, so no need to recurse after picking up the item. if room.IsItemStaircase(): self.inventory.AddItem(room.GetItem(), current_location) return # For a transport staircase, we don't know whether we came in through the left or right. # So try to leave both ways; the one that we came from will have already been marked as # visited and just return. if room.IsTransportStaircase(): for room_num_to_visit in [ room.GetStairwayRoomLeftExit(), room.GetStairwayRoomRightExit() ]: self._RecursivelyTraverseLevel(level_num, room_num_to_visit, Direction.STAIRCASE) return if self._CanGetRoomItem(entry_direction, room) and room.HasItem(): self.inventory.AddItem(room.GetItem(), current_location) if room.GetEnemy() == Enemy.THE_BEAST: if self.inventory.HasBowSilverArrowsAndSword( ) and self.inventory.Has(Item.LADDER): # TODO: Doesn't address the case where ladder isn't obtained log.info("Got the triforce of power!") self.inventory.AddItem(Item.TRIFORCE_OF_POWER, current_location) if room.GetEnemy() == Enemy.THE_KIDNAPPED: log.info("Found the kidnapped") if self.inventory.Has(Item.TRIFORCE_OF_POWER): log.info("And rescued the kidnapped! :)") self.inventory.AddItem(Item.RESCUED_KIDNAPPED_VIRTUAL_ITEM, current_location) for direction in (Direction.WEST, Direction.NORTH, Direction.EAST, Direction.SOUTH): if direction == entry_direction: continue if not self.inventory.HasReusableWeapon() and room.GetEnemy( ).HasHardCombatEnemies(): continue if self._CanMove(entry_direction, direction, level_num, room_num, room): self._RecursivelyTraverseLevel(level_num, RoomNum(room_num + direction), direction.Reverse()) if room.GetRoomType().HasUnobstructedStairs() or ( room.HasStairs() and self._CanDefeatEnemies(room)): if entry_direction != Direction.STAIRCASE: self._RecursivelyTraverseLevel(level_num, room.GetStairsDestination(), Direction.STAIRCASE)