Ajout de la map statique #8

Merged
mcmuzzle merged 1 commits from 1_ajoutMapStatique into main 2025-03-26 22:23:03 +00:00
16 changed files with 374 additions and 25 deletions

BIN
Graphics/plan.pdn Normal file

Binary file not shown.

View File

@@ -9,7 +9,7 @@ namespace Giants.Application;
/// </summary>
public class MatchRepositoryMock : IMatchRepository
{
private readonly IHexagonalGrid _gridLayout;
private readonly BoardLayout _boardLayout;
private static int _lastId = 1;
private Dictionary<int, Match> _matchs = new Dictionary<int, Match>();
@@ -17,9 +17,9 @@ public class MatchRepositoryMock : IMatchRepository
/// <summary>
/// constructeur
/// </summary>
public MatchRepositoryMock()
public MatchRepositoryMock(BoardLayout boardLayout)
{
_gridLayout = new HexagonalGridImpl();
_boardLayout = boardLayout;
}
/// <inheritdoc/>
@@ -35,9 +35,10 @@ public class MatchRepositoryMock : IMatchRepository
/// <inheritdoc/>
public Match CreateMatch()
{
Match result = new Match(_gridLayout)
Match result = new Match()
{
Id = _lastId++
Id = _lastId++,
Board = _boardLayout,
};
AddStaticData(result);
@@ -52,4 +53,8 @@ public class MatchRepositoryMock : IMatchRepository
}
public void SetMapData(IHexagonalGrid grid)
{
throw new NotImplementedException();
}
}

View File

@@ -0,0 +1,43 @@
using Giants.Core.Interfaces;
namespace Giants.Core.Commands;
/// <summary>
/// Logique metier qui permet d'ajouter les données statiques aux matchs qui arrivent du repository
/// </summary>
public class GetMatchCommand : BaseCommand<GetMatchResult>
{
private IMatchRepository _repo;
/// <summary> L'id du match a récupérer </summary>
public required int MatchId { get; init; }
public GetMatchCommand(IMatchRepository repo)
{
_repo = repo;
}
protected override GetMatchResult LocalExecute()
{
Match? m = _repo.GetMatch(MatchId);
if (null != m)
{
GetMatchResult result = new GetMatchResult()
{
Success = true,
Match = m
};
return result;
}
return new GetMatchResult() { };
}
}
public class GetMatchResult : BaseCommandResult
{
/// <summary> Le match si success null sinon </summary>
public Match? Match { get; init; }
}

View File

