Skip to content

Commit

Permalink
[#14]: move into helper, include bank
Browse files Browse the repository at this point in the history
  • Loading branch information
3k-dome committed May 7, 2023
1 parent 6f7443a commit a0f20d5
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 35 deletions.
132 changes: 132 additions & 0 deletions catan-lib/Helpers/ProductionPhase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
using CatanLib.Enums;
using CatanLib.Interfaces.Components;
using HexagonLib;
using System.Diagnostics;

namespace CatanLib.Helpers
{
public static class ProductionPhase
{
public static IEnumerable<ITerrainTile> GetProducingTiles(Dictionary<TileCoordinate, IHexTile> tileStore, int roll)
{
return tileStore.Select(entry => entry.Value)
.OfType<ITerrainTile>()
.Where(tile => tile.Production.Roll == roll);
}

public static IEnumerable<ISettlement> GetSettlements(Dictionary<VertexCoordinate, ISettlement> vertexStore, ITerrainTile tile)
{
return tile.Coordinate.Vertices()
.Select(vertexCoordinate => vertexStore[vertexCoordinate])
.Where(settlement => settlement.IsSettlement || settlement.IsCity);
}

public static IEnumerable<ResourceType> GetTotalYield(Dictionary<VertexCoordinate, ISettlement> vertexStore, IEnumerable<ITerrainTile> tiles)
{
IEnumerable<ResourceType> totalYield = Enumerable.Empty<ResourceType>();

foreach (ITerrainTile tile in tiles)
{
ResourceType resource = TerrainResources.Resources[tile.Terrain];
IEnumerable<ISettlement> settlements = GetSettlements(vertexStore, tile);
IEnumerable<ResourceType> tileProduction = settlements
.SelectMany(settlement => settlement.IsSettlement ? new[] { resource } : new[] { resource, resource });

totalYield = totalYield.Concat(tileProduction);
}

return totalYield;
}

public static void DistributeResources(Dictionary<VertexCoordinate, ISettlement> vertexStore, IEnumerable<ITerrainTile> tiles, IBank bank)
{
foreach (ITerrainTile tile in tiles)
{
ResourceType resource = TerrainResources.Resources[tile.Terrain];
IEnumerable<ISettlement> settlements = GetSettlements(vertexStore, tile);

foreach (ISettlement settlement in settlements)
{
if (settlement.IsSettlement)
{
GainResource(bank, settlement, resource);
continue;
}

if (settlement.IsCity)
{
GainResources(bank, settlement, new[] { resource, resource });
continue;
}
}
}
}

public static void GainResource(IBank bank, ISettlement settlement, ResourceType resource)
{
bank.UseResource(resource);
settlement.Belongs?.GainResource(resource);
}

public static void GainResources(IBank bank, ISettlement settlement, IEnumerable<ResourceType> resources)
{
bank.UseResources(resources);
settlement.Belongs?.GainResources(resources);
}

public static int GetPlayerCount(Dictionary<VertexCoordinate, ISettlement> vertexStore, IEnumerable<ITerrainTile> tiles)
{
return tiles.SelectMany(tile => tile.Coordinate.Vertices())
.Select(vertexCoordinate => vertexStore[vertexCoordinate])
.Where(settlement => settlement.IsSettlement || settlement.IsCity)
.Select(settlement =>
{
Debug.Assert(settlement.Belongs != null);
return settlement.Belongs;
})
.Distinct()
.Count();
}

public static void TryDistributeResources(Dictionary<VertexCoordinate, ISettlement> vertexStore, IEnumerable<ITerrainTile> tiles, IBank bank)
{
foreach (ITerrainTile tile in tiles)
{
ResourceType resource = TerrainResources.Resources[tile.Terrain];
IEnumerable<ISettlement> settlements = GetSettlements(vertexStore, tile);

foreach (ISettlement settlement in settlements)
{
if (settlement.IsSettlement)
{
TryGainResource(bank, settlement, resource);
continue;
}

if (settlement.IsCity)
{
TryGainResources(bank, settlement, new[] { resource, resource });
continue;
}
}
}
}

public static void TryGainResource(IBank bank, ISettlement settlement, ResourceType resource)
{
if (bank.HasResource(resource))
{
bank.UseResource(resource);
settlement.Belongs?.GainResource(resource);
}
}

public static void TryGainResources(IBank bank, ISettlement settlement, IEnumerable<ResourceType> resources)
{
foreach (ResourceType resource in resources)
{
TryGainResource(bank, settlement, resource);
}
}
}
}
49 changes: 14 additions & 35 deletions catan-lib/Parts/Catan.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using CatanLib.Enums;
using CatanLib.Helpers;
using CatanLib.Interfaces.Components;

namespace CatanLib.Parts
Expand All @@ -9,13 +10,15 @@ public class Catan<TSettlement, TRoad, TDice> : ICatan
where TDice : IDice, new()
{
public IDice Dice { get; private set; }
public IBank Bank { get; private set; }
public Board Board { get; private set; }
public IEnumerable<IPlayer> Players { get; private set; }
public IPlayer CurrentPlayer => Players.First();

public Catan(IEnumerable<IPlayer> players, int seed)
{
Dice = new TDice() { Random = new Random(seed) };
Bank = new Bank();
Board = Board.BoardFactory<TSettlement, TRoad>(Dice);
Players = players.OrderBy(_ => Dice.RollTwice());

Expand All @@ -38,49 +41,25 @@ private void CounterClockwise()

private void SettlementPhase()
{
//// only allow placement of one settlement

//Board.VertexStore.Select(entry => entry.Value)

//VertexCoordinate coordinate;

//// only allow placement of one road
//_ = Board.EdgeStore.Select(entry => entry.Key)
// .Where(edge => edge.VertexA == coordinate || edge.VertexB == coordinate);
}

private void ResourceProductionPhase()
{
int roll = Dice.RollTwice();

// find all tiles that match the roll
IEnumerable<ITerrainTile> tiles = Board.TileStore
.Select(entry => entry.Value)
.OfType<ITerrainTile>()
.Where(tile => tile.Production.Roll == roll);
IEnumerable<ITerrainTile> producingTiles = ProductionPhase.GetProducingTiles(Board.TileStore, Dice.RollTwice());
IEnumerable<ResourceType> totalYield = ProductionPhase.GetTotalYield(Board.VertexStore, producingTiles);

// all players gain resouces if the bank can provide the total yield
if (Bank.HasResources(totalYield))
{
ProductionPhase.DistributeResources(Board.VertexStore, producingTiles, Bank);
}

foreach (ITerrainTile tile in tiles)
// if only one player would gain resources he gains as much as possible
else if (ProductionPhase.GetPlayerCount(Board.VertexStore, producingTiles) == 1)
{
// find all settlements surrounding one of the matching tiles
IEnumerable<ISettlement> settlements = tile.Coordinate.Vertices()
.Select(vertexCoordinate => Board[vertexCoordinate])
.Where(settlement => settlement.IsSettlement || settlement.IsCity);

// add resouces to each settlement and city
foreach (ISettlement settlement in settlements)
{
if (settlement.IsSettlement)
{
settlement.Belongs?.GainResource(TerrainResources.Resources[tile.Terrain]);
continue;
}

if (settlement.IsCity)
{
settlement.Belongs?.GainResources(new[] { TerrainResources.Resources[tile.Terrain], TerrainResources.Resources[tile.Terrain] });
continue;
}
}
ProductionPhase.TryDistributeResources(Board.VertexStore, producingTiles, Bank);
}
}

Expand Down

0 comments on commit a0f20d5

Please sign in to comment.