push de fin

This commit is contained in:
2025-11-30 13:03:47 +01:00
commit d58b58c067
24 changed files with 601 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@@ -0,0 +1,7 @@
bin/
obj/
/packages/
riderModule.iml
/_ReSharper.Caches/
.idea

204
GaulishVillage/Board.cs Normal file
View File

@@ -0,0 +1,204 @@
namespace GaulishVillage;
public class Board
{
public List<Building> Buildings { get; private set; } = new();
public List<Entity> Entities { get; private set; } = new();
public TownHall TownHall { get; private set; }
public Board()
{
TownHall = new TownHall(5, 5);
Buildings.Add(TownHall);
}
public void AddBuilding(Building b) => Buildings.Add(b);
public void AddEntity(Entity e) => Entities.Add(e);
public void ProcessBuildings()
{
foreach (var b in Buildings)
{
if (b is ResourceGenerator rg)
rg.Generate();
}
}
public void UpdateEnemies()
{
foreach (var e in Entities)
{
if (e is Enemy enemy)
enemy.Move();
}
}
/*public void Render(Player player)
{
for (int y = 0; y < 10; y++)
{
for (int x = 0; x < 10; x++)
{
char c = '.';
if (player.X == x && player.Y == y)
c = 'P';
else if (TownHall.X == x && TownHall.Y == y)
c = 'H';
else
{
foreach (var b in Buildings)
if (b.X == x && b.Y == y)
c = 'B';
foreach (var e in Entities)
if (e.X == x && e.Y == y)
c = 'E';
}
Console.Write(c);
}
Console.WriteLine();
}
}*/
/*public void Render(Player player)
{
Console.Clear();
Console.ForegroundColor = ConsoleColor.DarkCyan;
Console.WriteLine("╔══════════════════════════════╗");
Console.WriteLine("║ Village des Gaulois ║");
Console.WriteLine("╚══════════════════════════════╝");
Console.ResetColor();
for (int y = 0; y < 10; y++)
{
for (int x = 0; x < 10; x++)
{
if (player.X == x && player.Y == y)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.Write("P");
}
else if (TownHall.X == x && TownHall.Y == y)
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.Write("H");
}
else
{
char c = '.';
ConsoleColor color = ConsoleColor.Gray;
foreach (var b in Buildings)
if (b.X == x && b.Y == y)
{
c = 'B';
color = ConsoleColor.Blue;
}
foreach (var e in Entities)
if (e.X == x && e.Y == y)
{
c = 'E';
color = ConsoleColor.Red;
}
Console.ForegroundColor = color;
Console.Write(c);
}
Console.ResetColor();
}
Console.WriteLine();
}
Console.WriteLine("────────────────────────────");
Console.WriteLine($"Gold: {player.Gold} | Elixir: {player.Elixir} | Position: ({player.X},{player.Y})");
Console.WriteLine("↑ ↓ ← → : bouger | G: mine | E: élixir | W: mur | B: caserne | C: collecter | T: troupe");
}*/
public void Render(Player player)
{
Console.Clear();
int width = 20;
int height = 20;
// Affichage carte
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
char c = ' ';
ConsoleColor color = ConsoleColor.Gray;
if (player.X == x && player.Y == y)
{
c = 'P';
color = ConsoleColor.Green;
}
else if (TownHall.X == x && TownHall.Y == y)
{
c = 'H';
color = ConsoleColor.Yellow;
}
else
{
foreach (var b in Buildings)
{
if (b.X == x && b.Y == y)
{
if (b is Wall)
{
c = 'W';
color = ConsoleColor.DarkGray;
}
else if (b is Barrack)
{
c = 'B';
color = ConsoleColor.Blue;
}
else if (b is GoldMine)
{
c = 'G';
color = ConsoleColor.Yellow;
}
else if (b is ElixirCollector)
{
c = 'E';
color = ConsoleColor.Magenta;
}
}
}
foreach (var e in Entities)
{
if (e.X == x && e.Y == y && e is Enemy)
{
c = 'R';
color = ConsoleColor.Red;
}
}
}
Console.ForegroundColor = color;
Console.Write(c);
Console.ResetColor();
}
Console.WriteLine();
}
// Panneau info
Console.WriteLine("────────────────────────────");
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine($"Score: {player.Gold + player.Elixir}");
Console.WriteLine($"Gold: {player.Gold}");
Console.WriteLine($"Elixir: {player.Elixir}");
Console.WriteLine($"TownHall HP: {TownHall.HP}");
Console.WriteLine($"Entities: {Entities.Count}");
Console.ResetColor();
Console.WriteLine("────────────────────────────");
Console.WriteLine("Commands: ↑↓←→ Move | G GoldMine | E Elixir | W Wall | B Barrack | C Collect | T Train | Q Quit");
}
}

