Skip to content

Commit 3ef6812

Browse files
committed
Feature: Adds lives system to Asteroids game.
1 parent 11fd169 commit 3ef6812

File tree

6 files changed

+41
-24
lines changed

6 files changed

+41
-24
lines changed

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

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ public abstract class AiGameCanvasBase : ScreensaverBase
3737
protected int ArenaWidth { get; }
3838
protected int ArenaHeight { get; }
3939

40-
protected abstract void DrawGame(ScreenData screen, AiGameBase game);
41-
4240
protected AiGameCanvasBase(int width, int height, int targetFps = 30) : base(width, height, targetFps)
4341
{
4442
ArenaWidth = width;
@@ -99,7 +97,6 @@ private void TrainAiImpl(Action<byte[]> saveBrainBytes)
9997

10098
// Persist brain improvements.
10199
AiBrainBase goatBrain = null;
102-
var increaseMutation = false;
103100
if (veryBest.Rating > m_savedRating)
104101
{
105102
m_savedRating = veryBest.Rating;
@@ -114,13 +111,12 @@ private void TrainAiImpl(Action<byte[]> saveBrainBytes)
114111
m_generationsSinceImprovement++;
115112

116113
m_currentPopSize = Math.Max(m_currentPopSize - 2, MinPopSize);
117-
// if (m_generationsSinceImprovement >= 100)
118-
// {
119-
// m_generationsSinceImprovement = 0;
120-
// m_currentPopSize = InitialPopSize;
121-
// //increaseMutation = true;
122-
// System.Console.WriteLine("Stagnation detected — Increasing population size.");
123-
// }
114+
if (m_generationsSinceImprovement >= 100)
115+
{
116+
m_generationsSinceImprovement = 0;
117+
m_currentPopSize = InitialPopSize;
118+
System.Console.WriteLine("Stagnation detected — Increasing population size.");
119+
}
124120
}
125121

126122
// Build the brains for the next generation.
@@ -136,12 +132,6 @@ private void TrainAiImpl(Action<byte[]> saveBrainBytes)
136132
// ...and 10% more with a small mutation.
137133
nextBrains.AddRange(eliteGames.Select(o => o.Brain.Clone().Mutate(0.02)));
138134

139-
if (increaseMutation)
140-
{
141-
// Fill 50% of the population with more mutations.
142-
nextBrains.AddRange(orderedGames.Take(orderedGames.Length / 2).Select(o => o.Brain.Clone().Mutate(0.5)));
143-
}
144-
145135
// Spawn 5% pure randoms.
146136
nextBrains.AddRange(Enumerable.Range(0, (int)(m_currentPopSize * 0.05)).Select(_ => veryBest.Brain.Clone().Randomize()));
147137

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ private void PlayGame(ScreenData screen)
5656
m_games[0].ResetGame();
5757
}
5858

59-
protected override void DrawGame(ScreenData screen, AiGameBase aiGame)
59+
private void DrawGame(ScreenData screen, AiGameBase aiGame)
6060
{
6161
screen.Clear(Foreground, Background);
6262

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

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
namespace G33kShell.Desktop.Console.Screensavers.Asteroids;
1919

20-
[DebuggerDisplay("Rating = {Rating}, Score = {Score}")]
20+
[DebuggerDisplay("Rating = {Rating}, Score = {Score}, Lives = {m_lives}")]
2121
public class Game : AiGameBase
2222
{
2323
private int m_bulletsFired;
@@ -26,6 +26,7 @@ public class Game : AiGameBase
2626
private int m_leftTurns;
2727
private int m_rightTurns;
2828
private GameState m_gameState;
29+
private int m_lives = 3;
2930

3031
/// <summary>
3132
/// Score used for public display.
@@ -38,7 +39,7 @@ public class Game : AiGameBase
3839
(1.0 - (double)Math.Abs(m_leftTurns - m_rightTurns) / (m_leftTurns + m_rightTurns + 1)) * 5.0 + // Reward not spinning.
3940
Score / 1000.0; // Reward score.
4041

41-
public override bool IsGameOver => Ship.Shield <= 0.0 || m_gameTicks > 200_000;
42+
public override bool IsGameOver => m_lives == 0 || m_gameTicks > 200_000;
4243
public Ship Ship { get; private set; }
4344
public List<Asteroid> Asteroids { get; } = [];
4445
public List<Bullet> Bullets { get; } = [];
@@ -155,7 +156,18 @@ public override void Tick()
155156
var distance = Asteroids[i].DistanceTo(Ship.Position);
156157
if (distance < Asteroids[i].Radius + shipRadius)
157158
{
158-
Ship.Shield = Math.Max(0.0, Ship.Shield - 0.05);
159+
var newShield = Ship.Shield - 0.08;
160+
if (newShield < 0.0)
161+
{
162+
// Ship is dead - Reset asteroids and bullets.
163+
m_lives--;
164+
Asteroids.Clear();
165+
Bullets.Clear();
166+
Ship.Reset();
167+
return;
168+
}
169+
170+
Ship.Shield = newShield;
159171
break;
160172
}
161173
}

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

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@ public class Ship
1919
private readonly int m_arenaWidth;
2020
private readonly int m_arenaHeight;
2121
private const float MaxSpeed = 0.2f;
22+
private const double MaxShield = 1.0;
2223

2324
private Vector2 m_acceleration = Vector2.Zero;
2425

2526
public enum Turn { None, Left, Right }
26-
public double Shield { get; set; } = 1.0;
27+
public double Shield { get; set; }
2728
public float Theta { get; private set; }
2829
public static int MaxBullets => 8;
2930

@@ -44,7 +45,8 @@ public Ship(int arenaWidth, int arenaHeight)
4445
{
4546
m_arenaWidth = arenaWidth;
4647
m_arenaHeight = arenaHeight;
47-
Position = new Vector2(arenaWidth / 2.0f, arenaHeight / 2.0f);
48+
49+
Reset();
4850
}
4951

5052
public void Move()
@@ -74,4 +76,17 @@ public void Move()
7476
var newY = (Position.Y + m_arenaHeight) % m_arenaHeight;
7577
Position = new Vector2(newX, newY);
7678
}
79+
80+
/// <summary>
81+
/// Called when the ship is destroyed. Reset to the center of the arena.
82+
/// </summary>
83+
public void Reset()
84+
{
85+
Position = new Vector2(m_arenaWidth / 2.0f, m_arenaHeight / 2.0f);
86+
Shield = MaxShield;
87+
IsShooting = false;
88+
Turning = Turn.None;
89+
IsThrusting = false;
90+
Velocity = Vector2.Zero;
91+
}
7792
}

G33kShell.Desktop/Console/Screensavers/Pong/PongCanvas.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ private void PlayGame(ScreenData screen)
6262
m_games[0].ResetGame();
6363
}
6464

65-
protected override void DrawGame(ScreenData screen, AiGameBase aiGame)
65+
private void DrawGame(ScreenData screen, AiGameBase aiGame)
6666
{
6767
var game = (Game)aiGame;
6868
var dimRgb = 0.2.Lerp(Background, Foreground);

G33kShell.Desktop/Console/Screensavers/Snake/SnakeCanvas.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ private void PlayGame(ScreenData screen)
5151
m_games[0].Tick();
5252
}
5353

54-
protected override void DrawGame(ScreenData screen, AiGameBase aiGame)
54+
private static void DrawGame(ScreenData screen, AiGameBase aiGame)
5555
{
5656
var game = (Game)aiGame;
5757

0 commit comments

Comments
 (0)