Example #1
0
 def GetLevelStaircaseRoomNumberList(self,
                                     level_num: LevelNum) -> List[RoomNum]:
     assert level_num in Range.VALID_LEVEL_NUMBERS
     offset = level_num * self.LEVEL_METADATA_OFFSET + self.STAIRCASE_LIST_OFFSET
     tbr: List[RoomNum] = []
     for offset in range(0, 9):
         tbr.append(RoomNum(self.level_metadata[offset]))
     return tbr
Example #2
0
    def __init__(self, rom_data: Optional[List[int]] = None) -> None:
        if not rom_data:
            rom_data = [0x26, 0x26, 0x00, 0x00, 0x17, 0x00]
        if rom_data[4] & 0x1F == 0x03:
            stuff_not_to_change = rom_data[4] & 0xE0
            rom_data[4] = stuff_not_to_change + 0x0E
        self.rom_data = rom_data

        self.marked_as_visited = False
        # -1 is used as a sentinal value indicating a lack of stairway room
        self.stairs_destination = RoomNum(-1)
Example #3
0
    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)
Example #4
0
 def GetLevelStartRoomNumber(self, level_num: LevelNum) -> RoomNum:
     assert level_num in Range.VALID_LEVEL_NUMBERS
     return RoomNum(
         self.level_metadata[level_num * self.LEVEL_METADATA_OFFSET +
                             self.START_ROOM_OFFSET])
Example #5
0
 def ClearStairsDestination(self) -> None:
     self.stairs_destination = RoomNum(-1)
Example #6
0
 def HasStairs(self) -> bool:
     # -1 is used as a sentinal value indicating a lack of stairs room
     return self.stairs_destination != RoomNum(-1)
Example #7
0
 def GetStairwayRoomRightExit(self) -> RoomNum:
     assert self.IsStairwayRoom()
     return RoomNum(self._ReadRomBits(1, 0x7F))
Example #8
0
    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)
Example #9
0
 def GetRoomNum(self) -> RoomNum:
     assert self.IsLevelRoom()
     return RoomNum(self.sub_id)