Beispiel #1
0
//Wyrmgus start
//int AiEnemyUnitsInDistance(const CUnit &unit, unsigned range)
int AiEnemyUnitsInDistance(const CUnit &unit, unsigned range, int z)
//Wyrmgus end
{
	//Wyrmgus start
//	return AiEnemyUnitsInDistance(*unit.Player, unit.Type, unit.tilePos, range);
	return AiEnemyUnitsInDistance(*unit.Player, unit.Type, unit.tilePos, range, z);
	//Wyrmgus end
}
Beispiel #2
0
VisitResult AiForceRallyPointFinder::Visit(TerrainTraversal &terrainTraversal, const Vec2i &pos, const Vec2i &from)
{
	const int minDist = 15;
	if (AiEnemyUnitsInDistance(*startUnit.Player, NULL, pos, minDist) == false
		&& Distance(pos, startPos) <= abs(distance - minDist)) {
		*resultPos = pos;
		return VisitResult_Finished;
	}
	if (CanMoveToMask(pos, movemask)) { // reachable
		return VisitResult_Ok;
	} else { // unreachable
		return VisitResult_DeadEnd;
	}
}
Beispiel #3
0
/**
**  Get a suitable depot for better resource harvesting.
**
**  @param worker    Worker itself.
**  @param oldDepot  Old assigned depot.
**  @param resUnit   Resource to harvest from, if succeed
**
**  @return          new depot if found, NULL otherwise.
*/
CUnit *AiGetSuitableDepot(const CUnit &worker, const CUnit &oldDepot, CUnit **resUnit)
{
	Assert(worker.CurrentAction() == UnitActionResource);
	COrder_Resource &order = *static_cast<COrder_Resource *>(worker.CurrentOrder());
	const int resource = order.GetCurrentResource();
	std::vector<CUnit *> depots;
	const Vec2i offset(MaxMapWidth, MaxMapHeight);

	for (std::vector<CUnit *>::iterator it = worker.Player->UnitBegin(); it != worker.Player->UnitEnd(); ++it) {
		CUnit &unit = **it;

		if (unit.Type->CanStore[resource] && !unit.IsUnusable()) {
			depots.push_back(&unit);
		}
	}
	// If there aren't any alternatives, exit
	if (depots.size() < 2) {
		return NULL;
	}
	std::sort(depots.begin(), depots.end(), CompareDepotsByDistance(worker));

	for (std::vector<CUnit *>::iterator it = depots.begin(); it != depots.end(); ++it) {
		CUnit &unit = **it;

		const unsigned int tooManyWorkers = 15;
		const int range = 15;

		if (&oldDepot == &unit) {
			continue;
		}
		if (unit.Refs > tooManyWorkers) {
			continue;
		}
		//Wyrmgus start
//		if (AiEnemyUnitsInDistance(worker, range)) {
		if (AiEnemyUnitsInDistance(worker, range, worker.MapLayer)) {
		//Wyrmgus end
			continue;
		}
		CUnit *res = UnitFindResource(worker, unit, range, resource, unit.Player->AiEnabled);
		if (res) {
			*resUnit = res;
			return &unit;
		}
	}
	return NULL;
}
Beispiel #4
0
/**
**  Find free building place. (flood fill version)
**
**  @param worker  Worker to build building.
**  @param type    Type of building.
**  @param ox      Original X position to try building
**  @param oy      Original Y position to try building
**  @param dpos    Pointer for position returned.
**
**  @return        True if place found, false if no found.
*/
static int AiFindBuildingPlace2(const CUnit &worker, const CUnitType &type, int ox, int oy, Vec2i *dpos)
{
    const Vec2i offset[] = {{0, -1}, {-1, 0}, {1, 0}, {0, 1}, {-1, -1}, {1, -1}, {-1, 1}, {1, 1}};
    Vec2i *points;
    int size;
    Vec2i pos = {ox, oy};
    Vec2i rpos;
    int mask;
    int wp;
    int rp;
    int ep;
    unsigned char *m;
    Vec2i backupPos = {-1, -1};
    bool backupok;

    //
    // Look if we can build at current place.
    //
    if (CanBuildUnitType(&worker, type, pos, 1) &&
            !AiEnemyUnitsInDistance(worker.Player, NULL, pos, 8)) {
        if (AiCheckSurrounding(worker, type, pos.x, pos.y, backupok)) {
            *dpos = pos;
            return 1;
        } else if (backupok) {
            backupPos = pos;
        }
    }

    size = Map.Info.MapWidth * Map.Info.MapHeight / 4;
    points = new Vec2i[size];

    //
    //  Make movement matrix.
    //
    unsigned char *matrix = CreateMatrix();
    const int w = Map.Info.MapWidth + 2;

    mask = worker.Type->MovementMask;
    // Ignore all possible mobile units.
    mask &= ~(MapFieldLandUnit | MapFieldAirUnit | MapFieldSeaUnit);

    points[0] = pos;
    // also use the bottom right
    if ((type.TileWidth > 1 || type.TileHeight > 1) &&
            pos.x + type.TileWidth - 1 < Map.Info.MapWidth &&
            pos.y + type.TileHeight - 1 < Map.Info.MapHeight) {
        points[1].x = pos.x + type.TileWidth - 1;
        points[1].y = pos.y + type.TileHeight - 1;
        ep = wp = 2; // start with two points
    } else {
        ep = wp = 1; // start with one point
    }
    matrix += w + w + 2;
    rp = 0;
    matrix[pos.x + pos.y * w] = 1; // mark start point

    //
    // Pop a point from stack, push all neighbours which could be entered.
    //
    for (;;) {
        while (rp != ep) {
            rpos = points[rp];
            for (int i = 0; i < 8; ++i) { // mark all neighbors
                pos = rpos + offset[i];
                m = matrix + pos.x + pos.y * w;
                if (*m) { // already checked
                    continue;
                }

                //
                // Look if we can build here and no enemies nearby.
                //
                if (CanBuildUnitType(&worker, type, pos, 1) &&
                        !AiEnemyUnitsInDistance(worker.Player, NULL, pos, 8)) {
                    if (AiCheckSurrounding(worker, type, pos.x, pos.y, backupok)) {
                        *dpos = pos;
                        delete[] points;
                        return 1;
                    } else if (backupok && backupPos.x == -1) {
                        backupPos = pos;
                    }
                }

                if (CanMoveToMask(pos, mask)) { // reachable
                    *m = 1;
                    points[wp] = pos; // push the point
                    if (++wp >= size) { // round about
                        wp = 0;
                    }
                } else { // unreachable
                    *m = 99;
                }
            }

            if (++rp >= size) { // round about
                rp = 0;
            }
        }

        //
        // Continue with next frame.
        //
        if (rp == wp) { // unreachable, no more points available
            break;
        }
        ep = wp;
    }
    delete[] points;

    if (backupPos.x != -1) {
        *dpos = backupPos;
        return 1;
    }
    return 0;
}
/**
**  Enemy units in distance.
**
**  @param unit   Find in distance for this unit.
**  @param range  Distance range to look.
**
**  @return       Number of enemy units.
*/
int AiEnemyUnitsInDistance(const CUnit &unit, unsigned range)
{
	return AiEnemyUnitsInDistance(unit.Player, unit.Type, unit.tilePos, range);
}
/**
**  Check if there's a unit that should be repaired.
*/
static void AiCheckRepair()
{
	int i;
	int j;
	int k;
	int n;
	bool repair_flag;

	n = AiPlayer->Player->TotalNumUnits;
	k = 0;
	// Selector for next unit
	for (i = n - 1; i >= 0; --i) {
		CUnit *unit = AiPlayer->Player->Units[i];
		if (unit && UnitNumber(*unit) == AiPlayer->LastRepairBuilding) {
			k = i + 1;
		}
	}

	for (i = k; i < n; ++i) {
		CUnit &unit = *AiPlayer->Player->Units[i];
		repair_flag = true;

		if (!unit.IsAliveOnMap()) {
			continue;
		}

		// Unit damaged?
		// Don't repair attacked unit (wait 5 sec before repairing)
		if (unit.Type->RepairHP &&
				unit.CurrentAction() != UnitActionBuilt &&
				unit.CurrentAction() != UnitActionUpgradeTo &&
				unit.Variable[HP_INDEX].Value < unit.Variable[HP_INDEX].Max &&
				unit.Attacked + 5 * CYCLES_PER_SECOND < GameCycle) {

			//
			// FIXME: Repair only units under control
			//
			if (AiEnemyUnitsInDistance(unit, unit.Stats->Variables[SIGHTRANGE_INDEX].Max)) {
				continue;
			}
			//
			// Must check, if there are enough resources
			//
			for (j = 1; j < MaxCosts; ++j) {
				if (unit.Stats->Costs[j] &&
						AiPlayer->Player->Resources[j] < 99) {
					repair_flag = false;
					break;
				}
			}

			//
			// Find a free worker, who can build this building can repair it?
			//
			if (repair_flag) {
				AiRepairUnit(unit);
				AiPlayer->LastRepairBuilding = UnitNumber(unit);
				return;
			}
		}
		// Building under construction but no worker
		if (unit.CurrentAction() == UnitActionBuilt) {
			int j;
			for (j = 0; j < AiPlayer->Player->TotalNumUnits; ++j) {
				COrderPtr order = AiPlayer->Player->Units[j]->CurrentOrder();
				if (order->Action == UnitActionRepair && order->GetGoal() == &unit) {
					break;
				}
			}
			if (j == AiPlayer->Player->TotalNumUnits) {
				// Make sure we have enough resources first
				for (j = 0; j < MaxCosts; ++j) {
					// FIXME: the resources don't necessarily have to be in storage
					if (AiPlayer->Player->Resources[j] < unit.Stats->Costs[j]) {
						break;
					}
				}
				if (j == MaxCosts) {
					AiRepairUnit(unit);
					AiPlayer->LastRepairBuilding = UnitNumber(unit);
					return;
				}
			}
		}
	}
	AiPlayer->LastRepairBuilding = 0;
}
Beispiel #7
0
/**
**  Check if there's a unit that should be repaired.
*/
static void AiCheckRepair()
{
	const int n = AiPlayer->Player->GetUnitCount();
	int k = 0;

	// Selector for next unit
	for (int i = n - 1; i >= 0; --i) {
		const CUnit &unit = AiPlayer->Player->GetUnit(i);
		if (UnitNumber(unit) == AiPlayer->LastRepairBuilding) {
			k = i + 1;
		}
	}

	for (int i = k; i < n; ++i) {
		CUnit &unit = AiPlayer->Player->GetUnit(i);
		bool repair_flag = true;

		if (!unit.IsAliveOnMap()) {
			continue;
		}

		// Unit damaged?
		// Don't repair attacked unit (wait 5 sec before repairing)
		if (unit.Type->RepairHP
			//Wyrmgus start
//			&& unit.CurrentAction() != UnitActionBuilt
			&& (unit.CurrentAction() != UnitActionBuilt || unit.Type->BoolFlag[BUILDEROUTSIDE_INDEX].value)
			//Wyrmgus end
			&& unit.CurrentAction() != UnitActionUpgradeTo
			//Wyrmgus start
//			&& unit.Variable[HP_INDEX].Value < unit.Variable[HP_INDEX].Max
			&& unit.Variable[HP_INDEX].Value < unit.GetModifiedVariable(HP_INDEX, VariableMax)
//			&& unit.Attacked + 5 * CYCLES_PER_SECOND < GameCycle) {
			) {
			//Wyrmgus end
			//
			// FIXME: Repair only units under control
			//
			//Wyrmgus start
//			if (AiEnemyUnitsInDistance(unit, unit.Stats->Variables[SIGHTRANGE_INDEX].Max)) {
			if (AiEnemyUnitsInDistance(unit, unit.Variable[SIGHTRANGE_INDEX].Max, unit.MapLayer)) {
			//Wyrmgus end
				continue;
			}
			//
			// Must check, if there are enough resources
			//
			for (int j = 1; j < MaxCosts; ++j) {
				if (unit.Stats->Costs[j]
					&& (AiPlayer->Player->Resources[j] + AiPlayer->Player->StoredResources[j])  < 99) {
					repair_flag = false;
					break;
				}
			}

			//
			// Find a free worker, who can build this building can repair it?
			//
			if (repair_flag) {
				AiRepairUnit(unit);
				AiPlayer->LastRepairBuilding = UnitNumber(unit);
				return;
			}
		}
		// Building under construction but no worker
		if (unit.CurrentAction() == UnitActionBuilt) {
			int j;
			for (j = 0; j < AiPlayer->Player->GetUnitCount(); ++j) {
				COrder *order = AiPlayer->Player->GetUnit(j).CurrentOrder();
				if (order->Action == UnitActionRepair) {
					COrder_Repair &orderRepair = *static_cast<COrder_Repair *>(order);

					if (orderRepair.GetReparableTarget() == &unit) {
						break;
					}
				}
			}
			if (j == AiPlayer->Player->GetUnitCount()) {
				// Make sure we have enough resources first
				for (j = 0; j < MaxCosts; ++j) {
					// FIXME: the resources don't necessarily have to be in storage
					if (AiPlayer->Player->Resources[j] + AiPlayer->Player->StoredResources[j] < unit.Stats->Costs[j]) {
						break;
					}
				}
				if (j == MaxCosts) {
					AiRepairUnit(unit);
					AiPlayer->LastRepairBuilding = UnitNumber(unit);
					return;
				}
			}
		}
	}
	AiPlayer->LastRepairBuilding = 0;
}