using GameModel.DeathGame; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace GameHandler.DeathGame { public delegate void CoffinCompleted(Coffin coffin); public class DeathGameHandler { const int MIN_PLAYER_COUNT = 3; const int MAX_PLAYER_COUNT = 12; const int MIN_COFFIN_SIZE = 6; const int MAX_COFFIN_SIZE = 12; public event CoffinCompleted CoffinCompleted; private static Random random = new Random(); private void ValidatePlayerCount(int playerCount) { if (playerCount < MIN_PLAYER_COUNT) { throw new InvalidDataException($"MaxPlayerCount must be at least {MIN_PLAYER_COUNT}"); } if (playerCount > MAX_PLAYER_COUNT) { throw new InvalidDataException($"MaxPlayerCount cannot be greater than {MAX_PLAYER_COUNT}"); } } private void ValidateGameSettings(DeathGameSettings deathGameSettings) { if (deathGameSettings.MaxCoffinSize < MIN_COFFIN_SIZE || deathGameSettings.MaxCoffinSize > MAX_COFFIN_SIZE ) { throw new InvalidDataException($"Max coffin size must be from {MIN_COFFIN_SIZE} to {MAX_COFFIN_SIZE}"); } } public DeathGameHandler() { } public DeathGameModel InitGameModel(int[] playerIds, DeathGameSettings deathGameSettings) { ValidatePlayerCount(playerIds.Count()); ValidateGameSettings(deathGameSettings); var coffins = new List(); foreach (var playerId in playerIds) { if (coffins.Any(_ => _.PlayerId.Equals(playerId))) { throw new InvalidDataException($"player {playerId} already exists"); } coffins.Add(new Coffin(playerId,0,0)); } return new DeathGameModel(1, coffins.OrderBy(_ => random.Next()).ToList().ToArray(), deathGameSettings); } public DeathGameModel CalcNextModel(DeathGameModel gm, int pinCount, bool isTrowIntoAllPins, bool boardCleared) { var incLine = false; var incX = false; if (gm.Id == 1) // first round in game { incX = true; if (pinCount < 3) { incLine = true; } } if (isTrowIntoAllPins) { incX = true; } if (pinCount == 0) { incLine = true; } var current = gm.Coffins.First(); var next = gm.Coffins.Skip(1).First(); var previous = gm.Coffins.Last(); Coffin? currentUpdated = null; Coffin? nextUpdated = next; Coffin? previousUpdated = previous; var xCount = current.XCount; var lineCount = current.LineCount; if ((current.XCount == 2) && incX) { xCount = 0; lineCount++; } if (incLine) { lineCount++; } if (incX) { xCount++; } currentUpdated = current with { LineCount = lineCount, XCount = xCount }; if (lineCount > gm.deathGameSettings.MaxCoffinSize) { CoffinCompleted?.Invoke(currentUpdated); currentUpdated = null; } if (boardCleared) { previousUpdated = previous with { LineCount = previous.LineCount + 1 }; if (previousUpdated.LineCount > gm.deathGameSettings.MaxCoffinSize) { CoffinCompleted?.Invoke(previousUpdated); previousUpdated = null; } if (next.XCount < 2) { nextUpdated = next with { XCount = next.XCount + 1 }; } else { nextUpdated = next with { LineCount = previous.LineCount + 1, XCount = 0 }; if (nextUpdated.LineCount > gm.deathGameSettings.MaxCoffinSize) { CoffinCompleted?.Invoke(nextUpdated); nextUpdated = null; } } } var coffins = gm.Coffins.Skip(1).ToList(); if (currentUpdated != null) { coffins.Add(currentUpdated); } if (nextUpdated == null) { coffins.Remove(next); } if (previousUpdated == null) { coffins.Remove(previous); } else { var idx = coffins.IndexOf(previous); coffins.Remove(previous); coffins.Insert(idx, previousUpdated); } var result = gm with { Coffins = coffins.ToArray(), Id = gm.Id + 1 }; return result; } } }