commit d58b58c067e399da01a1b3ec7237eb16115333e3 Author: Lucas Date: Sun Nov 30 13:03:47 2025 +0100 push de fin diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6d3c262 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +bin/ +obj/ +/packages/ +riderModule.iml +/_ReSharper.Caches/ +.idea + diff --git a/GaulishVillage/Board.cs b/GaulishVillage/Board.cs new file mode 100644 index 0000000..b6a455e --- /dev/null +++ b/GaulishVillage/Board.cs @@ -0,0 +1,204 @@ +namespace GaulishVillage; + +public class Board +{ + public List Buildings { get; private set; } = new(); + public List 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"); +} + + +} \ No newline at end of file diff --git a/GaulishVillage/Buildings/Barrack.cs b/GaulishVillage/Buildings/Barrack.cs new file mode 100644 index 0000000..df7eb72 --- /dev/null +++ b/GaulishVillage/Buildings/Barrack.cs @@ -0,0 +1,6 @@ +namespace GaulishVillage; + +public class Barrack : Building +{ + public override string ToString() => $"🏹 Barrack"; +} \ No newline at end of file diff --git a/GaulishVillage/Buildings/Building.cs b/GaulishVillage/Buildings/Building.cs new file mode 100644 index 0000000..522a929 --- /dev/null +++ b/GaulishVillage/Buildings/Building.cs @@ -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; +} \ No newline at end of file diff --git a/GaulishVillage/Buildings/ResourceGenerator/ElixirCollector.cs b/GaulishVillage/Buildings/ResourceGenerator/ElixirCollector.cs new file mode 100644 index 0000000..7b5f9ed --- /dev/null +++ b/GaulishVillage/Buildings/ResourceGenerator/ElixirCollector.cs @@ -0,0 +1,7 @@ +namespace GaulishVillage; + +public class ElixirCollector : ResourceGenerator +{ + public override void Generate() => Stock += 3; + public override string ToString() => $"🧪 Elixir Collector (Stock: {Stock})"; +} \ No newline at end of file diff --git a/GaulishVillage/Buildings/ResourceGenerator/GoldMine.cs b/GaulishVillage/Buildings/ResourceGenerator/GoldMine.cs new file mode 100644 index 0000000..cc78dd6 --- /dev/null +++ b/GaulishVillage/Buildings/ResourceGenerator/GoldMine.cs @@ -0,0 +1,7 @@ +namespace GaulishVillage; + +public class GoldMine : ResourceGenerator +{ + public override void Generate() => Stock += 5; + public override string ToString() => $"⛏️ Gold Mine (Stock: {Stock})"; +} \ No newline at end of file diff --git a/GaulishVillage/Buildings/ResourceGenerator/ResourceGenerator.cs b/GaulishVillage/Buildings/ResourceGenerator/ResourceGenerator.cs new file mode 100644 index 0000000..3842287 --- /dev/null +++ b/GaulishVillage/Buildings/ResourceGenerator/ResourceGenerator.cs @@ -0,0 +1,7 @@ +namespace GaulishVillage; + +public abstract class ResourceGenerator : Building +{ + public int Stock { get; set; } + public abstract void Generate(); +} \ No newline at end of file diff --git a/GaulishVillage/Buildings/TownHall.cs b/GaulishVillage/Buildings/TownHall.cs new file mode 100644 index 0000000..092351a --- /dev/null +++ b/GaulishVillage/Buildings/TownHall.cs @@ -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})"; +} \ No newline at end of file diff --git a/GaulishVillage/Buildings/Wall.cs b/GaulishVillage/Buildings/Wall.cs new file mode 100644 index 0000000..fe9a164 --- /dev/null +++ b/GaulishVillage/Buildings/Wall.cs @@ -0,0 +1,6 @@ +namespace GaulishVillage; + +public class Wall : Building +{ + public override string ToString() => $"🧱 Wall (HP: {HP})"; +} \ No newline at end of file diff --git a/GaulishVillage/Entity/Entity.cs b/GaulishVillage/Entity/Entity.cs new file mode 100644 index 0000000..842af5b --- /dev/null +++ b/GaulishVillage/Entity/Entity.cs @@ -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(); +} \ No newline at end of file diff --git a/GaulishVillage/Entity/Npc/Enemy/Bomberman.cs b/GaulishVillage/Entity/Npc/Enemy/Bomberman.cs new file mode 100644 index 0000000..b1723e5 --- /dev/null +++ b/GaulishVillage/Entity/Npc/Enemy/Bomberman.cs @@ -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 !"); + } +} \ No newline at end of file diff --git a/GaulishVillage/Entity/Npc/Enemy/Enemy.cs b/GaulishVillage/Entity/Npc/Enemy/Enemy.cs new file mode 100644 index 0000000..3b24310 --- /dev/null +++ b/GaulishVillage/Entity/Npc/Enemy/Enemy.cs @@ -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(); } +} \ No newline at end of file diff --git a/GaulishVillage/Entity/Npc/Enemy/Raider.cs b/GaulishVillage/Entity/Npc/Enemy/Raider.cs new file mode 100644 index 0000000..b9d7a15 --- /dev/null +++ b/GaulishVillage/Entity/Npc/Enemy/Raider.cs @@ -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} !"); + } + } + } +} \ No newline at end of file diff --git a/GaulishVillage/Entity/Npc/Trainable/Archer.cs b/GaulishVillage/Entity/Npc/Trainable/Archer.cs new file mode 100644 index 0000000..3ddcff2 --- /dev/null +++ b/GaulishVillage/Entity/Npc/Trainable/Archer.cs @@ -0,0 +1,7 @@ +namespace GaulishVillage; + + +public class Archer : Trainable +{ + public Archer(Board board) : base(board) {} +} \ No newline at end of file diff --git a/GaulishVillage/Entity/Npc/Trainable/Barbarian.cs b/GaulishVillage/Entity/Npc/Trainable/Barbarian.cs new file mode 100644 index 0000000..7de5ef3 --- /dev/null +++ b/GaulishVillage/Entity/Npc/Trainable/Barbarian.cs @@ -0,0 +1,6 @@ +namespace GaulishVillage; + +public class Barbarian : Trainable +{ + public Barbarian(Board board) : base(board) {} +} diff --git a/GaulishVillage/Entity/Npc/Trainable/Trainable.cs b/GaulishVillage/Entity/Npc/Trainable/Trainable.cs new file mode 100644 index 0000000..4ed6fc6 --- /dev/null +++ b/GaulishVillage/Entity/Npc/Trainable/Trainable.cs @@ -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; + } +} \ No newline at end of file diff --git a/GaulishVillage/Entity/Player.cs b/GaulishVillage/Entity/Player.cs new file mode 100644 index 0000000..d5fdebb --- /dev/null +++ b/GaulishVillage/Entity/Player.cs @@ -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})"); + } +} \ No newline at end of file diff --git a/GaulishVillage/GameEngine.cs b/GaulishVillage/GameEngine.cs new file mode 100644 index 0000000..10f40a6 --- /dev/null +++ b/GaulishVillage/GameEngine.cs @@ -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(); + } +} \ No newline at end of file diff --git a/GaulishVillage/GaulishVillage.csproj b/GaulishVillage/GaulishVillage.csproj new file mode 100644 index 0000000..2b14c81 --- /dev/null +++ b/GaulishVillage/GaulishVillage.csproj @@ -0,0 +1,10 @@ + + + + Exe + net7.0 + enable + enable + + + diff --git a/GaulishVillage/GaulishVillage.sln b/GaulishVillage/GaulishVillage.sln new file mode 100644 index 0000000..7f49665 --- /dev/null +++ b/GaulishVillage/GaulishVillage.sln @@ -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 diff --git a/GaulishVillage/Program.cs b/GaulishVillage/Program.cs new file mode 100644 index 0000000..2d08cda --- /dev/null +++ b/GaulishVillage/Program.cs @@ -0,0 +1,10 @@ +namespace GaulishVillage; + +class Program +{ + static void Main(string[] args) + { + GameEngine game = new GameEngine(); + game.Start(); + } +} \ No newline at end of file diff --git a/GaulishVillage/Utils.cs b/GaulishVillage/Utils.cs new file mode 100644 index 0000000..a3ba73f --- /dev/null +++ b/GaulishVillage/Utils.cs @@ -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); + } +} \ No newline at end of file diff --git a/GaulishVillage/global.json b/GaulishVillage/global.json new file mode 100644 index 0000000..aaac9e0 --- /dev/null +++ b/GaulishVillage/global.json @@ -0,0 +1,7 @@ +{ + "sdk": { + "version": "7.0.0", + "rollForward": "latestMinor", + "allowPrerelease": false + } +} \ No newline at end of file diff --git a/README b/README new file mode 100644 index 0000000..6a29d11 --- /dev/null +++ b/README @@ -0,0 +1 @@ +vide