/** ** Find Resource. ** ** @param unit The unit that wants to find a resource. ** @param startUnit Find closest unit from this location ** @param range Maximum distance to the resource. ** @param resource The resource id. ** ** @note This will return an usable resource building that doesn't ** belong to the player or one of his allies. ** ** @return NULL or resource unit */ CUnit *UnitFindResource(const CUnit &unit, const CUnit &startUnit, int range, int resource, //Wyrmgus start // bool check_usage, const CUnit *deposit) bool check_usage, const CUnit *deposit, bool mine_on_top) //Wyrmgus end { if (!deposit) { // Find the nearest depot deposit = FindDepositNearLoc(*unit.Player, startUnit.tilePos, range, resource); } TerrainTraversal terrainTraversal; terrainTraversal.SetSize(Map.Info.MapWidth, Map.Info.MapHeight); terrainTraversal.Init(); terrainTraversal.PushUnitPosAndNeighboor(startUnit); CUnit *resultMine = NULL; //Wyrmgus start // ResourceUnitFinder resourceUnitFinder(unit, deposit, resource, range, check_usage, &resultMine); ResourceUnitFinder resourceUnitFinder(unit, deposit, resource, range, check_usage, &resultMine, mine_on_top); //Wyrmgus end terrainTraversal.Run(resourceUnitFinder); return resultMine; }
//Wyrmgus start //static bool AiRepairBuilding(const CPlayer &player, const CUnitType &type, CUnit &building) static bool AiRepairBuilding(const CPlayer &player, const CUnitType &type, CUnit &building) //Wyrmgus end { if (type.RepairRange == 0) { return false; } // We need to send all nearby free workers to repair that building // AI shouldn't send workers that are far away from repair point // Selection of mining workers. std::vector<CUnit *> table; FindPlayerUnitsByType(*AiPlayer->Player, type, table, true); int num = 0; for (size_t i = 0; i != table.size(); ++i) { CUnit &unit = *table[i]; if (IsReadyToRepair(unit)) { table[num++] = &unit; } } table.resize(num); if (table.empty()) { return false; } TerrainTraversal terrainTraversal; //Wyrmgus start // terrainTraversal.SetSize(Map.Info.MapWidth, Map.Info.MapHeight); terrainTraversal.SetSize(Map.Info.MapWidths[building.MapLayer], Map.Info.MapHeights[building.MapLayer]); //Wyrmgus end terrainTraversal.Init(); terrainTraversal.PushUnitPosAndNeighboor(building); const int maxRange = 15; const int movemask = type.MovementMask & ~(MapFieldLandUnit | MapFieldAirUnit | MapFieldSeaUnit); CUnit *unit = NULL; //Wyrmgus start // UnitFinder unitFinder(player, table, maxRange, movemask, &unit); UnitFinder unitFinder(player, table, maxRange, movemask, &unit, building.MapLayer); //Wyrmgus end if (terrainTraversal.Run(unitFinder) && unit != NULL) { const Vec2i invalidPos(-1, -1); //Wyrmgus start // CommandRepair(*unit, invalidPos, &building, FlushCommands); CommandRepair(*unit, invalidPos, &building, FlushCommands, building.MapLayer); //Wyrmgus end return true; } return false; }
/** ** Find the closest piece of terrain with the given flags. ** ** @param movemask The movement mask to reach that location. ** @param resmask Result tile mask. ** @param range Maximum distance for the search. ** @param player Only search fields explored by player ** @param startPos Map start position for the search. ** ** @param terrainPos OUT: Map position of tile. ** ** @note Movement mask can be 0xFFFFFFFF to have no effect ** Range is not circular, but square. ** Player is ignored if nil(search the entire map) ** ** @return True if wood was found. */ bool FindTerrainType(int movemask, int resmask, int range, const CPlayer &player, const Vec2i &startPos, Vec2i *terrainPos) { TerrainTraversal terrainTraversal; terrainTraversal.SetSize(Map.Info.MapWidth, Map.Info.MapHeight); terrainTraversal.Init(); terrainTraversal.PushPos(startPos); TerrainFinder terrainFinder(player, range, movemask & ~(MapFieldLandUnit | MapFieldAirUnit | MapFieldSeaUnit), resmask, terrainPos); return terrainTraversal.Run(terrainFinder); }
/** ** Check if we can repair the building. ** ** @param type Unit that can repair the building. ** @param building Building to be repaired. ** ** @return True if can repair, false if can't repair.. */ static bool AiRepairBuilding(const CPlayer &player, const CUnitType &type, CUnit &building) { if (type.RepairRange == 0) { return false; } // Remove all workers not mining. on the way building something // FIXME: It is not clever to use workers with gold // Idea: Antonis: Put the rest of the workers in a table in case // miners can't reach but others can. This will be useful if AI becomes // more flexible (e.g.: transports workers to an island) // FIXME: too hardcoded, not nice, needs improvement. // FIXME: too many workers repair the same building! // Selection of mining workers. std::vector<CUnit *> table; FindPlayerUnitsByType(*AiPlayer->Player, type, table); int num = 0; for (size_t i = 0; i != table.size(); ++i) { CUnit &unit = *table[i]; if (IsReadyToRepair(unit)) { table[num++] = &unit; } } table.resize(num); if (table.empty()) { return false; } TerrainTraversal terrainTraversal; terrainTraversal.SetSize(Map.Info.MapWidth, Map.Info.MapHeight); terrainTraversal.Init(); terrainTraversal.PushUnitPosAndNeighboor(building); const int maxRange = 100; const int movemask = type.MovementMask & ~(MapFieldLandUnit | MapFieldAirUnit | MapFieldSeaUnit); CUnit *unit = NULL; UnitFinder unitFinder(player, table, maxRange, movemask, &unit); if (terrainTraversal.Run(unitFinder) && unit != NULL) { const Vec2i invalidPos(-1, -1); CommandRepair(*unit, invalidPos, &building, FlushCommands); return true; } return false; }
static bool FindNearestReachableTerrainType(int movemask, int resmask, int range, const CPlayer &player, const Vec2i &startPos, Vec2i *terrainPos) { TerrainTraversal terrainTraversal; terrainTraversal.SetSize(Map.Info.MapWidth, Map.Info.MapHeight); terrainTraversal.Init(); Assert(Map.Field(startPos)->CheckMask(resmask)); terrainTraversal.PushPos(startPos); NearReachableTerrainFinder nearReachableTerrainFinder(player, range, movemask, resmask, terrainPos); return terrainTraversal.Run(nearReachableTerrainFinder); }
bool AiForce::NewRallyPoint(const Vec2i &startPos, Vec2i *resultPos) { Assert(this->Units.size() > 0); const CUnit &leader = *(this->Units[0]); const int distance = leader.MapDistanceTo(startPos); WaitOnRallyPoint = AI_WAIT_ON_RALLY_POINT; TerrainTraversal terrainTraversal; terrainTraversal.SetSize(Map.Info.MapWidth, Map.Info.MapHeight); terrainTraversal.Init(); Assert(Map.Info.IsPointOnMap(startPos)); terrainTraversal.PushPos(startPos); AiForceRallyPointFinder aiForceRallyPointFinder(leader, distance, leader.tilePos, resultPos); return terrainTraversal.Run(aiForceRallyPointFinder); }