Skip to content
Draft
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
42 changes: 41 additions & 1 deletion GoRogue.UnitTests/Pathing/FleeMapTests.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
using System.Linq;
using System.Collections.Generic;
using System.Linq;
using GoRogue.Pathing;
using GoRogue.UnitTests.Mocks;
using SadRogue.Primitives;
using SadRogue.Primitives.GridViews;
using Xunit;
using Xunit.Abstractions;

namespace GoRogue.UnitTests.Pathing
{
public class FleeMapTests
{
private readonly ITestOutputHelper output;
private const int _width = 40;
private const int _height = 35;
private static readonly Point _goal = (5, 5);

public FleeMapTests(ITestOutputHelper output)
{
this.output = output;
}
[Fact]
public void FleeMapDoesNotLeadToGoal()
{
Expand Down Expand Up @@ -61,5 +68,38 @@ public void OpenEdgedMapSupported()

// TODO: Verify flee map leads away from goal
}

[Theory]
[InlineData(1.2)] //go right
[InlineData(1.6)] //go right
[InlineData(1.7)] //go left !?
public void test(double magnitude)
{
//map:
// #
// #C
// #
// Character (C) at (5,5) should flee threats (#) by going right
var threatsCells = new List<SadRogue.Primitives.Point>
{
(5,4),
(4,5),
(5,6)
};

var gridView = new LambdaGridView<GoalState>(11, 11, cell => threatsCells.Contains(cell) ? GoalState.Goal : GoalState.Clear);
var goalMap = new GoalMap(gridView, Distance.Manhattan);
var fleeMap = new FleeMap(goalMap, magnitude);
var currentCell = new SadRogue.Primitives.Point(5, 5);


output.WriteLine(fleeMap.ToString(4));

//Direction direction = fleeMap.GetDirectionOfMinValue(currentCell, AdjacencyRule.Cardinals);



//Assert.Equal(Direction.Right, direction);
}
}
}
2 changes: 1 addition & 1 deletion GoRogue/GoRogue.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Basic package info -->
<TargetFrameworks>netstandard2.1;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0</TargetFrameworks>
<TargetFrameworks>netstandard2.1;netcoreapp3.1;net5.0;net6.0;net7.0</TargetFrameworks>
<RootNamespace>GoRogue</RootNamespace>
<Authors>Chris3606</Authors>
<Copyright>Copyright © 2023 Christopher Ridley (Chris3606)</Copyright>
Expand Down
121 changes: 0 additions & 121 deletions GoRogue/Pathing/AStar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -366,127 +366,6 @@ private bool CheckWalkability(Point pos, Point start, Point end, bool assumeEndp
}
}