@@ -11,19 +11,15 @@ namespace Giants.Core;
public class Match
{
#region données statiques
public int Id { get; init; }
IHexagonalGrid _grid;
public required BoardLayout Board { get; init; }
#endregion
#region données dynamiques
#endregion
/// <summary> Construction de base </summary>
/// <param name="grid"> La grid du jeu</param>
public Match(IHexagonalGrid grid)
{
_grid = grid;
}
/// <summary> Permet de comparer des Match, cette methode est critique pour l'ia pour reduire son parcour d'arbre </summary>
/// <param name="obj"></param>

View File

@@ -5,5 +5,32 @@ namespace Giants.Core.Interfaces;
/// </summary>
public interface IHexagonalGrid
{
/// <summary>
/// indique le style de grille, voir https://www.redblobgames.com/grids/hexagons/ pour des détails
/// </summary>
public enum HexStyle
{
/// <summary> Pointe vers le haut, impaire a droite </summary>
PointyOdd,
/// <summary> Pointe vers le haut, pair a droite </summary>
PointyEven,
/// <summary> Pointe vers le coté, impaire en bas</summary>
FlatOdd,
/// <summary> Pointe vers le coté, impaire en haut</summary>
FlatEven
}
/// <summary>
/// Demande a la grille d'allouer sa taille et son type
/// </summary>
/// <param name="style">le style de grid</param>
public void Init(HexStyle style = HexStyle.PointyOdd);
/// <summary>
/// Permet de recupérer la liste des tiles voisines d'une tile fournie en parametre
/// </summary>
/// <param name="coords">La tuile de laquelle on cherche les voisins</param>
/// <returns>la liste des tiles voisines</returns>
public ICollection<AxialCoords> GetNeighbours(AxialCoords coords);
}

View File

@@ -1,7 +1,7 @@
namespace Giants.Core.Interfaces;
/// <summary>
/// Interface de tout fournisseur de match, ils sont responsable d'instancier les match a partir d'un ID ou d'en créer des nouveaux
/// Interface de tout fournisseur de match, ils récupere les données dynamiques d'un match
/// </summary>
public interface IMatchRepository
{
@@ -17,4 +17,9 @@ public interface IMatchRepository
/// </summary>
/// <returns>le nouveau match a son état initial</returns>
Match? CreateMatch();
/// <summary>
/// Fournir au repository la map a assigner aux match instanciés
/// </summary>
public void SetMapData(IHexagonalGrid grid);
}

View File

@@ -0,0 +1,19 @@
namespace Giants.Core;
public struct AxialCoords
{
public int Q { get; init; }
public int R { get; init; }
public AxialCoords(int Q, int R)
{
this.Q = Q;
this.R = R;
}
public AxialCoords()
{
Q = 0;
R = 0;
}
}

View File

@@ -1,9 +1,109 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.RegularExpressions;
using Giants.Core.Interfaces;
namespace Giants.Core;
/// <summary>
/// Represente l'organisation d'un plateau, il ne contient aucune informations liées a une partie mais il permet
/// d'effectuer des recherches de chemins ou de type de tuiles
/// noter que cette classe doit être immuable comme c'est un valueObjet, donc pas des setter autre que init
/// </summary>
public class BoardLayout
{
IHexagonalGrid _grid;
Dictionary<int, TileInfos> _tiles;
int width = 16;
public BoardLayout(IHexagonalGrid gridSystem)
{
_grid = gridSystem;
BuildDefaultBoard();
}
public ICollection<AxialCoords> GetNeighbours(AxialCoords coords)
{
var tmp = _grid.GetNeighbours(coords);
return tmp.Where(t => _tiles.ContainsKey(Index(t.Q, t.R))).ToList();
}
[MemberNotNull(nameof(_tiles))]
private void BuildDefaultBoard()
{
_grid.Init(IHexagonalGrid.HexStyle.FlatOdd);
//creation des tiles depuis la position bas gauche vers le haut puis la droite
_tiles = new Dictionary<int, TileInfos>();
AddTile(new TileInfos() { Q = 1, R = 6, TileType = TileTypes.Basic, AhusAccess = new List<AxialCoords>() { new AxialCoords(-1, 0) } });
AddTile(new TileInfos() { Q = 2, R = 7, TileType = TileTypes.Basic, AhusAccess = new List<AxialCoords>() { new AxialCoords(0, 1) } });
AddTile(new TileInfos() { Q = 2, R = 6, TileType = TileTypes.Village });
AddTile(new TileInfos() { Q = 2, R = 5, TileType = TileTypes.Basic, AhusAccess = new List<AxialCoords>() { new AxialCoords(-1, 0) } });
AddTile(new TileInfos() { Q = 2, R = 4, TileType = TileTypes.Basic, AhusAccess = new List<AxialCoords>() { new AxialCoords(-1, 0) } });
AddTile(new TileInfos() { Q = 3, R = 6, TileType = TileTypes.Basic, AhusAccess = new List<AxialCoords>() { new AxialCoords(0, 1) } });
AddTile(new TileInfos() { Q = 3, R = 5, TileType = TileTypes.Basic });
AddTile(new TileInfos() { Q = 3, R = 4, TileType = TileTypes.HatCarry });
AddTile(new TileInfos() { Q = 3, R = 3, TileType = TileTypes.Basic, AhusAccess = new List<AxialCoords>() { new AxialCoords(-1, 0) } });
AddTile(new TileInfos() { Q = 3, R = 2, TileType = TileTypes.Basic, AhusAccess = new List<AxialCoords>() { new AxialCoords(-1, 0) } });
AddTile(new TileInfos() { Q = 3, R = 1, TileType = TileTypes.Basic, AhusAccess = new List<AxialCoords>() { new AxialCoords(-1, 0) } });
AddTile(new TileInfos() { Q = 4, R = 6, TileType = TileTypes.Basic, AhusAccess = new List<AxialCoords>() { new AxialCoords(0, 1) } });
AddTile(new TileInfos() { Q = 4, R = 5, TileType = TileTypes.Basic });
AddTile(new TileInfos() { Q = 4, R = 4, TileType = TileTypes.Basic });
AddTile(new TileInfos() { Q = 4, R = 3, TileType = TileTypes.Basic });
AddTile(new TileInfos() { Q = 4, R = 2, TileType = TileTypes.Forest });
AddTile(new TileInfos() { Q = 4, R = 1, TileType = TileTypes.Forest });
AddTile(new TileInfos() { Q = 4, R = 0, TileType = TileTypes.Basic, AhusAccess = new List<AxialCoords>() { new AxialCoords(0, -1) } });
AddTile(new TileInfos() { Q = 5, R = 4, TileType = TileTypes.Basic });
AddTile(new TileInfos() { Q = 5, R = 3, TileType = TileTypes.Basic });
AddTile(new TileInfos() { Q = 5, R = 2, TileType = TileTypes.Forest });
AddTile(new TileInfos() { Q = 5, R = 1, TileType = TileTypes.Forest });
AddTile(new TileInfos() { Q = 5, R = 0, TileType = TileTypes.Forest });
AddTile(new TileInfos() { Q = 5, R = -1, TileType = TileTypes.Basic, AhusAccess = new List<AxialCoords>() { new AxialCoords(-1, 0), new AxialCoords(0, -1), new AxialCoords(1, -1) } });
AddTile(new TileInfos() { Q = 6, R = 4, TileType = TileTypes.Basic, AhusAccess = new List<AxialCoords>() { new AxialCoords(0, 1) } });
AddTile(new TileInfos() { Q = 6, R = 3, TileType = TileTypes.Basic });
AddTile(new TileInfos() { Q = 6, R = 2, TileType = TileTypes.Basic });
AddTile(new TileInfos() { Q = 6, R = 1, TileType = TileTypes.Forest });
AddTile(new TileInfos() { Q = 6, R = 0, TileType = TileTypes.Forest });
AddTile(new TileInfos() { Q = 6, R = -1, TileType = TileTypes.Basic });
AddTile(new TileInfos() { Q = 7, R = 3, TileType = TileTypes.Basic, AhusAccess = new List<AxialCoords>() { new AxialCoords(0, 1) } });
AddTile(new TileInfos() { Q = 7, R = 2, TileType = TileTypes.Basic });
AddTile(new TileInfos() { Q = 7, R = 1, TileType = TileTypes.Basic });
AddTile(new TileInfos() { Q = 7, R = 0, TileType = TileTypes.Basic });
AddTile(new TileInfos() { Q = 7, R = -1, TileType = TileTypes.Basic, AhusAccess = new List<AxialCoords>() { new AxialCoords(1, -1) } });
AddTile(new TileInfos() { Q = 8, R = 2, TileType = TileTypes.Basic, AhusAccess = new List<AxialCoords>() { new AxialCoords(0, 1) } });
AddTile(new TileInfos() { Q = 8, R = 1, TileType = TileTypes.Hut });
AddTile(new TileInfos() { Q = 8, R = 0, TileType = TileTypes.Basic });
AddTile(new TileInfos() { Q = 8, R = -1, TileType = TileTypes.Basic, AhusAccess = new List<AxialCoords>() { new AxialCoords(1, -1) } });
AddTile(new TileInfos() { Q = 9, R = 1, TileType = TileTypes.Basic });
AddTile(new TileInfos() { Q = 9, R = 0, TileType = TileTypes.Basic });
AddTile(new TileInfos() { Q = 9, R = -1, TileType = TileTypes.Basic, AhusAccess = new List<AxialCoords>() { new AxialCoords(1, -1) } });
AddTile(new TileInfos() { Q = 10, R = 1, TileType = TileTypes.Basic, AhusAccess = new List<AxialCoords>() { new AxialCoords(0, 1) } });
AddTile(new TileInfos() { Q = 10, R = 0, TileType = TileTypes.Basic });
AddTile(new TileInfos() { Q = 10, R = -1, TileType = TileTypes.Basic });
AddTile(new TileInfos() { Q = 11, R = 1, TileType = TileTypes.Basic, AhusAccess = new List<AxialCoords>() { new AxialCoords(0, 1) } });
AddTile(new TileInfos() { Q = 11, R = 0, TileType = TileTypes.MoaiCarry });
AddTile(new TileInfos() { Q = 11, R = -1, TileType = TileTypes.Basic, AhusAccess = new List<AxialCoords>() { new AxialCoords(1, -1) } });
AddTile(new TileInfos() { Q = 12, R = 0, TileType = TileTypes.Basic, AhusAccess = new List<AxialCoords>() { new AxialCoords(0, 1) } });
AddTile(new TileInfos() { Q = 12, R = -1, TileType = TileTypes.Basic });
AddTile(new TileInfos() { Q = 13, R = 0, TileType = TileTypes.Basic, AhusAccess = new List<AxialCoords>() { new AxialCoords(0, 1) } });
AddTile(new TileInfos() { Q = 13, R = -1, TileType = TileTypes.Basic });
AddTile(new TileInfos() { Q = 13, R = -2, TileType = TileTypes.Basic });
AddTile(new TileInfos() { Q = 14, R = -1, TileType = TileTypes.Basic, AhusAccess = new List<AxialCoords>() { new AxialCoords(1, 0) } });
AddTile(new TileInfos() { Q = 14, R = -2, TileType = TileTypes.Basic, AhusAccess = new List<AxialCoords>() { new AxialCoords(1, -1) } });
}
private void AddTile(TileInfos t)
{
_tiles.Add(Index(t.Q, t.R), t);
}
private int Index(int q, int r)
{
return q * width + r;
}
}

View File

@@ -5,4 +5,12 @@ namespace Giants.Core;
/// </summary>
public class TileInfos
{
public int Q { get; init; }
public int R { get; init; }
public TileTypes TileType { get; init; } = TileTypes.Unknown;
/// <summary> La liste des directions dans laquel un ahu est accessible depuis cet tile </summary>
public ICollection<AxialCoords> AhusAccess { get; init; } = new List<AxialCoords>();
}

View File

@@ -1,5 +0,0 @@
namespace Giants.Core;
public class TilePosition
{
}

View File

@@ -0,0 +1,19 @@
namespace Giants.Core;
public enum TileTypes
{
/// <summary> Tile inconnu </summary>
Unknown,
/// <summary> Tile de type de base, rien de spécial</summary>
Basic,
/// <summary> Une foret qui fourni les billots </summary>
Forest,
/// <summary> La tuile du village, recruter des ouvriers </summary>
Village,
/// <summary> Carriere de moai </summary>
MoaiCarry,
/// <summary> Carriere de chapeau </summary>
HatCarry,
/// <summary> Maison du magicien </summary>
Hut
}

View File

@@ -1,16 +1,41 @@
namespace Giants.Infrastructure;
using Giants.Core;
using Giants.Core.Interfaces;
using HexagonalLib;
using HexagonalLib.Coordinates;
public class HexagonalGridImpl : IHexagonalGrid
{
private readonly HexagonalGrid _grid;
private HexagonalGrid _grid;
public HexagonalGridImpl()
/// <inheritdoc/>
public void Init(IHexagonalGrid.HexStyle style = IHexagonalGrid.HexStyle.PointyOdd)
{
_grid = new HexagonalGrid(HexagonalGridType.PointyEven, 1.0f);
_grid = new HexagonalGrid(ConvertGridType(style), 1.0f);
}
public ICollection<AxialCoords> GetNeighbours(AxialCoords coords)
{
var result = new List<AxialCoords>();
foreach (var hex in _grid.GetNeighbors(new Axial(coords.Q, coords.R)))
{
result.Add(new AxialCoords(hex.Q, hex.R));
}
return result;
}
private HexagonalGridType ConvertGridType(IHexagonalGrid.HexStyle style)
{
return style switch
{
IHexagonalGrid.HexStyle.PointyEven => HexagonalGridType.PointyEven,
IHexagonalGrid.HexStyle.FlatEven => HexagonalGridType.FlatEven,
IHexagonalGrid.HexStyle.PointyOdd => HexagonalGridType.PointyOdd,
IHexagonalGrid.HexStyle.FlatOdd => HexagonalGridType.FlatOdd,
_ => throw new ArgumentOutOfRangeException(nameof(style), $"Unexpected grid style : {style}"),
};
}
}

View File

@@ -3,10 +3,20 @@ namespace Giants.Core.Tests;
using Giants.Application;
using Giants.Core.Commands;
using Giants.Core.Interfaces;
using Giants.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
public class ApplicationTests
{
private readonly IMatchRepository _repo;
public ApplicationTests()
{
IHexagonalGrid _grid = new HexagonalGridImpl();
BoardLayout layout = new BoardLayout(_grid);
_repo = new MatchRepositoryMock(layout);
}
[Fact]
public void ApplicationCreationExample()
{
@@ -17,10 +27,8 @@ public class ApplicationTests
public void TryingServiceInjection()
{
// creation des instances
IMatchRepository matchRepository = new MatchRepositoryMock();
var serviceCollection = new ServiceCollection();
serviceCollection.AddScoped(repo => matchRepository);
serviceCollection.AddScoped(repo => _repo);
// Ajout des commandes disponibles
serviceCollection.AddScoped<NewMatchCommand>();

View File

@@ -0,0 +1,45 @@
namespace Giants.Core.Tests;
using Giants.Application;
using Giants.Core.Commands;
using Giants.Core.Interfaces;
using Giants.Infrastructure;
public class GetMatchCommandTest
{
private readonly IMatchRepository _repo;
public GetMatchCommandTest()
{
IHexagonalGrid _grid = new HexagonalGridImpl();
BoardLayout layout = new BoardLayout(_grid);
_repo = new MatchRepositoryMock(layout);
var match1 = _repo.CreateMatch();
}
[Fact]
public void GetMatchNotExisting()
{
GetMatchCommand command = new GetMatchCommand(_repo)
{
MatchId = 2
};
GetMatchResult result = command.Execute();
Assert.False(result.Success);
Assert.Null(result.Match);
}
[Fact]
public void GetMatchSimple()
{
GetMatchCommand command = new GetMatchCommand(_repo)
{
MatchId = 1
};
GetMatchResult result = command.Execute();
Assert.True(result.Success);
Assert.NotNull(result.Match);
}
}

View File

@@ -3,10 +3,18 @@ namespace Giants.Core.Tests;
using Giants.Application;
using Giants.Core.Commands;
using Giants.Core.Interfaces;
using Giants.Infrastructure;
public class NewMatchCommandTest
{
private readonly IMatchRepository _repo = new MatchRepositoryMock();
private readonly IMatchRepository _repo;
public NewMatchCommandTest()
{
IHexagonalGrid _grid = new HexagonalGridImpl();
BoardLayout layout = new BoardLayout(_grid);
_repo = new MatchRepositoryMock(layout);
}
[Fact]
public void CreateBasicMatch()

View File

@@ -0,0 +1,46 @@
using Giants.Core.Interfaces;
using Giants.Infrastructure;
namespace Giants.Core.Tests;
public class BoardLayoutTests
{
[Fact]
public void TestNeighbour()
{
IHexagonalGrid grid = new HexagonalGridImpl();
BoardLayout layout = new BoardLayout(grid);
var test = layout.GetNeighbours(new AxialCoords(2, 6)).ToList();
foreach (var voisin in new List<AxialCoords>() {
new AxialCoords(3,5),
new AxialCoords(1,6),
new AxialCoords(3,6),
new AxialCoords(2,5),
new AxialCoords(2,7),
})
{
Assert.Contains(voisin, test);
}
Assert.Equal(5, test.Count);
}
[Fact]
public void TestNeighbourWhenAhu()
{
IHexagonalGrid grid = new HexagonalGridImpl();
BoardLayout layout = new BoardLayout(grid);
var test = layout.GetNeighbours(new AxialCoords(14, -2)).ToList();
foreach (var voisin in new List<AxialCoords>() {
new AxialCoords(13,-2),
new AxialCoords(13,-1),
new AxialCoords(14,-1),
})
{
Assert.Contains(voisin, test);
}
Assert.Equal(3, test.Count);
}
}