Hide and Seek
An implementation of intelligent AI agents to simulate a hide-and-seek game where each agent makes the best choice for themself.
Published onUpdated on
4.935
Motivation
Originally, this was done for a project due in a course of Artificial Intelligence. But as I do it, I feel like it’s not a fun project to work on. So I deviated and started to redesign the project to be more fun and interesting. Starting the project, I had a goal in mind: to make this as a learning opportunity, and using what I studied in AIMA (Artificial Intelligence: A Modern Approach).
Overview
This project is a simulation of a game of Hide and Seek, where the hiders and seekers are intelligent agents. The hiders are tasked with hiding in the environment, while the seekers are tasked with finding the hiders. Only 1 seeker, though.
Project Structure Overview:
.
|-- src
|-- agent.py
|-- hide_and_seek.py
|-- hider.py
|-- seeker.py
|-- map_state.py
|-- vector2d.py
|-- main.py
|-- maps
|-- lX_mY.txt
|-- ...
Where:
agent.pycontains the base class for an agent, including the moveset and vision.hide_and_seek.pycontains the board, manages the positions for agents, can check whether the game is over.hider.pycontains the hider class, which is a subclass of the agent class. Contains some additional methods for the hider.seeker.pycontains the seeker class, which is a subclass of the agent class. Contains some additional methods for the seeker.map_state.pycontains the map state class, which is a representation of the map itself.vector2d.pycontains thevectorclass andvectorfclass, which are basically tuples of 2 integers and 2 floats, respectively. The integer version is used for each cell in the map, while the float version is used for calculating raytracing.
The Game
The game is a simple simulation of states. The game is played in a 2D grid, where the agents can move in 8 directions (up, down, left, right, and diagonals). The agents have a vision range, which is the number of squares they can see around themselves. The agents can only see in a square around themselves, and they can only see the current state of the map, without knowing about opponents.
The game is played accordingly:
- Check if the game is over (time limit reached, or all hiders caught). If it is over, go to step 6.
- Tick the seeker. The seeker looks around itself, updates its internal state, and moves.
- Tick the game board. Check if the seeker overlaps any hiders, if it does, the hider is caught. Update the game board accordingly.
- Tick the hiders. The remaining hiders look around themselves, update their internal state, and move (if possible).
- The score and time is ticked. Score gets deducted by 1 for each step. Time
gets incremented by 1 for each step. If the time limit is reached, the game is
over. For each hider the seeker caught in this tick, the score gets increased
by
20. - Finished 1 state. Wait for next tick.
The game board is displayed with the following characters:
.is an empty space.His a hider.Sis a seeker.Xis a immovable wall.☐is a movable box.-is what the seeker can see.*is the alert flare.
Seeker
- Performance Measure: catch all hiders, in the fewest steps possible, within the time limit.
- Environment: a known map, with boxes and walls. Only us, the gamemasters, know where the hiders are.
- Actuators: the agent may move in any 8 directions, or stay in place (unlikely).
- Sensors: the agent can see in a square around itself, with a vision radius
of
n(wherenis the vision range).
A step is defined as a movement in any of the 8 directions, or staying in place.
The seeker goes through 2 stages: perceive and accept.
- Perception: The seeker looks around, and checks cells it can see (not blocked), and are valid (not WALL, not BORDER). It may ask the gamemaster whether a cell has a hider or not. If the cell is empty, it cools down the cell. If the cell has a hider, it heats up the cell. If the cell is a hider, it heats up by A LOT. If there is a flare shot, a region around the flare is heated up.
- Action: The seeker checks its current state (the heatmap), and selects all cells with the highest value (aka the hottest cells). It then runs a multi A* search from its current position, finds the first goal cell it can discover, and returns a direction to move to that cell.
Hider
Level 1 - Level 2
- Performance Measure: hide from the seeker within the time limit.
- Environment: a known map, with boxes and walls. Only us, the gamemasters, know where the seeker is.
- Actuators: the agent may move in any 8 directions, or stay in place. Or additionally, the agent may shoot a flare.
- Sensors: the agent can see in a square around itself, with a vision radius
of
n(wherenis the vision range). This is shorter than the seeker’s vision.
These two levels are basically the same, with the only difference being the number of hiders. In level 1, there is only 1 hider, while in level 2, there are multiples.

Level 3
- Performance Measure: hide from the seeker within the time limit.
- Environment: a known map, with boxes and walls. Only us, the gamemasters, know where the seeker is.
- Actuators: the agent may move in any 8 directions, or stay in place. Or additionally, the agent may shoot a flare. The agent may also move.
- Sensors: the agent can see in a square around itself, with a vision radius
of
n(wherenis the vision range). This is shorter than the seeker’s vision.
Assuming, with similar configurations, this means the hider is a reverse-seeker. It wants to move to the coldest place possible, where the heatmap starts out to be hot. This is probably not it, as if the hider wants to move the shortest path too, the chance of it colliding with the seeker is very high.
I have not implemented this level and level 4 (multiple hiders). Since I can’t theoretically prove that using a reverse heat map would be better, as a better method would be to let the hider think it’s better to hide in corners, for example.