//Update the current game state (on start of tick) private RiftGame UpdateGameState(RiftGame gameState) { Log("Updating gamestate"); gameState.MyPlatinum = int.Parse(ReadLine()); // my available Platinum Log($"Current platinum: {gameState.MyPlatinum}"); //Update all the zones for (int i = 0; i < gameState.AmountOfZones; i++) { string[] inputs = ReadLine().Split(' '); int zId = int.Parse(inputs[0]); // this zone's ID var zone = gameState.GetZone(zId); int? oldOwner = zone.OwningPlayerID; zone.OwningPlayerID = int.Parse(inputs[1]); // the player who owns this zone (-1 otherwise) zone.OwningPlayerID = zone.OwningPlayerID < 0 ? null : zone.OwningPlayerID; //Keep null zone.AmountPodsPlayer0 = int.Parse(inputs[2]); // player 0's PODs on this zone zone.AmountPodsPlayer1 = int.Parse(inputs[3]); // player 1's PODs on this zone zone.AmountPodsPlayer2 = int.Parse(inputs[4]); // player 2's PODs on this zone (always 0 for a two player game) zone.AmountPodsPlayer3 = int.Parse(inputs[5]); // player 3's PODs on this zone (always 0 for a two or three player game) if (zone.OwningPlayerID != oldOwner) { Log($"Ownership of zone {zone.NodeIndex} changed from {oldOwner} to {zone.OwningPlayerID}"); } } return(gameState); }
private void LogRepresentation(RiftGame game) { var podNodes = game.GetZonesWithMyPods().ToList(); var controlNodes = game.GetZonesUnderMyControl().ToList(); Log($"Current statistics: {podNodes.Count} with myNodes, {controlNodes.Count} under control"); }
// **** Status readers //Read game state/parameters (init) private RiftGame GetGameFromInitialInput() { var game = new RiftGame(); string[] inputs = ReadLine().Split(' '); game.AmountOfPlayers = int.Parse(inputs[0]); // the amount of players (2 to 4) game.MyPlayerID = int.Parse(inputs[1]); // my player ID (0, 1, 2 or 3) game.AmountOfZones = int.Parse(inputs[2]); // the amount of zones on the map game.AmountOfZoneLinks = int.Parse(inputs[3]); // the amount of links between all zones //Read nodes for (int i = 0; i < game.AmountOfZones; i++) { inputs = ReadLine().Split(' '); RiftZone rz = new RiftZone() { NodeIndex = int.Parse(inputs[0]), PlatimumSource = int.Parse(inputs[1]) }; game.AddOrReplaceZone(rz); } //Link nodes for (int i = 0; i < game.AmountOfZoneLinks; i++) { inputs = ReadLine().Split(' '); var z1 = game.GetZone(int.Parse(inputs[0])); var z2 = game.GetZone(int.Parse(inputs[1])); z1.LinkedNodes.Add(z2); z2.LinkedNodes.Add(z1); } return(game); }
private IEnumerable <PodMovement> GetMovements(RiftGame game) { var controlledZones = game.GetZonesUnderMyControl(); foreach (var z in controlledZones) { var movableInZone = z.GetAmountMovable(game.MyPlayerID); Log($"Can move {movableInZone} from zone {z.NodeIndex}"); if (!(movableInZone > 0)) { continue; } //Find the node to move to var moveTo = z.LinkedNodes.FirstOrDefault(zz => zz.OwningPlayerID != game.MyPlayerID) ?? z.LinkedNodes.FirstOrDefault(); if (moveTo != null) { Log($"Moving {movableInZone} to {moveTo.NodeIndex}"); yield return(new PodMovement() { Amount = movableInZone.Value, ZoneOrigin = z.NodeIndex, ZoneDestination = moveTo.NodeIndex }); } } }
private string GenerateMovementString(RiftGame game) { /*Rules for moving: * A POD (or group of PODs) can only make one move per game round. * A POD can only move from one zone to a contiguous zone – either neutral, already owned or owned by an enemy. * A POD located on a zone where a fight is ongoing – meaning a zone with enemy PODs on it – can only move to a neutral zone or a zone he/she owns. Simply put, a POD that flees a fight can only retreat on a zone which does not belong to an enemy. */ /* * Line 1: a series of movement commands. A movement command is composed of 3 integers podsCount zoneOrigin zoneDestination that indicate the number of PODs to move from one zone to another. * For example 4 2 1 3 2 6 = two commands: moving four PODs from zone 2 to zone 1 and moving three PODs from zone 2 to 6. * Just write WAIT if you do not wish to make any movements. */ int maxPodToPurchase = game.MyPlatinum / 20; var movements = GetMovements(game).ToList(); if (!movements.Any()) { Log("No movements"); return("WAIT"); } Log($"Found {movements.Count()} movements"); movements.ForEach(m => Log(m)); return(string.Join(" ", movements.Select(p => p.GetOutputString()))); }
private IEnumerable <PodPurchase> GetPurchases(RiftGame game, int maxAmount) { int amountAvailable = maxAmount; Log($"Platimum to buy {amountAvailable} pods"); //Populate neutral zones var neutralZones = GetNeutralZonesForMoves(game).ToList(); Log($"Found {neutralZones.Count()} neutralzones"); //While we can get nodes that are neutral while (amountAvailable > 0 && neutralZones.Any()) { //Pick a random node, because otherwise we will start populating in the left top var neutralZone = GetRandomFromCollection(neutralZones); amountAvailable--; yield return(new PodPurchase() { Amount = 1, Zone = neutralZone.NodeIndex }); neutralZone.AddPodsForPlayer(game.MyPlayerID, 1); //Update the temporary count //Check if there are still zones neutralZones = GetNeutralZonesForMoves(game).ToList(); } if (amountAvailable > 0) { Log("Still platinum available after populating empty nodes to purchase!"); } //Check if we need to strengthen our outer defenses (zones that are mine, but are next to empty or enemy nodes) var zonesToStrengthen = game.GetZonesUnderMyControl().Where(z => z.LinkedNodes.Any(l => l.OwningPlayerID != game.MyPlayerID)); Log($"Found {zonesToStrengthen.Count()} zones to strengthen"); foreach (var zoneToStrengthen in zonesToStrengthen) { if (amountAvailable <= 0) { break; } amountAvailable--; yield return(new PodPurchase() { Amount = 1, Zone = zoneToStrengthen.NodeIndex }); zoneToStrengthen.AddPodsForPlayer(game.MyPlayerID, 1); //Update the temporary count } }
private string GeneratePurchaseString(RiftGame game) { /* Rules for buying: * Each player can buy as many troops as their Platinum stock allows. A war POD costs 20 Platinum bars. * A freshly bought POD can only be placed on a neutral zone or on a zone owned by the buyer. */ /* * Line 2: a series of purchase commands. A purchase command is composed of 2 integers podsCount zoneDestination that indicate the number of PODs to add to a zone. * For example 2 32 1 11 = two commands: buy two PODs for zone 32 and buy one POD for zone 11. * Just write WAIT if you do not want to buy anything. */ int maxPodToPurchase = game.MyPlatinum / 20; var purchases = GetPurchases(game, maxPodToPurchase).ToList(); if (!purchases.Any()) { return("WAIT"); } Log($"Found {purchases.Count()} purchases"); purchases.ForEach(p => Log(p)); return(string.Join(" ", purchases.Select(p => p.GetOutputString()))); }
private IEnumerable <RiftZone> GetNeutralZonesForMoves(RiftGame game) { //Get elements that are neutral and not yet have nodes of me (this can happen if the nodes were set by the randomize function, //this will not de-queue them from the default list, since ownership transfers after the tick) return(game.GetAllZones().Where(z => z.OwningPlayerID == null && z.GetAmountPodsForPlayer(game.MyPlayerID) <= 0)); }