Skip to content

Commit 56d59f5

Browse files
committed
Feature: Simplified Asteroids game inputs and improved Rating calculation.
1 parent c7a9a2e commit 56d59f5

File tree

6 files changed

+17
-60
lines changed

6 files changed

+17
-60
lines changed

G33kShell.Desktop/Console/Screensavers/AI/AiGameCanvasBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ private void TrainAiImpl(Action<byte[]> saveBrainBytes)
119119
{
120120
m_generationsSinceImprovement++;
121121

122-
m_currentPopSize = Math.Max(m_currentPopSize - 2, MinPopSize);
122+
m_currentPopSize = Math.Max(m_currentPopSize - 1, MinPopSize);
123123
if (m_generationsSinceImprovement >= 100)
124124
{
125125
m_generationsSinceImprovement = 0;

G33kShell.Desktop/Console/Screensavers/Asteroids/Asteroid.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ public class Asteroid
1616
private readonly float m_direction;
1717
private readonly Vector2[] m_offsets;
1818
private static readonly int[] Radii = [2, 4, MaxRadius];
19-
private static readonly int[] HitScores = [20, 10, 5];
2019
private static readonly int[] SizeMetrics = [1, 2, 4];
2120
private static readonly float[] Speeds = [1.5f, 1.0f, 0.6f];
2221
private int m_size = 2;
@@ -25,15 +24,14 @@ public class Asteroid
2524

2625
public int SizeMetric => SizeMetrics[m_size];
2726
public int Radius => Radii[m_size];
28-
public int HitScore => HitScores[m_size];
2927
public bool IsInvulnerable => m_invulnerable > 0;
3028

3129
/// <summary>
3230
/// Position in arena coordinates.
3331
/// </summary>
3432
public Vector2 Position { get; private set; }
3533

36-
private Vector2 Velocity
34+
public Vector2 Velocity
3735
{
3836
get
3937
{

G33kShell.Desktop/Console/Screensavers/Asteroids/Brain.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ namespace G33kShell.Desktop.Console.Screensavers.Asteroids;
1515

1616
public class Brain : AiBrainBase
1717
{
18-
public const int BrainInputCount = 10;
18+
public const int BrainInputCount = 6;
1919

20-
public Brain() : base(BrainInputCount, [32, 16], 4)
20+
public Brain() : base(BrainInputCount, [16, 8], 4)
2121
{
2222
}
2323

G33kShell.Desktop/Console/Screensavers/Asteroids/Bullet.cs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,12 @@ public class Bullet
2626
public Vector2 Position { get; private set; }
2727

2828
public bool IsExpired { get; private set; }
29-
30-
/// <summary>
31-
/// The target the bullet is nominally aiming for.
32-
/// </summary>
33-
public Asteroid Target { get; }
34-
35-
public Bullet(Vector2 position, float theta, Asteroid target, int arenaWidth, int arenaHeight)
29+
30+
public Bullet(Vector2 position, float theta, int arenaWidth, int arenaHeight)
3631
{
3732
m_arenaWidth = arenaWidth;
3833
m_arenaHeight = arenaHeight;
3934
Position = position;
40-
Target = target;
4135
m_velocity = theta.ToDirection();
4236
m_distanceUntilDeath = new Vector2(arenaWidth, arenaHeight).Length() * 0.4;
4337
}

G33kShell.Desktop/Console/Screensavers/Asteroids/Game.cs

Lines changed: 6 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ namespace G33kShell.Desktop.Console.Screensavers.Asteroids;
2121
public class Game : AiGameBase
2222
{
2323
private int m_bulletsFired;
24-
private int m_asteroidsHit;
25-
private int m_perfectHits;
2624
private int m_gameTicks;
2725
private int m_leftTurns;
2826
private int m_rightTurns;
@@ -39,33 +37,19 @@ public override double Rating
3937
{
4038
get
4139
{
42-
if (Score == 0)
43-
return 0.0; // Penalize pacifists.
44-
if (m_gameTicks > 2000 && m_bulletsFired < 5)
45-
return 0.0; // Penalize idle campers.
4640
if (TurnEquality < 0.3)
4741
return 0.0; // Penalize wonky-turners.
4842
if (m_thrustTicks == 0)
4943
return 0.0; // Penalize non-thrusters.
5044

51-
var thrustRatio = m_thrustTicks / (double)m_gameTicks;
52-
var survivalBonus = (m_gameTicks / 8000.0).Clamp(0.0, 1.0);
53-
54-
return Score / 8000.0 * 10.0 +
55-
HitRatio * 0.5 * 0.1 +
56-
PerfectHitRatio * 1.0 * 0.1 +
57-
thrustRatio * 2.0 * 0.1 +
58-
TurnEquality * 0.5 * 0.1 +
59-
survivalBonus * 1.0 * 0.1
60-
;
45+
return Score * HitRatio * HitRatio * m_gameTicks * 0.001;
6146
}
6247
}
6348

6449
public override IEnumerable<(string Name, string Value)> ExtraGameStats()
6550
{
6651
yield return ("Score", Score.ToString());
67-
yield return ("Accuracy", HitRatio.ToString("P1"));
68-
yield return ("Perfect", PerfectHitRatio.ToString("P1"));
52+
yield return ("HitRatio", HitRatio.ToString("P1"));
6953
yield return ("Ticks", m_gameTicks.ToString());
7054
yield return ("TurnEquality", TurnEquality.ToString("P1"));
7155
yield return ("Thrusts", m_thrustTicks.ToString());
@@ -87,8 +71,7 @@ private double TurnEquality
8771
public List<Asteroid> Asteroids { get; } = [];
8872
public List<Bullet> Bullets { get; } = [];
8973

90-
private double PerfectHitRatio => m_bulletsFired == 0 ? 0.0 : (double)m_perfectHits / m_bulletsFired;
91-
private double HitRatio => m_bulletsFired == 0 ? 0.0 : (double)m_asteroidsHit / m_bulletsFired;
74+
private double HitRatio => m_bulletsFired == 0 ? 0.0 : (double)Score / m_bulletsFired;
9275

9376
public Game(int arenaWidth, int arenaHeight) : base(arenaWidth, arenaHeight, new Brain())
9477
{
@@ -98,13 +81,11 @@ public override Game ResetGame()
9881
{
9982
Ship = new Ship(ArenaWidth, ArenaHeight);
10083
Score = 0;
101-
m_gameState = new GameState(Ship, Asteroids, Bullets, ArenaWidth, ArenaHeight);
84+
m_gameState = new GameState(Ship, Asteroids, ArenaWidth, ArenaHeight);
10285

10386
Asteroids.Clear();
10487
Bullets.Clear();
10588
m_bulletsFired = 0;
106-
m_perfectHits = 0;
107-
m_asteroidsHit = 0;
10889
m_gameTicks = 0;
10990
m_leftTurns = 0;
11091
m_rightTurns = 0;
@@ -151,8 +132,7 @@ public override void Tick()
151132
// Spawn new bullets.
152133
if (Ship.IsShooting && Bullets.Count < Ship.MaxBullets)
153134
{
154-
var target = Asteroids.FastFindMin(o => Vector2.DistanceSquared(Ship.Position, o.Position));
155-
Bullets.Add(new Bullet(Ship.Position, Ship.Theta, target, ArenaWidth, ArenaHeight));
135+
Bullets.Add(new Bullet(Ship.Position, Ship.Theta, ArenaWidth, ArenaHeight));
156136
m_bulletsFired++;
157137
}
158138

@@ -189,12 +169,7 @@ public override void Tick()
189169
// Bullet hit an asteroid.
190170
bulletsToRemove.Add(bullet);
191171
hitAsteroid.Explode(Asteroids);
192-
Score += hitAsteroid.HitScore;
193-
194-
// Bonus points if it was the asteroid we were aiming for.
195-
if (bullet.Target == hitAsteroid)
196-
m_perfectHits++;
197-
m_asteroidsHit++;
172+
Score++;
198173
}
199174

200175
for (var i = 0; i < bulletsToRemove.Count; i++)

G33kShell.Desktop/Console/Screensavers/Asteroids/GameState.cs

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,12 @@ public class GameState : IAiGameState
2424
private readonly double[] m_inputVector = new double[Brain.BrainInputCount];
2525
private readonly Ship m_ship;
2626
private readonly List<Asteroid> m_asteroids;
27-
private readonly List<Bullet> m_bullets;
2827
private readonly float m_arenaDiagonal;
2928

30-
public GameState(Ship ship, List<Asteroid> asteroids, List<Bullet> bullets, int arenaWidth, int arenaHeight)
29+
public GameState(Ship ship, List<Asteroid> asteroids, int arenaWidth, int arenaHeight)
3130
{
3231
m_ship = ship;
3332
m_asteroids = asteroids;
34-
m_bullets = bullets;
3533

3634
m_arenaDiagonal = new Vector2(arenaWidth, arenaHeight).Length();
3735
}
@@ -56,19 +54,11 @@ public double[] ToInputVector()
5654
m_inputVector[2] = 0.0;
5755
}
5856

59-
var normalizedVelocity = m_ship.Velocity == Vector2.Zero ? Vector2.Zero : Vector2.Normalize(m_ship.Velocity);
60-
m_inputVector[3] = normalizedVelocity.X.Clamp(-1.0f, 1.0f);
61-
m_inputVector[4] = normalizedVelocity.Y.Clamp(-1.0f, 1.0f);
57+
var relativeVelocity = asteroid?.Velocity ?? Vector2.Zero - m_ship.Velocity;
58+
relativeVelocity = relativeVelocity.LengthSquared() > 0.0f ? Vector2.Normalize(relativeVelocity) : Vector2.Zero;
59+
m_inputVector[3] = relativeVelocity.X.Clamp(-1.0f, 1.0f);
60+
m_inputVector[4] = relativeVelocity.Y.Clamp(-1.0f, 1.0f);
6261
m_inputVector[5] = (m_ship.Theta / Math.Tau).Clamp(-1.0f, 1.0f);
63-
m_inputVector[6] = m_ship.IsShooting ? 1.0 : 0.0;
64-
m_inputVector[7] = m_ship.IsThrusting ? 1.0 : 0.0;
65-
m_inputVector[8] = m_ship.Turning switch
66-
{
67-
Ship.Turn.Left => -1.0,
68-
Ship.Turn.Right => 1.0,
69-
_ => 0.0
70-
};
71-
m_inputVector[9] = (double)m_bullets.Count / Ship.MaxBullets;
7262

7363
return m_inputVector;
7464
}

0 commit comments

Comments
 (0)