Series: Modeling logic puzzles
Phần: 9 / 91. Introduction
Haunted Mirror Maze (also known as Undead) is a logic puzzle described as follows: given an grid where some cells already contain a diagonal mirror, the player needs to fill every remaining cell with one of three monsters, a vampire (), a ghost (), or a zombie (), satisfying the following conditions:
- Numbers outside the grid give the number of monsters visible when looking into the grid from that point. A line of sight travels in a straight line and bounces off every mirror cell it passes through, until it exits the grid.
- A vampire is only visible head-on, before the line of sight has bounced off any mirror. A ghost is the opposite, only visible after the line of sight has bounced off at least one mirror. A zombie is always visible, whether head-on or reflected.
- Some puzzles pre-fill a few cells with a fixed monster.
- Some puzzles also give the total number of vampires, ghosts, and zombies hidden in the maze.
Source: Simon Tatham's Portable Puzzle Collection
To better picture the logic of a line of sight, consider the following example.
Looking from the left, the line of sight passes through a vampire (visible, since nothing has bounced off a mirror yet), a ghost (not visible, since it hasn't been reflected yet), and a zombie (always visible), then bounces when it meets a mirror. From that point on, everything the line of sight reaches counts as reflected: the vampire is now not visible, while the ghost and the zombie are both visible. In total, monsters are visible.
Below is an example of a 6×6 Haunted Mirror Maze puzzle and its solution.
2. Modeling the puzzle
Some symbols used in this problem
- is the number of rows in the grid
- is the number of columns in the grid
- is the set of cells that already contain a mirror
- is the set of sight lines. For a sight line , let be the set of cells the line of sight passes through before bouncing off its first mirror, and be the set of cells it passes through after that, once it has bounced off at least one mirror. Both sets exclude the mirror cells themselves
- is the number of monsters visible for sight line
- , , are respectively the total number of vampires, ghosts, and zombies hidden in the maze (if given)
- is the set of pairs representing the coordinates of the pre-filled cells in the grid
- is the monster filled in cell
2.1. Decision variables
For each cell in the grid, we define variables , , such that
2.2. Constraints
- Mirror cells contain no monster
- Every other cell contains exactly one monster
- Pre-filled cells
- Total number of each monster (if given)
-
The number of monsters visible along each sight line matches its clue.
Since a vampire is only visible head-on, a ghost is only visible once reflected, and a zombie is always visible, this condition is simply
2.3. Objective function
This problem does not have an objective function, as we are not aiming to minimize or maximize anything, all we need is to find a feasible solution. Technically, when programming, we can set the objective function to a constant (I often choose 0).
3. Conclusion
This is a puzzle with a fairly interesting idea, but it isn't really a hard one. The constraints are expressed quite directly and are easy to follow.
For more Haunted Mirror Maze puzzles and variations, please refer to Krazydad. The Python code for Haunted Mirror Maze modeling is available at Tung-hehe.
Happy modeling!
