public static List<Move> ParseMoves(Map fullMap, string line) { var result = new List<Move>(); var moveInput = InputParser.Split(line); for (int i = 1; i < moveInput.Length; i++) { try { Move move; if (moveInput[i + 1].Equals("place_armies")) { Region region = fullMap.GetRegionByID(int.Parse(moveInput[i + 2])); String playerName = moveInput[i]; int armies = int.Parse(moveInput[i + 3]); move = new PlaceArmiesMove(playerName, region, armies); i += 3; } else if (moveInput[i + 1].Equals("attack/transfer")) { Region fromRegion = fullMap.GetRegionByID(int.Parse(moveInput[i + 2])); Region toRegion = fullMap.GetRegionByID(int.Parse(moveInput[i + 3])); String playerName = moveInput[i]; int armies = int.Parse(moveInput[i + 4]); move = new AttackTransferMove(playerName, fromRegion, toRegion, toRegion, armies, MoveReason.Unknown); i += 4; } else { // Should never happen. continue; } result.Add(move); } catch (Exception ex) { Console.Error.WriteLine("Unable to parse moves: " + ex); } } return result; }
public static void HandleAttack(AttackTransferMove move, GameState gameState) { var fromRegion = gameState.FullMap.GetRegionByID(move.FromRegion.ID); var toRegion = gameState.FullMap.GetRegionByID(move.ToRegion.ID); ConsoleExtensions.WriteColoredLine(ConsoleColor.Yellow, "Player '{0}' attacks region {1} ({2} armies) from region {3} ({4} armies) with {5} armies for {6}.", move.PlayerName, toRegion.ID, toRegion.Armies, fromRegion.ID, fromRegion.Armies, move.Armies, move.MoveReason); int attackers = move.Armies; int defenders = toRegion.Armies; int attackersLost; int defendersLost; if (toRegion.PlayerName == "neutral" && toRegion.Armies == 2) { // Not random to properly determine growth changes instead of relying on random. switch (move.Armies) { case 1: attackersLost = 1; defendersLost = 0; break; case 2: attackersLost = 1; defendersLost = 1; break; case 3: attackersLost = 2; defendersLost = 2; break; case 4: attackersLost = 1; defendersLost = 2; break; default: attackersLost = 0; defendersLost = 2; break; } } else { // Aaand this one is wrong, but it was the first I came up with without reading the rules. // TODO: it's 70% chance 1 defender kills an attacker and 60% chance 1 attacker kills 1 defender, but do surviving armies get another go if any opposing armies left? attackersLost = Math.Abs(defenders - (attackers / _random.Next(1, attackers))); defendersLost = Math.Abs(attackers - (defenders / _random.Next(1, defenders))); if (attackersLost > attackers) { attackersLost = attackers; } if (defendersLost > defenders) { defendersLost = defenders; } } attackers -= attackersLost; defenders -= defendersLost; if (defenders <= 0) { fromRegion.Armies -= move.Armies; fromRegion.ArmiesAvailable -= move.Armies; string defenderName = toRegion.PlayerName; // change ownership and transfer attackers toRegion.PlayerName = move.PlayerName; toRegion.Armies = move.Armies - attackersLost; if (toRegion.Armies < 1) { toRegion.Armies = 1; } ConsoleExtensions.WriteColoredLine(ConsoleColor.Green, "Player '{0}' won and lost {1} armies, defender '{2}' lost {3}.", move.PlayerName, attackersLost, defenderName, defendersLost); } else { fromRegion.Armies -= attackersLost; fromRegion.ArmiesAvailable -= attackersLost; toRegion.Armies -= defendersLost; ConsoleExtensions.WriteColoredLine(ConsoleColor.Green, "Player '{0}' lost, losing {1} armies, defender '{2}' lost {3}.", move.PlayerName, attackersLost, toRegion.PlayerName, defendersLost); } }
protected virtual void Move(IGameplayEngine actingPlayer, AttackTransferMove move) { var fromRegion = _gameState.FullMap.GetRegionByID(move.FromRegion.ID); var toRegion = _gameState.FullMap.GetRegionByID(move.ToRegion.ID); if (move.Armies < 1) { ConsoleExtensions.WriteColoredLine(ConsoleColor.Red, "Player '{0}' tried to move {1} armies from region {2} to {3}, which is a bit silly. Move discarded.", move.PlayerName, move.Armies, fromRegion.ID, toRegion.ID, fromRegion.Armies); return; } if (fromRegion.PlayerName != move.PlayerName) { ConsoleExtensions.WriteColoredLine(ConsoleColor.Red, "Player '{0}' tried to move {1} armies from region {2} to {3}, but region {2} is not theirs. Move discarded.", move.PlayerName, move.Armies, fromRegion.ID, toRegion.ID); return; } if (move.Armies > fromRegion.ArmiesAvailable) { ConsoleExtensions.WriteColoredLine(ConsoleColor.Red, "Player '{0}' tried to move {1} armies from region {2} to {3}, but only {4} armies were remaining. Move discarded.", move.PlayerName, move.Armies, fromRegion.ID, toRegion.ID, fromRegion.Armies); return; } if (!fromRegion.Neighbors.Contains(toRegion)) { ConsoleExtensions.WriteColoredLine(ConsoleColor.Red, "Player '{0}' tried to move {1} armies from region {2} to {3}, but the regions are no neighbors. Move discarded.", move.PlayerName, move.Armies, fromRegion.ID, toRegion.ID); return; } if (move.PlayerName == toRegion.PlayerName) { MoveArmies(move.PlayerName, fromRegion, toRegion, move.Armies, move.MoveReason); } else { AttackHandler.HandleAttack(move, _gameState); } ConsoleExtensions.WriteColoredLine(ConsoleColor.Magenta, "Region {0} ('{1}'): {2} armies, Region {3} ('{4}'): {5} armies", fromRegion.ID, fromRegion.PlayerName, fromRegion.Armies, toRegion.ID, toRegion.PlayerName, toRegion.Armies); }