feat(gamecli): implement Observation.Build with unit tests
This commit is contained in:
52
GameCli.Tests/ObservationTests.cs
Normal file
52
GameCli.Tests/ObservationTests.cs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
using GameCli;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace GameCli.Tests;
|
||||||
|
|
||||||
|
public class ObservationTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Build_HasSevenDimensions()
|
||||||
|
{
|
||||||
|
var ship = new ShipState(0.5f, 0.5f, 0f, 0f, 0f, 0f);
|
||||||
|
var obs = Observation.Build(ship, target: (0.5f, 0.5f));
|
||||||
|
Assert.Equal(7, obs.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Build_DisplacementIsTargetMinusShip()
|
||||||
|
{
|
||||||
|
var ship = new ShipState(0.3f, 0.4f, 0f, 0f, 0f, 0f);
|
||||||
|
var obs = Observation.Build(ship, target: (0.7f, 0.9f));
|
||||||
|
// dx, dy at indices 0, 1
|
||||||
|
Assert.Equal(0.4f, obs[0], precision: 5);
|
||||||
|
Assert.Equal(0.5f, obs[1], precision: 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Build_EncodesVelocity()
|
||||||
|
{
|
||||||
|
var ship = new ShipState(0.5f, 0.5f, 0.1f, -0.2f, 0f, 0f);
|
||||||
|
var obs = Observation.Build(ship, target: (0.5f, 0.5f));
|
||||||
|
Assert.Equal(0.1f, obs[2], precision: 5);
|
||||||
|
Assert.Equal(-0.2f, obs[3], precision: 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Build_EncodesAngleAsSinCos()
|
||||||
|
{
|
||||||
|
var ship = new ShipState(0.5f, 0.5f, 0f, 0f, MathF.PI / 2f, 0f);
|
||||||
|
var obs = Observation.Build(ship, target: (0.5f, 0.5f));
|
||||||
|
// sin(π/2)=1, cos(π/2)=0
|
||||||
|
Assert.Equal(1f, obs[4], precision: 5);
|
||||||
|
Assert.Equal(0f, obs[5], precision: 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Build_LastDimIsAngularVelocity()
|
||||||
|
{
|
||||||
|
var ship = new ShipState(0.5f, 0.5f, 0f, 0f, 0f, 0.7f);
|
||||||
|
var obs = Observation.Build(ship, target: (0.5f, 0.5f));
|
||||||
|
Assert.Equal(0.7f, obs[6], precision: 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
25
GameCli/Observation.cs
Normal file
25
GameCli/Observation.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
namespace GameCli;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Builds the 7-dim observation vector fed to PPO:
|
||||||
|
/// [dx, dy, vx, vy, sin(angle), cos(angle), angular_velocity]
|
||||||
|
/// Angle is encoded as sin/cos to avoid the discontinuity at ±π.
|
||||||
|
/// </summary>
|
||||||
|
public static class Observation
|
||||||
|
{
|
||||||
|
public const int Dim = 7;
|
||||||
|
|
||||||
|
public static float[] Build(ShipState s, (float X, float Y) target)
|
||||||
|
{
|
||||||
|
return new float[Dim]
|
||||||
|
{
|
||||||
|
target.X - s.X,
|
||||||
|
target.Y - s.Y,
|
||||||
|
s.VX,
|
||||||
|
s.VY,
|
||||||
|
MathF.Sin(s.Angle),
|
||||||
|
MathF.Cos(s.Angle),
|
||||||
|
s.AngularVelocity,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user