Exemple #1
0
class ItemRandomizer():
    def __init__(self, data_table: DataTable, settings: Settings) -> None:
        self.data_table = data_table
        self.settings = settings
        self.item_shuffler = ItemShuffler(settings)

    WOOD_SWORD_LOCATION = Location.CavePosition(CaveType.WOOD_SWORD_CAVE, 2)
    #  TAKE_ANY_HEART_LOCATION = Location.CavePosition(1, 3)
    WHITE_SWORD_LOCATION = Location.CavePosition(CaveType.WHITE_SWORD_CAVE, 2)
    MAGICAL_SWORD_LOCATION = Location.CavePosition(CaveType.MAGICAL_SWORD_CAVE,
                                                   2)
    LETTER_LOCATION = Location.CavePosition(CaveType.LETTER_CAVE, 2)
    #  BLUE_POTION_LOCATION = Location.CavePosition(CaveType.POTION_SHOP, 1)
    #  SHIELD_LOCATION_1 = Location.CavePosition(CaveType.SHOP_A, 1)
    WOODEN_ARROWS_LOCATION = Location.CavePosition(CaveType.SHOP_A, 3)
    #  SHIELD_LOCATION_2 = Location.CavePosition(CaveType.SHOP_B, 1)
    BLUE_CANDLE_LOCATION = Location.CavePosition(CaveType.SHOP_B, 3)
    #  SHIELD_LOCATION_3 = Location.CavePosition(CaveType.SHOP_C, 1)
    #  BAIT_LOCATION_1 = Location.CavePosition(CaveType.SHOP_C, 2)
    BLUE_RING_LOCATION = Location.CavePosition(CaveType.SHOP_D, 2)
    #  BAIT_LOCATION_2 = Location.CavePosition(CaveType.SHOP_D, 3)
    ARMOS_ITEM_LOCATION = Location.CavePosition(
        CaveType.ARMOS_ITEM_VIRTUAL_CAVE, 2)
    COAST_ITEM_LOCATION = Location.CavePosition(
        CaveType.COAST_ITEM_VIRTUAL_CAVE, 2)

    def ResetState(self) -> None:
        self.item_shuffler.ResetState()

    def Randomize(self) -> None:
        self.ResetState()
        self.ReadItemsAndLocationsFromTable()
        self.ShuffleItems()
        self.WriteItemsAndLocationsToTable()

    def ReadItemsAndLocationsFromTable(self) -> None:
        for level_num in Range.VALID_LEVEL_NUMBERS:
            self._ReadItemsAndLocationsForUndergroundLevel(level_num)
        for location in self._GetOverworldItemLocationsToShuffle():
            item_num = self.data_table.GetCaveItem(location)
            self.item_shuffler.AddLocationAndItem(location, item_num)
#    self.item_shuffler.AddLocationAndItem(self.BAIT_LOCATION_1, Item.BAIT)
#      self.item_shuffler.AddLocationAndItem(self.BAIT_LOCATION_2, Item.HEART_CONTAINER)
#    self.item_shuffler.AddLocationAndItem(self.SHIELD_LOCATION_1, Item.MAGICAL_SHIELD)

#      self.item_shuffler.AddLocationAndItem(self.SHIELD_LOCATION_2, Item.HEART_CONTAINER)
#      self.item_shuffler.AddLocationAndItem(self.SHIELD_LOCATION_3, Item.HEART_CONTAINER)
#      self.item_shuffler.AddLocationAndItem(self.TAKE_ANY_HEART_LOCATION, Item.HEART_CONTAINER)

    def _GetOverworldItemLocationsToShuffle(self) -> List[Location]:
        items: List[Location] = []
        if self.settings.shuffle_white_sword:
            items.append(self.WHITE_SWORD_LOCATION)
        if self.settings.shuffle_magical_sword:
            items.append(self.MAGICAL_SWORD_LOCATION)
        if self.settings.shuffle_coast_item:
            items.append(self.COAST_ITEM_LOCATION)
        if self.settings.shuffle_armos_item:
            items.append(self.ARMOS_ITEM_LOCATION)
        if self.settings.shuffle_letter:
            items.append(self.LETTER_LOCATION)
        if self.settings.shuffle_shop_items:
            items.extend([
                self.WOODEN_ARROWS_LOCATION, self.BLUE_CANDLE_LOCATION,
                self.BLUE_RING_LOCATION
            ])


#      if not self.settings.shuffle_take_any_hearts_shields_and_bait:
#        items.extend([self.BAIT_LOCATION_1, self.BAIT_LOCATION_2])
        return items

    def _ReadItemsAndLocationsForUndergroundLevel(self,
                                                  level_num: LevelNum) -> None:
        #logging.debug("Reading staircase room data for level %d " % level_num)
        #for staircase_room_num in self.data_table.GetLevelStaircaseRoomNumberList(level_num):
        print("level %d" % level_num)
        level_start_room_num = self.data_table.GetLevelStartRoomNumber(
            level_num)
        level_entrance_direction = self.data_table.GetLevelEntranceDirection(
            level_num)
        print("Traversing level %d.  Start room is %x. Dir is %s " %
              (level_num, level_start_room_num, level_entrance_direction))
        self._ReadItemsAndLocationsRecursively(level_num, level_start_room_num,
                                               level_entrance_direction)

    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 ShuffleItems(self) -> None:
        self.item_shuffler.ShuffleItems()

    def WriteItemsAndLocationsToTable(self) -> None:
        for (location,
             item_num) in self.item_shuffler.GetAllLocationAndItemData():
            if location.IsLevelRoom():
                self.data_table.SetRoomItem(item_num, location)
                #if item_num == Item.TRIFORCE:
                #  self.data_table.UpdateTriforceLocation(location)
            elif location.IsCavePosition():
                self.data_table.SetCaveItem(item_num, location)