View File

@@ -0,0 +1,6 @@
namespace GaulishVillage;
public class Barrack : Building
{
public override string ToString() => $"🏹 Barrack";
}

View File

@@ -0,0 +1,8 @@
namespace GaulishVillage;
public abstract class Building
{
public int X { get; set; }
public int Y { get; set; }
public int HP { get; set; } = 10;
}

View File

@@ -0,0 +1,7 @@
namespace GaulishVillage;
public class ElixirCollector : ResourceGenerator
{
public override void Generate() => Stock += 3;
public override string ToString() => $"🧪 Elixir Collector (Stock: {Stock})";
}

View File

@@ -0,0 +1,7 @@
namespace GaulishVillage;
public class GoldMine : ResourceGenerator
{
public override void Generate() => Stock += 5;
public override string ToString() => $"⛏️ Gold Mine (Stock: {Stock})";
}

View File

@@ -0,0 +1,7 @@
namespace GaulishVillage;
public abstract class ResourceGenerator : Building
{
public int Stock { get; set; }
public abstract void Generate();
}

View File

@@ -0,0 +1,13 @@
namespace GaulishVillage;
public class TownHall : Building
{
public TownHall(int x, int y)
{
X = x;
Y = y;
HP = 50;
}
public override string ToString() => $"🏛️ Town Hall (HP: {HP})";
}

View File

@@ -0,0 +1,6 @@
namespace GaulishVillage;
public class Wall : Building
{
public override string ToString() => $"🧱 Wall (HP: {HP})";
}

View File

@@ -0,0 +1,17 @@
namespace GaulishVillage;
public abstract class Entity
{
public int X { get; set; }
public int Y { get; set; }
protected Board Board;
public Entity(Board board)
{
Board = board;
X = 0;
Y = 0;
}
public abstract void Act();
}

View File

@@ -0,0 +1,12 @@
namespace GaulishVillage;
public class Bomberman : Enemy
{
public Bomberman(Board board) : base(board) {}
public override void Move()
{
Board.TownHall.HP = 0;
Console.WriteLine("💣 Bomberman détruit instantanément le Town Hall !");
}
}

View File

@@ -0,0 +1,9 @@
namespace GaulishVillage;
public abstract class Enemy : Entity
{
public Enemy(Board board) : base(board) {}
public abstract void Move();
public override void Act() { Move(); }
}

View File

@@ -0,0 +1,36 @@
namespace GaulishVillage;
public class Raider : Enemy
{
public Raider(Board board) : base(board) {}
public override void Move()
{
Building closest = null;
int minDist = int.MaxValue;
foreach (var b in Board.Buildings)
{
int dist = Utils.ManhattanDistance(X, Y, b.X, b.Y);
if (dist < minDist)
{
minDist = dist;
closest = b;
}
}
if (closest != null)
{
if (X < closest.X) X++;
else if (X > closest.X) X--;
else if (Y < closest.Y) Y++;
else if (Y > closest.Y) Y--;
if (X == closest.X && Y == closest.Y)
{
closest.HP -= 5;
Console.WriteLine($"💥 Raider attaque {closest.GetType().Name} !");
}
}
}
}

View File

@@ -0,0 +1,7 @@
namespace GaulishVillage;
public class Archer : Trainable
{
public Archer(Board board) : base(board) {}
}

View File

@@ -0,0 +1,6 @@
namespace GaulishVillage;
public class Barbarian : Trainable
{
public Barbarian(Board board) : base(board) {}
}

View File

@@ -0,0 +1,65 @@
namespace GaulishVillage;
public abstract class Trainable : Entity
{
public bool IsReturning = false;
public Trainable(Board board) : base(board) {}
public override void Act()
{
if (IsReturning)
ReturnToTownHall();
else
AttackEnemies();
}
protected void AttackEnemies()
{
Enemy closest = null;
int minDist = int.MaxValue;
foreach (var e in Board.Entities)
{
if (e is Enemy enemy)
{
int dist = Utils.ManhattanDistance(X, Y, enemy.X, enemy.Y);
if (dist < minDist)
{
minDist = dist;
closest = enemy;
}
}
}
if (closest != null)
{
if (X < closest.X) X++;
else if (X > closest.X) X--;
else if (Y < closest.Y) Y++;
else if (Y > closest.Y) Y--;
if (X == closest.X && Y == closest.Y)
{
Board.Entities.Remove(closest);
IsReturning = true;
}
}
else
{
IsReturning = true;
}
}
protected void ReturnToTownHall()
{
var th = Board.TownHall;
if (X < th.X) X++;
else if (X > th.X) X--;
else if (Y < th.Y) Y++;
else if (Y > th.Y) Y--;
if (X == th.X && Y == th.Y)
IsReturning = false;
}
}

