Esempio n. 1
0
/**
**  Check if we can build the building.
**
**  @param type      Unit that can build the building.
**  @param building  Building to be build.
**
**  @return          True if made, false if can't be made.
**
**  @note            We must check if the dependencies are fulfilled.
*/
static int AiBuildBuilding(const CUnitType &type, CUnitType &building, int near_x, int near_y)
{
	CUnit *table[UnitMax];
	int num = 0;

	//
	// Remove all workers on the way building something
	//
	const int nunits = FindPlayerUnitsByType(AiPlayer->Player, type, table);
	for (int i = 0; i < nunits; ++i) {
		CUnit& unit = *table[i];
		int j;

		for (j = 0; j < unit.OrderCount; ++j) {
			int action = unit.Orders[j]->Action;
			if (action == UnitActionBuild ||
				action == UnitActionRepair ||
				action == UnitActionReturnGoods ||
				(action == UnitActionResource &&
					 unit.SubAction > 55) /* SUB_START_GATHERING */) {
				break;
			}
		}
		if (j == unit.OrderCount) {
			table[num++] = &unit;
		}
	}

	if (num == 0) {
		// No workers available to build
		return 0;
	}

	CUnit& unit = (num == 1) ? *table[0] : *table[SyncRand() % num];

	Vec2i pos;
	// Find a place to build.
	if (AiFindBuildingPlace(unit, building, near_x, near_y, &pos)) {
		CommandBuildBuilding(unit, pos, building, FlushCommands);
		return 1;
	} else {
		//when first worker can't build then rest also won't be able (save CPU)
		if (near_x != -1 && near_y != -1) {
			//Crush CPU !!!!!
			for (int i = 0; i < num && table[i] != &unit; ++i) {
				// Find a place to build.
				if (AiFindBuildingPlace(*table[i], building, near_x, near_y, &pos)) {
					CommandBuildBuilding(*table[i], pos, building, FlushCommands);
					return 1;
				}
			}
		}
	}
	return 0;
}
Esempio n. 2
0
//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;
}
Esempio n. 3
0
/**
**  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;
}
Esempio n. 4
0
/**
**  Check if we can research the upgrade.
**
**  @param type  Unit that can research the upgrade.
**  @param what  What should be researched.
**
**  @return      True if made, false if can't be made.
**
**  @note        We must check if the dependencies are fulfilled.
*/
static bool AiResearchUpgrade(const CUnitType &type, CUpgrade &what)
{
    std::vector<CUnit *> table;

    FindPlayerUnitsByType(*AiPlayer->Player, type, table);
    for (size_t i = 0; i != table.size(); ++i) {
        CUnit &unit = *table[i];

        if (unit.IsIdle()) {
            CommandResearch(unit, what, FlushCommands);
            return true;
        }
    }
    return false;
}
Esempio n. 5
0
/**
**  Check if we can upgrade to unit-type.
**
**  @param type  Unit that can upgrade to unit-type
**  @param what  To what should be upgraded.
**
**  @return      True if made, false if can't be made.
**
**  @note        We must check if the dependencies are fulfilled.
*/
static bool AiUpgradeTo(const CUnitType &type, CUnitType &what)
{
    std::vector<CUnit *> table;

    // Remove all units already doing something.
    FindPlayerUnitsByType(*AiPlayer->Player, type, table);
    for (size_t i = 0; i != table.size(); ++i) {
        CUnit &unit = *table[i];

        if (unit.IsIdle()) {
            CommandUpgradeTo(unit, what, FlushCommands);
            return true;
        }
    }
    return false;
}
Esempio n. 6
0
/**
**  Check if we can train the unit.
**
**  @param type  Unit that can train the unit.
**  @param what  What to be trained.
**
**  @return      True if made, false if can't be made.
**
**  @note        We must check if the dependencies are fulfilled.
*/
static bool AiTrainUnit(const CUnitType &type, CUnitType &what)
{
	std::vector<CUnit *> table;

	FindPlayerUnitsByType(*AiPlayer->Player, type, table, true);
	for (size_t i = 0; i != table.size(); ++i) {
		CUnit &unit = *table[i];

		if (unit.IsIdle()) {
			//Wyrmgus start
//			CommandTrainUnit(unit, what, FlushCommands);
			CommandTrainUnit(unit, what, AiPlayer->Player->Index, FlushCommands);
			//Wyrmgus end
			return true;
		}
	}
	return false;
}
Esempio n. 7
0
/**
**  Check if we can build the building.
**
**  @param type      Unit that can build the building.
**  @param building  Building to be build.
**
**  @return          True if made, false if can't be made.
**
**  @note            We must check if the dependencies are fulfilled.
*/
static int AiBuildBuilding(const CUnitType &type, CUnitType &building, const Vec2i &nearPos)
{
    std::vector<CUnit *> table;

    FindPlayerUnitsByType(*AiPlayer->Player, type, table);

    int num = 0;

    // Remove all workers on the way building something
    for (size_t i = 0; i != table.size(); ++i) {
        CUnit &unit = *table[i];

        if (IsAlreadyWorking(unit) == false) {
            table[num++] = &unit;
        }
    }
    if (num == 0) {
        // No workers available to build
        return 0;
    }

    CUnit &unit = (num == 1) ? *table[0] : *table[SyncRand() % num];

    Vec2i pos;
    // Find a place to build.
    if (AiFindBuildingPlace(unit, building, nearPos, &pos)) {
        CommandBuildBuilding(unit, pos, building, FlushCommands);
        return 1;
    } else {
        //when first worker can't build then rest also won't be able (save CPU)
        if (Map.Info.IsPointOnMap(nearPos)) {
            //Crush CPU !!!!!
            for (int i = 0; i < num && table[i] != &unit; ++i) {
                // Find a place to build.
                if (AiFindBuildingPlace(*table[i], building, nearPos, &pos)) {
                    CommandBuildBuilding(*table[i], pos, building, FlushCommands);
                    return 1;
                }
            }
        }
    }
    return 0;
}
Esempio n. 8
0
/**
**  Check if we can upgrade to unit-type.
**
**  @param type  Unit that can upgrade to unit-type
**  @param what  To what should be upgraded.
**
**  @return      True if made, false if can't be made.
**
**  @note        We must check if the dependencies are fulfilled.
*/
static int AiUpgradeTo(const CUnitType &type, CUnitType &what)
{
	CUnit *table[UnitMax];
	int num = 0;

	// Remove all units already doing something.
	const int nunits = FindPlayerUnitsByType(AiPlayer->Player, type, table);
	for (int i = 0; i < nunits; ++i) {
		CUnit *unit = table[i];

		if (unit->IsIdle()) {
			table[num++] = unit;
		}
	}

	for (int i = 0; i < num; ++i) {
		CUnit &unit = *table[i];

		CommandUpgradeTo(unit, what, FlushCommands);
		return 1;
	}
	return 0;
}
Esempio n. 9
0
/**
**  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 int AiRepairBuilding(const CUnitType &type, CUnit &building)
{
	// 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.
	CUnit *table[UnitMax];
	int nunits = FindPlayerUnitsByType(AiPlayer->Player, type, table);
	int num = 0;
	for (int i = 0; i < nunits; ++i) {
		CUnit &unit = *table[i];

		if (unit.Type->RepairRange && unit.OrderCount == 1 &&
			((unit.CurrentAction() == UnitActionResource && unit.SubAction <= 55) /* SUB_START_GATHERING */ ||
				unit.CurrentAction() == UnitActionStill)) {
			table[num++] = &unit;
		}
	}

	// Sort by distance loops -Antonis-
	int distance[UnitMax];
	for (int i = 0; i < num; ++i) {
		CUnit &unit = *table[i];
		int rX = unit.tilePos.x - building.tilePos.x;
		int rY = unit.tilePos.y - building.tilePos.y;

		// FIXME: Probably calculated from top left corner of building
		rX = std::max(rX, -rX);
		rY = std::max(rY, -rY);
		distance[i] = std::min(rX, rY);
	}
	for (int i = 0; i < num; ++i) {
		int r_temp = distance[i];
		int index_temp = i;
		for (int j = i; j < num; ++j) {
			if (distance[j] < r_temp) {
				r_temp = distance[j];
				index_temp = j;
			}
		}
		if (index_temp > i) {
			std::swap(distance[i], distance[index_temp]);
			std::swap(table[i], table[index_temp]);
		}
	}

	// Check if building is reachable and try next trio of workers

	int nbworker = AiPlayer->TriedRepairWorkers[UnitNumber(building)];
	if (nbworker > num) {
		nbworker = AiPlayer->TriedRepairWorkers[UnitNumber(building)] = 0;
	}

	int k = nbworker;
	for (int i = nbworker; i < num && i < nbworker + 3; ++i) {

		CUnit &unit = *table[i];

		if (UnitReachable(unit, building, unit.Type->RepairRange)) {
			const Vec2i invalidPos = {-1, -1};
			CommandRepair(unit, invalidPos, &building, FlushCommands);
			return 1;
		}
		k = i;
	}
	AiPlayer->TriedRepairWorkers[UnitNumber(building)] = k + 1;
	return 0;
}