/// <summary>
/// Encapsulates a path as returned by pathfinding algorithms like AStar.
/// </summary>
/// <remarks>
/// Provides various functions to iterate through/access steps of the path, as well as
/// constant-time reversing functionality.
/// </remarks>
[PublicAPI]
public class Path
{
private readonly IReadOnlyList<Point> _steps;
private bool _inOriginalOrder;

/// <summary>
/// Creates a copy of the path, optionally reversing the path as it does so.
/// </summary>
/// <remarks>Reversing is an O(1) operation, since it does not modify the list.</remarks>
/// <param name="pathToCopy">The path to copy.</param>
/// <param name="reverse">Whether or not to reverse the path. Defaults to <see langword="false" />.</param>
public Path(Path pathToCopy, bool reverse = false)
{
_steps = pathToCopy._steps;
_inOriginalOrder = reverse ? !pathToCopy._inOriginalOrder : pathToCopy._inOriginalOrder;
}

// Create based on internal list
internal Path(IReadOnlyList<Point> steps)
{
_steps = steps;
_inOriginalOrder = true;
}

/// <summary>
/// Ending point of the path.
/// </summary>
public Point End => _inOriginalOrder ? _steps[0] : _steps[^1];

/// <summary>
/// The length of the path, NOT including the starting point.
/// </summary>
public int Length => _steps.Count - 1;

/// <summary>
/// The length of the path, INCLUDING the starting point.
/// </summary>
public int LengthWithStart => _steps.Count;

/// <summary>
/// Starting point of the path.
/// </summary>
public Point Start => _inOriginalOrder ? _steps[^1] : _steps[0];


/// <summary>
/// The coordinates that constitute the path (in order), NOT including the starting point.
/// These are the coordinates something might walk along to follow a path.
/// </summary>
public IEnumerable<Point> Steps
{
get
{
if (_inOriginalOrder)
for (var i = _steps.Count - 2; i >= 0; i--)
yield return _steps[i];
else
for (var i = 1; i < _steps.Count; i++)
yield return _steps[i];
}
}

/// <summary>
/// The coordinates that constitute the path (in order), INCLUDING the starting point.
/// </summary>
public IEnumerable<Point> StepsWithStart
{
get
{
if (_inOriginalOrder)
for (var i = _steps.Count - 1; i >= 0; i--)
yield return _steps[i];
else
foreach (var step in _steps)
yield return step;
}
}

/// <summary>
/// Gets the nth step along the path, where 0 is the step AFTER the starting point.
/// </summary>
/// <param name="stepNum">The (array-like index) of the step to get.</param>
/// <returns>The coordinate constituting the step specified.</returns>
public Point GetStep(int stepNum)
{
if (_inOriginalOrder)
return _steps[_steps.Count - 2 - stepNum];

return _steps[stepNum + 1];
}

/// <summary>
/// Gets the nth step along the path, where 0 IS the starting point.
/// </summary>
/// <param name="stepNum">The (array-like index) of the step to get.</param>
/// <returns>The coordinate constituting the step specified.</returns>
public Point GetStepWithStart(int stepNum) =>
// TODO: Revisit array-from-end syntax here
_inOriginalOrder ? _steps[_steps.Count - 1 - stepNum] : _steps[stepNum];

/// <summary>
/// Reverses the path, in constant time.
/// </summary>
public void Reverse() => _inOriginalOrder = !_inOriginalOrder;

/// <summary>
/// Returns a string representation of all the steps in the path, including the start point,
/// eg. [(1, 2), (3, 4), (5, 6)].
/// </summary>
/// <returns>A string representation of all steps in the path, including the start.</returns>
public override string ToString() => StepsWithStart.ExtendToString();
}