View File

@@ -0,0 +1,76 @@
namespace GaulishVillage;
public class Player : Entity
{
public int Gold { get; private set; } = 50;
public int Elixir { get; private set; } = 30;
public Player(Board board) : base(board) {}
public override void Act() {}
public void HandleInput()
{
var key = Console.ReadKey(true).Key;
switch (key)
{
case ConsoleKey.UpArrow: Y--; break;
case ConsoleKey.DownArrow: Y++; break;
case ConsoleKey.LeftArrow: X--; break;
case ConsoleKey.RightArrow: X++; break;
case ConsoleKey.G: Build(new GoldMine()); break;
case ConsoleKey.E: Build(new ElixirCollector()); break;
case ConsoleKey.W: Build(new Wall()); break;
case ConsoleKey.B: Build(new Barrack()); break;
case ConsoleKey.C: CollectResources(); break;
case ConsoleKey.T: TrainTroop(); break;
}
}
private void Build(Building b)
{
b.X = X;
b.Y = Y;
Board.AddBuilding(b);
Gold -= 10;
}
private void CollectResources()
{
foreach (var b in Board.Buildings)
{
if (b.X == X && b.Y == Y && b is ResourceGenerator rg && rg.Stock > 0)
{
if (b is GoldMine)
Gold += rg.Stock;
else if (b is ElixirCollector)
Elixir += rg.Stock;
rg.Stock = 0;
}
}
}
private void TrainTroop()
{
foreach (var b in Board.Buildings)
{
if (b.X == X && b.Y == Y && b is Barrack)
{
if (Elixir >= 10)
{
var troop = new Archer(Board);
Board.AddEntity(troop);
Elixir -= 10;
Console.WriteLine("✅ Troupe recrutée !");
return;
}
}
}
Console.WriteLine("❌ Pas de Barrack ou pas assez d'Elixir !");
}
public void ShowStats()
{
Console.WriteLine($"Gold: {Gold} | Elixir: {Elixir} | Position: ({X},{Y})");
}
}

View File

@@ -0,0 +1,55 @@
namespace GaulishVillage;
public class GameEngine
{
public Board Board { get; private set; }
public Player Player { get; private set; }
private int turn = 0;
private int raiderSpawnDelay = 5;
public void Start()
{
Board = new Board();
Player = new Player(Board);
Board.AddEntity(Player);
while (true)
{
Console.Clear();
Board.Render(Player);
Player.ShowStats();
Board.ProcessBuildings();
ProcessEnemies();
Player.HandleInput();
if (Board.TownHall.HP <= 0)
{
Console.WriteLine("💥 Le Town Hall est détruit. Partie perdue !");
break;
}
Thread.Sleep(500);
turn++;
}
}
private void ProcessEnemies()
{
if (turn % raiderSpawnDelay == 0 && turn != 0)
{
Raider raider = new Raider(Board);
Board.AddEntity(raider);
}
if (turn == 200)
{
Bomberman bomber = new Bomberman(Board);
Board.AddEntity(bomber);
}
Board.UpdateEnemies();
}
}

View File

@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,16 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GaulishVillage", "GaulishVillage\GaulishVillage.csproj", "{80C37C64-D7C5-46E0-9C09-291DD7B10BEE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{80C37C64-D7C5-46E0-9C09-291DD7B10BEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{80C37C64-D7C5-46E0-9C09-291DD7B10BEE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{80C37C64-D7C5-46E0-9C09-291DD7B10BEE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{80C37C64-D7C5-46E0-9C09-291DD7B10BEE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

10
GaulishVillage/Program.cs Normal file
View File

@@ -0,0 +1,10 @@
namespace GaulishVillage;
class Program
{
static void Main(string[] args)
{
GameEngine game = new GameEngine();
game.Start();
}
}

9
GaulishVillage/Utils.cs Normal file
View File

@@ -0,0 +1,9 @@
namespace GaulishVillage;
public static class Utils
{
public static int ManhattanDistance(int x1, int y1, int x2, int y2)
{
return Math.Abs(x1 - x2) + Math.Abs(y1 - y2);
}
}

View File

@@ -0,0 +1,7 @@
{
"sdk": {
"version": "7.0.0",
"rollForward": "latestMinor",
"allowPrerelease": false
}
}

1
README Normal file
View File

@@ -0,0 +1 @@
vide