using Microsoft.Xna.Framework; using Xunit; namespace MrGameEng.Pathfinding.Tests; public class FlowFieldTests { [Fact] public void Build_DistancesGrowFromGoal_DirectionsDescend() { var grid = new TestGrid(".....", ".###.", "....."); var builder = new FlowFieldBuilder(grid); var field = new FlowField(); builder.Build([new Point(0, 0)], field); Assert.Equal(0f, field.DistanceAt(0, 0)); Assert.True(field.DistanceAt(4, 2) > field.DistanceAt(1, 0)); // Из любой достижимой не-целевой клетки направление ведёт к клетке с меньшей дистанцией. for (var y = 0; y < grid.Height; y++) { for (var x = 0; x < grid.Width; x++) { if ( !grid.IsPassable(x, y) || !field.IsReachable(x, y) || field.DistanceAt(x, y) == 0f ) { continue; } var direction = field.DirectionAt(x, y); Assert.NotEqual(Vector2.Zero, direction); var nx = x + Math.Sign(MathF.Round(direction.X * 10f)); var ny = y + Math.Sign(MathF.Round(direction.Y * 10f)); Assert.True( field.DistanceAt(nx, ny) < field.DistanceAt(x, y), $"direction at ({x},{y}) does not descend" ); } } } [Fact] public void Build_UnreachablePocket_IsFlagged() { var grid = new TestGrid("..#..", "..#..", "..#.."); var builder = new FlowFieldBuilder(grid); var field = new FlowField(); builder.Build([new Point(0, 1)], field); Assert.False(field.IsReachable(4, 1)); Assert.Equal(Vector2.Zero, field.DirectionAt(4, 1)); Assert.True(field.IsReachable(1, 2)); } [Fact] public void Build_MultipleGoals_EachCellFlowsToNearest() { var grid = new TestGrid(".........."); var builder = new FlowFieldBuilder(grid); var field = new FlowField(); builder.Build([new Point(0, 0), new Point(9, 0)], field); Assert.True(field.DirectionAt(2, 0).X < 0f); // ближе к левой цели Assert.True(field.DirectionAt(7, 0).X > 0f); // ближе к правой Assert.Equal(0f, field.DistanceAt(9, 0)); } [Fact] public void Build_Rebuild_OverwritesPreviousField() { var grid = new TestGrid("....."); var builder = new FlowFieldBuilder(grid); var field = new FlowField(); builder.Build([new Point(0, 0)], field); Assert.True(field.DirectionAt(4, 0).X < 0f); builder.Build([new Point(4, 0)], field); Assert.True(field.DirectionAt(0, 0).X > 0f); Assert.Equal(0f, field.DistanceAt(4, 0)); } [Fact] public void Build_NoValidGoals_EverythingUnreachable() { var grid = new TestGrid(".#."); var builder = new FlowFieldBuilder(grid); var field = new FlowField(); builder.Build([new Point(1, 0)], field); // цель — стена Assert.False(field.IsReachable(0, 0)); Assert.False(field.IsReachable(2, 0)); } }