// Node representing a grid position in AStar's priority queue
internal class AStarNode : FastPriorityQueueNode
{
Expand Down
144 changes: 144 additions & 0 deletions GoRogue/Pathing/Path.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using SadRogue.Primitives;

namespace GoRogue.Pathing
{
/// <summary>
/// Encapsulates a path as returned by pathfinding algorithms like AStar.
/// </summary>
/// <remarks>
/// Provides various functions to iterate through/access steps of the path, as well as
/// constant-time reversing functionality.
/// </remarks>
[PublicAPI]
public class Path : IReadOnlyList<Point> // TODO: Need efficient enumerables; also maybe pull start out of path?

Check failure on line 16 in GoRogue/Pathing/Path.cs

View workflow job for this annotation

GitHub Actions / build

'Path' does not implement interface member 'IEnumerable.GetEnumerator()'

Check failure on line 16 in GoRogue/Pathing/Path.cs

View workflow job for this annotation

GitHub Actions / build

'Path' does not implement interface member 'IEnumerable<Point>.GetEnumerator()'

Check failure on line 16 in GoRogue/Pathing/Path.cs

View workflow job for this annotation

GitHub Actions / build

'Path' does not implement interface member 'IEnumerable.GetEnumerator()'

Check failure on line 16 in GoRogue/Pathing/Path.cs

View workflow job for this annotation

GitHub Actions / build

'Path' does not implement interface member 'IEnumerable<Point>.GetEnumerator()'

Check failure on line 16 in GoRogue/Pathing/Path.cs

View workflow job for this annotation

GitHub Actions / build

'Path' does not implement interface member 'IEnumerable.GetEnumerator()'

Check failure on line 16 in GoRogue/Pathing/Path.cs

View workflow job for this annotation

GitHub Actions / build

'Path' does not implement interface member 'IEnumerable<Point>.GetEnumerator()'

Check failure on line 16 in GoRogue/Pathing/Path.cs

View workflow job for this annotation

GitHub Actions / build

'Path' does not implement interface member 'IEnumerable.GetEnumerator()'

Check failure on line 16 in GoRogue/Pathing/Path.cs

View workflow job for this annotation

GitHub Actions / build

'Path' does not implement interface member 'IEnumerable<Point>.GetEnumerator()'

Check failure on line 16 in GoRogue/Pathing/Path.cs

View workflow job for this annotation

GitHub Actions / build

'Path' does not implement interface member 'IEnumerable.GetEnumerator()'

Check failure on line 16 in GoRogue/Pathing/Path.cs

View workflow job for this annotation

GitHub Actions / build

'Path' does not implement interface member 'IEnumerable<Point>.GetEnumerator()'
{
private readonly IReadOnlyList<Point> _steps;
private bool _inOriginalOrder;

/// <summary>
/// Creates a copy of the path, optionally reversing the path as it does so.
/// </summary>
/// <remarks>Reversing is an O(1) operation, since it does not modify the list.</remarks>
/// <param name="pathToCopy">The path to copy.</param>
/// <param name="reverse">Whether or not to reverse the path. Defaults to <see langword="false" />.</param>
public Path(Path pathToCopy, bool reverse = false)
{
_steps = pathToCopy._steps;
_inOriginalOrder = reverse ? !pathToCopy._inOriginalOrder : pathToCopy._inOriginalOrder;
}

// Create based on internal list
internal Path(IReadOnlyList<Point> steps)
{
_steps = steps;
_inOriginalOrder = true;
}

/// <summary>
/// Gets the nth step along the path, where 0 is the step AFTER the starting point.
/// </summary>
/// <param name="index">The (array-like index) of the step to get.</param>
/// <returns>The coordinate constituting the step specified.</returns>
public Point this[int index] => _inOriginalOrder ? _steps[^(2 - index)] : _steps[index + 1];

/// <summary>
/// The length of the path, NOT including the starting point.
/// </summary>
public int Count => _steps.Count - 1;

/// <summary>
/// Ending point of the path.
/// </summary>
public Point End => _inOriginalOrder ? _steps[0] : _steps[^1];

/// <summary>
/// The length of the path, NOT including the starting point.
/// </summary>
[Obsolete("Use Count property instead.")]
public int Length => _steps.Count - 1;

/// <summary>
/// The length of the path, INCLUDING the starting point.
/// </summary>
[Obsolete("Use CountWithStart property instead.")]
public int LengthWithStart => _steps.Count;

/// <summary>
/// Starting point of the path.
/// </summary>
public Point Start => _inOriginalOrder ? _steps[^1] : _steps[0];


/// <summary>
/// The coordinates that constitute the path (in order), NOT including the starting point.
/// These are the coordinates something might walk along to follow a path.
/// </summary>
[Obsolete("Path now implements IReadOnlyList; use its indexers/enumerable implementation directly instead.")]
public IEnumerable<Point> Steps
{
get
{
if (_inOriginalOrder)
for (var i = _steps.Count - 2; i >= 0; i--)
yield return _steps[i];
else
for (var i = 1; i < _steps.Count; i++)
yield return _steps[i];
}
}

/// <summary>
/// The coordinates that constitute the path (in order), INCLUDING the starting point.
/// </summary>
public IEnumerable<Point> StepsWithStart
{
get
{
if (_inOriginalOrder)
for (var i = _steps.Count - 1; i >= 0; i--)
yield return _steps[i];
else
foreach (var step in _steps)
yield return step;
}
}

/// <summary>
/// Gets the nth step along the path, where 0 is the step AFTER the starting point.
/// </summary>
/// <param name="stepNum">The (array-like index) of the step to get.</param>
/// <returns>The coordinate constituting the step specified.</returns>
[Obsolete("Use the indexers provided by Path instead.")]
public Point GetStep(int stepNum)
{
if (_inOriginalOrder)
return _steps[_steps.Count - 2 - stepNum];

return _steps[stepNum + 1];
}

/// <summary>
/// Gets the nth step along the path, where 0 IS the starting point.
/// </summary>
/// <param name="stepNum">The (array-like index) of the step to get.</param>
/// <returns>The coordinate constituting the step specified.</returns>
public Point GetStepWithStart(int stepNum) =>
// TODO: Revisit array-from-end syntax here
_inOriginalOrder ? _steps[_steps.Count - 1 - stepNum] : _steps[stepNum];

/// <summary>
/// Reverses the path, in constant time.
/// </summary>
public void Reverse() => _inOriginalOrder = !_inOriginalOrder;

/// <summary>
/// Returns a string representation of all the steps in the path, including the start point,
/// eg. [(1, 2), (3, 4), (5, 6)].
/// </summary>
/// <returns>A string representation of all steps in the path, including the start.</returns>
public override string ToString() => StepsWithStart.ExtendToString();
}
}