Example #1
0
 // This calculates a map of positions a unit can move to (keys) and best paths discovered (values)
 public Dictionary<Position, Path> CreateMovementMap(Unit unit)
 {
     var map = new Dictionary<Position, Path>(new PositionComparer());
     Path path = new Path(unit.MovementPoints);
     CreateMovementMap(unit, unit.Hex, path, unit.Owner.Identifier, map);
     // Remove all the hexes occupied by friendly units since those were only permitted for passing through
     foreach (var position in map.Keys)
     {
         Hex hex = GetHex(position);
         if (hex.Unit != null)
             map.Remove(position);
     }
     return map;
 }
Example #2
0
 void CreateMovementMap(Unit unit, Hex currentHex, Path currentPath, PlayerIdentifier owner, Dictionary<Position, Path> map)
 {
     for(int i = 0; i < HexOffsets.Length; i++)
     {
         RiverEdge riverEdge = currentHex.RiverEdges[i];
         Position offset = HexOffsets[i];
         Position neighbourPosition = currentHex.Position + offset;
         Hex neighbourHex = GetHex(neighbourPosition);
         if (neighbourHex == null)
         {
             // This hex is not part of the map, skip it
             continue;
         }
         if (neighbourHex.Unit != null && neighbourHex.Unit.Owner.Identifier != owner)
         {
             // This hex is already occupied by an enemy unit, skip it
             continue;
         }
         int terrainMovementPoints = neighbourHex.GetTerrainMovementPoints();
         int movementPointsLost;
         if (riverEdge != null && !riverEdge.IsBridge)
         {
             // It's a move across a river without a bridge
             // This is only possible under special circumstances
             // The unit must have its full movement points and it will lose all of them after the crossing
             int maximumMovementPoints = unit.Stats.Movement.Value;
             if (currentPath.MovementPointsLeft < maximumMovementPoints)
             {
                 // The unit had already moved so it can't cross the river
                 continue;
             }
             if (currentPath.MovementPointsLeft < terrainMovementPoints)
             {
                 // This is an extraordinarily rare case but it means that the unit can't cross the river because it couldn't enter the target terrain type, even if the river wasn't there
                 continue;
             }
             movementPointsLost = maximumMovementPoints;
         }
         else
         {
             // It's either a regular move without a river or a move across a bridge
             movementPointsLost = terrainMovementPoints;
         }
         int newMovementPoints = currentPath.MovementPointsLeft - movementPointsLost;
         if (newMovementPoints < 0)
         {
             // The unit doesn't have enough movement points left to enter this hex
             continue;
         }
         Path previousPath;
         if (map.TryGetValue(neighbourPosition, out previousPath))
         {
             // This neighbouring hex was already analysed by a previous recursive call to this function, check if we can even improve on what it calculated
             if (previousPath.MovementPointsLeft <= newMovementPoints)
             {
                 // The solution is inferior or just as good, skip it
                 continue;
             }
         }
         // Create or update the entry in the movement map
         Path newPath = new Path(currentPath, neighbourHex, newMovementPoints);
         map[neighbourPosition] = newPath;
         CreateMovementMap(unit, neighbourHex, newPath, owner, map);
     }
 }
Example #3
0
 public Path(Path currentPath, Hex newHex, int movementPointsLeft)
 {
     Hexes = new List<Hex>();
     Hexes.AddRange(currentPath.Hexes);
     Hexes.Add(newHex);
     MovementPointsLeft = movementPointsLeft;
 }
Example #4
0
 List<Hex> CaptureHexes(Path path)
 {
     List<Hex> captures = new List<Hex>();
     var map = Game.Map;
     // Capture hexes
     foreach (var pathHex in path.Hexes)
     {
         if (pathHex.Owner != Identifier)
         {
             // Direct capture
             pathHex.Owner = Identifier;
             captures.Add(pathHex);
             // Check for indirect captures
             foreach (var offset in Map.HexOffsets)
             {
                 Position neighbourPosition = pathHex.Position + offset;
                 Hex neighbourHex = map.GetHex(neighbourPosition);
                 List<Hex> capturedRegion = map.GetIndirectlyCapturedRegion(neighbourHex, Identifier);
                 if (capturedRegion == null)
                 {
                     // No region to capture could be found
                     continue;
                 }
                 foreach (var emptyRegionHex in capturedRegion)
                 {
                     emptyRegionHex.Owner = Identifier;
                     captures.Add(emptyRegionHex);
                 }
             }
         }
     }
     return captures;
 }