0

I hope this is the correct subpage of SE, if not please direct me to the more appropriate place.

Imagine the following scenario:

You are put into a random but known position inside a given maze. The maze contains, in addition to walls (█) and pathways (.), the following things:

  • R - A refresh point which is single use but when used refreshes the amount of steps you can take.
  • S - A save point which is multi use and gives you a known position you can start from (instead of a random position) but does not refresh your steps while inside the maze. If used to re-enter it grants you a full set of steps. Only relevant if algorithm can account for multiple re-entries (see optional optimizations below).
  • T - A treasure chest, which gives you some form of reward (the reward itself is irrelevant for the pathing algorithm)
  • M - A monster which you will need to fight if you encounter it. It will drop some treasure if defeated, but any damage it does to you will need to be regenerated (so a time penalty) or, if it defeats you, you get kicked out of the maze and need to re-enter it (either randomly or through a previously passed save point).

Used / looted / defeated status of a tile preserve between runs.

You have a maximum of 30 steps you can take before you get kicked out of the maze from exhaustion, unless refreshed at a refresh point.

Mazes are always square, with a side length of 160 tiles.

Example part of a maze:

█ █ █ . █ █ █ █ █
. . . . █ . . M █
█ █ █ █ █ . █ . █
M . █ . . R █ . █
█ R █ . █ █ █ . █
█ M . . █ . █ . █
█ █ █ M █ S █ . █
█ . █ . T . . . █
█ . █ . █ █ █ R █

Example visualization of a full maze. Blue drops are refresh points, fires are save points, ghosts are monsters and gifts are treasures. Everything else is irrelevant

What is a good way, given the mentioned restrictions, to find the path, starting from your current position, that passes by the most treasures (and monsters) before you're kicked out of the maze of exhaustion?

What I tried

I tried creating a graph of nodes based on the refresh points as the nodes and the paths between them as the connections, giving a higher value to more points of interest between nodes. I then used a modified Dijkstra algorithm to find the path with the highest value.
Unfortunately, while it works somewhat, it doesn't take into account what treasures/monsters have already been visited, often leading to high density areas of the map being covered many times over, requiring human intervention for improvement of said path (which more often than not has caused user error and a miscount, leading to a failed run).

I'm thankful for any ideas and suggestions as to how to tackle this.

Optional optimizations / extensions:

  • allow backtracking where it makes sense
  • use save points strategically to come back to and cover more area, spanning multiple runs.
  • allow the use of different weights to prioritize/avoid treasures/monsters by user preference
  • there is a single boss inside this maze, which is the ultimate "goal" of it. Make the path end there, while still picking up as many treasures on the way as possible.
  • whatever else you can think of
Plagiatus
  • 101
  • 3

1 Answers1

1

Basic approach

I suggest you reduce this to a longest path problem in a directed graph. In particular, conceptually we imagine the entire state space, and build a graph with one vertex per possible state in the state space, with edges representing moves you can make in a single step.

More specifically, we have one vertex in the graph for each pair $\langle \ell,s\rangle$, corresponding to starting at location $\ell$ with $s$ steps remaining. Add edges $\langle \ell,s \rangle \to \langle \ell',s-1 \rangle$ if you can go from location $\ell$ to location $\ell'$ in a single step. The weight on this edge is the value incurred in taking that step (e.g., if you visited a treasure, add the value of that treasure; if you defeated a monster, add the value of that monster).

Now find the longest path in this graph. You can find a longest path by negating all edge weights, and then finding a shortest path using the Bellman-Ford algorithm.

I am assuming you can assign a value to any particular path (e.g., that each treasure has a value and defeating each monster has a value, and the total value is the sum of those values acquiring along the way, and you can collect a treasure multiple times).

Save points

When we have save points, we need to keep track of the most recent save point, so let's revise our approach. Create one vertex per triple $\langle \ell,s,p \rangle$, corresponding to starting at location $\ell$ with $s$ steps remaining, and where the most recent save point is $p$. Now we can create edges corresponding to the different ways we can take a single step from this location.

Then, find a longest path in this graph, as before.

Single-use locations

This assumes you can collect a treasure multiple times, defeat a monster multiple times, and use a refresh point multiple times. I suspect in practice you can't. To take this into account, the state needs to keep track of which treasures have already been collected and which monsters have already been defeated and which refresh points have already been used. Taking this into account, each vertex of the graph might correspond to a tuple $\langle \ell, s, p, T \rangle$, where $\ell,s,p$ are as before and $T$ denotes the set of treasures collected and monsters defeated and refresh points used.

This blows up the size of the state space by a factor that is exponential in the number of treasures/monsters/refreshes, so applying Bellman-Ford naively might become intractable. Instead, you could try using heuristics, like A* search or some other method.

D.W.
  • 167,959
  • 22
  • 232
  • 500