Find tuple within tuple as a dictionary key

Viewed 37

For a dungeon crawler, I have multiple game levels that can be navigated by using a 2d list as a grid. The dungeons are all unique objects with many attributes, including tuples representing interactive event locations.

    def __init__(self):
        super().__init__()
        self.name = "The Catacombs"
        self.level = 1
        self.throne = (2, 3)
        self.fountain = (3, 3)
        self.teleporter = (4, 3)
        self.pit = (2, 4)
        ....

The next part of the code exists as a player class function. The player's coordinates are stored as a tuple. If the player's coordinates exist as a key in a dictionary, a corresponding function is called..

def event_logic(self):
    self.coordinates = (self.x, self.y)
    event_dict = {self.dungeon.throne: self.throne_event,
                  self.dungeon.fountain: self.fountain_event,
                  self.dungeon.teleporter: self.teleporter_event,
                  self.dungeon.pit: self.pit_event

                      }

        if self.coordinates in event_dict.keys():
            event_function = (event_dict[self.coordinates])
            return event_function()

The problem is that this only allows me to have one such event per level; I am using one tuple for each key. I want to have a few pits to fall into and a few thrones to sit on or pry gems from. So, after realizing that lists cannot be used as keys, I tried using a tuple of tuples, like, self.throne = ((2,3), (18,4)....) to allow me to have multiple events throughout, but that does not work, because the player's coordinates do not exactly match the tuple of tuples. I need a way to determine if 1 tuple exists within multiple tuples within the dictionary keys to call the corresponding function. If this is not possible, I need an alternative way..

2 Answers

Using dictionary keys like this defeats the quick access purpose of a dictionary.

You'd be better having a dictionary of all events based on co-ordinates allowing you to easily look up multiple events e.g.:

self.locations = {}
self.location[(2, 3)] = self.throne_event
self.location[(2, 6)] = self.teleporter_event
self.location[(3, 5)] = self.teleporter_event


if self.coordinates in self.locations():
    location_event = self.locations.get(self.coordinates)

This limits you to one event for location. To allow multiple, store a list at each co-ordinate:

location_events = [
    self.throne_event,
    self.fountain_event
]
self.locations[(2, 3)] = location_events

Then to action the player's coordinates:

events_at_coordinate = self.locations.get(self.coordinates)
for event in events_at_coordinate:
    # do what you would do with your location event(s)

it may be easier to not directly work on individual type of items, but rather store the list of items present at each location. Example:

def __init__(self):
    super().__init__()
    self.name = "The Catacombs"
    self.level = 1
    self.pois = [
        {"type": "throne", "positions": [(2, 3), (4,5)]},
        {"type": "pit", "positions": [(2, 4), (4,4)]}
    ]

Then you can just loop other these to build a second-hand variable:

position_to_items = {}
for item_props in self.pois:
    for position in item_props["positions"]:
        if position in position_to_items:
            position_to_items[position].append(item_props["type"])
        else:
            position_to_items[position] = [item_props["type"]]

Then, given a position (tuple), you'll directly get the list of items present in the room.

Related