Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 42 additions & 4 deletions src/Zen.Desktop.Host/ProcessorHooks/ManicMiner/RoutePlanner.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using Zen.Z80.Processor;

Expand All @@ -9,9 +10,12 @@ public class RoutePlanner

private readonly PriorityQueue<(int X, int Y, List<Move> Moves, HashSet<(int X, int Y)> Keys, HashSet<(int X, int Y)> Visited, int Steps), int> _queue = new();

public RoutePlanner(int level, Interface @interface)
private readonly HashSet<(int X, int Y)> _deathCells;

public RoutePlanner(int level, Interface @interface, IEnumerable<(int X, int Y)> deathCells = null)
{
_levelData = new LevelData(level, @interface);
_deathCells = deathCells == null ? [] : [..deathCells];
}

public void Initialise()
Expand Down Expand Up @@ -46,7 +50,9 @@ public List<Move> GetNextRoute()
continue;
}

_queue.Enqueue((move.X, move.Y, [..node.Moves, move.Move], node.Keys, [..node.Visited, (move.X, move.Y)], node.Steps + 1), node.Steps + 1);
var penalty = GetDeathPenalty(move.X, move.Y);

_queue.Enqueue((move.X, move.Y, [..node.Moves, move.Move], [..node.Keys], [..node.Visited, (move.X, move.Y)], node.Steps + 1), node.Steps + 1 + penalty);
}
}

Expand Down Expand Up @@ -115,7 +121,7 @@ private bool IsComplete((int X, int Y, List<Move> Moves, HashSet<(int X, int Y)>

if (TryWalk(x, y, 2))
{
moves.Add((Move.Left, x + 2, y));
moves.Add((Move.Right, x + 2, y));
}

var jump = TryJump(x, y, -2);
Expand All @@ -129,7 +135,7 @@ private bool IsComplete((int X, int Y, List<Move> Moves, HashSet<(int X, int Y)>

if (jump.Safe)
{
moves.Add((Move.UpLeft, jump.X, jump.Y));
moves.Add((Move.UpRight, jump.X, jump.Y));
}

return moves;
Expand Down Expand Up @@ -247,6 +253,38 @@ private bool CheckSafe(int x, int y)
return true;
}

private int GetDeathPenalty(int x, int y)
{
if (_deathCells.Count == 0)
{
return 0;
}

var cell = (x / 8, y / 8);

if (_deathCells.Contains(cell))
{
return 10000;
}

foreach (var deathCell in _deathCells)
{
var distance = Math.Abs(deathCell.X - cell.Item1) + Math.Abs(deathCell.Y - cell.Item2);

if (distance <= 2)
{
return 1000;
}

if (distance <= 4)
{
return 250;
}
}

return 0;
}

private bool CheckOpen(int x, int y)
{
var cell = _levelData.Map[x / 8, y / 8];
Expand Down
52 changes: 48 additions & 4 deletions src/Zen.Desktop.Host/ProcessorHooks/ManicMiner/WillyBot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public class WillyBot : IProcessorHook
private readonly Queue<Move> _route = new();

private Move _move;

private readonly Dictionary<int, HashSet<(int X, int Y)>> _deathsByLevel = new();

public bool Activate(State state)
{
Expand All @@ -37,6 +39,8 @@ public void PassiveCycle(State state, Interface @interface)
case 0x88FF:
// Dead

LearnFromDeath(@interface);

RestartLevel();

break;
Expand Down Expand Up @@ -121,7 +125,7 @@ public void PassiveCycle(State state, Interface @interface)

var grounded = @interface.ReadFromMemory(0x806B) == 0;

if (grounded)
if (grounded && _route.Count > 0)
{
_move = _route.Dequeue();
}
Expand All @@ -132,7 +136,7 @@ public void PassiveCycle(State state, Interface @interface)

private void StartLevel(Interface @interface)
{
_routePlanner = new RoutePlanner(_level, @interface);
_routePlanner = new RoutePlanner(_level, @interface, GetDeathCells(_level));

_routePlanner.Initialise();

Expand All @@ -142,7 +146,47 @@ private void StartLevel(Interface @interface)
private void RestartLevel()
{
_route.Clear();

_routePlanner.GetNextRoute().ForEach(m => _route.Enqueue(m));

var route = _routePlanner.GetNextRoute();

if (route == null)
{
return;
}

route.ForEach(m => _route.Enqueue(m));
}

private void LearnFromDeath(Interface @interface)
{
var cellPointer = @interface.ReadFromMemory(0x806C) + (@interface.ReadFromMemory(0x806D) << 8);

if (cellPointer < 0x5C00)
{
return;
}

var cellOffset = cellPointer - 0x5C00;

var x = cellOffset % 32;
var y = @interface.ReadFromMemory(0x8068) / 2 / 8;

if (!_deathsByLevel.TryGetValue(_level, out var cells))
{
cells = [];
_deathsByLevel[_level] = cells;
}

cells.Add((x, y));
}

private IEnumerable<(int X, int Y)> GetDeathCells(int level)
{
if (_deathsByLevel.TryGetValue(level, out var cells))
{
return cells;
}

return [];
}
}