//////////Methods////////// /// <summary> /// Creates a new map of the game /// </summary> public Map(IPirateGame game) { // updates map constants this.Rows = game.GetRows(); this.Collumns = game.GetCols(); this.AttackRadius = Utils.Sqrt(game.GetAttackRadius()); // set the computing limits this.IsBig = this.Rows > 40 || this.Collumns > 40; // create the pirate managers this.MyPirateManager = new PirateManager(game, Owner.Me); this.MyAttackMap = new AttackMap(this, this.MyPirateManager.GetAllPirates()); this.EnemyPirateManager = new PirateManager(game, Owner.Enemy); this.EnemyAttackMap = new AttackMap(this, this.EnemyPirateManager.GetAllPirates()); // create the sail manager this.SailManager = new SailManager(game, this); // create the update proxy this.updateProxy = new UpdateProxy <IPirateGame>(); this.updateProxy.Add(this.MyPirateManager); this.updateProxy.Add(this.EnemyPirateManager); this.updateProxy.Add(this.SailManager); // initialize the neighbors matrix this.neighbors = new List <Location> [this.Rows, this.Collumns, (2 * game.GetActionsPerTurn()) + 1]; // calculate the neighbors for each location in map for (int row = 0; row < this.Rows; row++) { for (int collumn = 0; collumn < this.Collumns; collumn++) { // assign neighbors of distance 0 ;) this.neighbors[row, collumn, 0] = new List <Location>(); this.neighbors[row, collumn, 0].Add(new Location(row, collumn)); // for each distance from 1 to max for (int distance = 1; distance < this.neighbors.GetLength(2); distance++) { this.neighbors[row, collumn, distance] = new List <Location>(); // add all the neighbors in a windmill-like shape for (int i = 0; i < distance; i++) { // all four quarters, were the row delta is i this.neighbors[row, collumn, distance].Add(new Location(row + i, collumn + (distance - i))); this.neighbors[row, collumn, distance].Add(new Location(row - i, collumn - (distance - i))); this.neighbors[row, collumn, distance].Add(new Location(row - (distance - i), collumn + i)); this.neighbors[row, collumn, distance].Add(new Location(row + (distance - i), collumn - i)); } // remove neighbors which are not in the map this.neighbors[row, collumn, distance].RemoveAll(loc => !this.InMap(loc)); } } } // the list of availible treasures List <Pirates.Treasure> allTreasures = game.Treasures(); // initialize the lists containing the treasures by states this.treasuresByStates = new List <Treasure> [(int)TreasureState.COUNT]; for (int i = 0; i < this.treasuresByStates.Length; i++) { this.treasuresByStates[i] = new List <Treasure>(); } // initialize the allTreasures array and the treasuresSpawnOnMap dictionary this.allTreasures = new Treasure[allTreasures.Count]; this.treasuresSpawnOnMap = new Dictionary <Location, Treasure>(); // initialize all the treasures in the allTreasures array, and add them to freeToTakeTreasures and to treasuresSpawnOnMap foreach (Pirates.Treasure t in allTreasures) { Treasure newTreasure = new Treasure(t); newTreasure.NativeObject = t; this.allTreasures[t.Id] = newTreasure; this.treasuresByStates[(int)TreasureState.FreeToTake].Add(newTreasure); this.treasuresSpawnOnMap.Add(newTreasure.InitialLocation, newTreasure); } // initialize the piratesSpawnOnMap dictionary this.piratesSpawnOnMap = new Dictionary <Location, Pirate>(); foreach (Pirate p in this.MyPirateManager.GetAllPirates()) { this.piratesSpawnOnMap.Add(p.InitialLocation, p); } foreach (Pirate p in this.EnemyPirateManager.GetAllPirates()) { this.piratesSpawnOnMap.Add(p.InitialLocation, p); } // initialize the map dictionaries, and update them this.piratesOnMap = new Dictionary <Location, Pirate>(); this.updatePiratesMapDictionary(); this.treasuresOnMap = new ListsDictionary <Location, Treasure>(); this.updateTreasuresMapDictionary(); // initialize the powerups list this.powerups = new List <Powerup>(); this.repopulatePowerups(game.Powerups(), game.GetTurn()); // initialize treasuresSpawnClusters this.treasuresSpawnClusers = Cluster.Clusterify <Treasure>(this.allTreasures, this.AttackRadius); // initialize the value being carried this.myCarriedValue = 0; this.enemyCarriedValue = 0; }
/// <summary> /// Returns a list of possible immediate destinations for the sail and the calculated distance to the destination, /// that uses every number of moves satisfing minMoves <= moves <= maxMoves /// </summary> /// <param name="from">The start location</param> /// <param name="to">The destination</param> /// <param name="minToDistance">The minimum distance from the destination, which is OK to get to</param> /// <param name="maxToDistance">The maximum distance from the destination, which is OK to get to</param> /// <param name="maxDistancePerTurn">the maximum amount of distance a pirate can travel in a turn</param> /// <param name="dontStayInRange">should you avoid staying in the attack range of an enemy pirate</param> /// <param name="minMoves">The minimum number of moves to use</param> /// <param name="maxMoves">The maximum number of moves to use (or less, if the destination is in reach from the start location)</param> /// <param name="maxResultsForMovesNum">The maximum number of results to include, for each number of moves being checked</param> /// <param name="disallowedTerrain">the list of disallowed terrain to NOT walk on</param> /// <returns>A list of possible immediate destinations for the sail and their calculated distance to the destination</returns> public List <KeyValuePair <Location, int> > GetCompleteSailOptions(ILocateable from, ILocateable to, int minToDistance, int maxToDistance, int maxDistancePerTurn, bool dontStayInRange, int minMoves, int maxMoves, int maxResultsForMovesNum, params Terrain[] disallowedTerrain) { // sanity check if (from == null || from.GetLocation() == null || !this.map.InMap(from) || to == null || to.GetLocation() == null || !this.map.InMap(to)) { return(new List <KeyValuePair <Location, int> >()); } // the attack map of the enemy AttackMap enemyAttackMap = this.map.EnemyAttackMap; // do the location stays in attack range System.Predicate <Location> staysInAttackRange = loc => enemyAttackMap.GetDangerousPiratesInAttackRange(loc).Intersect( enemyAttackMap.GetDangerousPiratesInAttackRange(from)).Count() > 0; // use at most "distance" moves to reach destination int distance = Map.ManhattanDistance(from, to); if (distance < maxMoves) { maxMoves = distance; } // get all the possible results List <Location> possibleResults = new List <Location>(); for (int moves = minMoves; moves <= maxMoves; moves++) { possibleResults.AddRange(this.map.GetNeighbors(from, moves)); } // remove the results that stay in attack range if needed if (dontStayInRange) { possibleResults.RemoveAll(staysInAttackRange); } // get all the possible final destinations List <Location> finalDestinations = new List <Location>(); for (int radius = minToDistance; radius <= maxToDistance; radius++) { finalDestinations.AddRange(this.map.GetNeighbors(to, radius)); } // update A* algorithm this.Update_AStar(finalDestinations, possibleResults, maxDistancePerTurn, disallowedTerrain); // calculate the results List <KeyValuePair <Location, int> > results = new List <KeyValuePair <Location, int> >(); // for each possible "moves" value for (int moves = minMoves; moves <= maxMoves; moves++) { // choose only best results possibleResults.Clear(); possibleResults.AddRange(this.map.GetNeighbors(from, moves)); // remove the results that stay in attack range if needed if (dontStayInRange) { possibleResults.RemoveAll(staysInAttackRange); } possibleResults.Shuffle(); // shuffle the neighbors, so that two neighbors with the same gScore will be randomly ordered possibleResults = possibleResults.OrderBy(loc => this.getGScore(loc)).ToList(); // sort by gScore for (int i = 0; i < possibleResults.Count && i < maxResultsForMovesNum; i++) { if (this.getGScore(possibleResults[i]) >= this.aStar_gScore.Length) // if the value is "infinity" { break; } // add the result, and its distance to the destination results.Add(new KeyValuePair <Location, int>(possibleResults[i], this.getGScore(possibleResults[i]))); } } return(results); }