KoogleV4/GameHandler/DeathGame/DeathGameHandler.cs

184 lines
5.4 KiB
C#

using GameModel;
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 delegate void FirstThrowFailed(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;
public event FirstThrowFailed FirstThrowFailed;
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<Coffin>();
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 current = gm.Coffins.First();
var next = gm.Coffins.Skip(1).First();
var previous = gm.Coffins.Last();
var incLine = false;
var incX = false;
if (isTrowIntoAllPins) // into all pins
{
incX = true;
if (pinCount < 3)
{
FirstThrowFailed?.Invoke(current);
incLine = true;
}
}
if (isTrowIntoAllPins)
{
incX = true;
}
if (pinCount == 0)
{
incLine = true;
}
var xCount = current.XCount;
var lineCount = current.LineCount;
if (incLine)
{
lineCount++;
}
if (incX)
{
xCount++;
}
if (xCount == 3)
{
xCount = 0;
lineCount++;
}
Coffin? nextUpdated = next;
Coffin? previousUpdated = previous;
Coffin? 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 = next.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;
}
}
}