/**
**  Build new units to reduce the food shortage.
*/
static bool AiRequestSupply()
{
	// Don't request supply if we're sleeping.  When the script starts it may
	// request a better unit than the one we pick here.  If we only have enough
	// resources for one unit we don't want to build the wrong one.
	if (AiPlayer->SleepCycles != 0) {
		/* we still need supply */
		return true;
	}

	// Count the already made build requests.
	int counter[UnitTypeMax];

	AiGetBuildRequestsCount(AiPlayer, counter);
	struct cnode cache[16];

	memset(cache, 0, sizeof(cache));

	//
	// Check if we can build this?
	//
	int j = 0;
	const int n = AiHelpers.UnitLimit[0].size();

	for (int i = 0; i < n; ++i) {
		CUnitType &type = *AiHelpers.UnitLimit[0][i];
		if (counter[type.Slot]) { // Already ordered.
#if defined(DEBUG) && defined(DebugRequestSupply)
			DebugPrint("%d: AiRequestSupply: Supply already build in %s\n"
				_C_ AiPlayer->Player->Index _C_ type->Name.c_str());
#endif
			return false;
		}

		if (!AiRequestedTypeAllowed(AiPlayer->Player, type)) {
			continue;
		}

		//
		// Check if resources available.
		//
		cache[j].needmask = AiCheckUnitTypeCosts(type);

		for (int c = 1; c < MaxCosts; ++c) {
			cache[j].unit_cost += type.Stats[AiPlayer->Player->Index].Costs[c];
		}
		cache[j].unit_cost += type.Supply - 1;
		cache[j].unit_cost /= type.Supply;
		cache[j++].type = &type;
		Assert(j < 16);
	}

	if (j > 1)
		qsort(&cache, j, sizeof (struct cnode), cnode_cmp);

	if (j) {
		if (!cache[0].needmask) {
			CUnitType &type = *cache[0].type;
			if (AiMakeUnit(type, -1, -1)) {
				AiBuildQueue newqueue;
				newqueue.Type = &type;
				newqueue.Want = 1;
				newqueue.Made = 1;
				AiPlayer->UnitTypeBuilt.insert(
					AiPlayer->UnitTypeBuilt.begin(), newqueue);
#if defined( DEBUG) && defined( DebugRequestSupply )
				DebugPrint("%d: AiRequestSupply: build Supply in %s\n"
					_C_ AiPlayer->Player->Index _C_ type->Name.c_str());
#endif
				return false;
			}
		}
		AiPlayer->NeededMask |= cache[0].needmask;
	}


#if defined( DEBUG) && defined( DebugRequestSupply )
	std::string needed("");
	for (int i = 1; i < MaxCosts; ++i) {
		if (cache[0].needmask & (1 << i))
		{
			needed += ":";
			switch (i)
			{
				case GoldCost:
					needed += "Gold<";
				break;
				case WoodCost:
					needed += "Wood<";
				break;
				case OilCost:
					needed += "Oil<";
				break;
				default:
					needed += "unknown<";
				break;
			}
			needed += '0' + i;
			needed += ">";
		}
	}
	DebugPrint("%d: AiRequestSupply: needed build %s with %s resource\n"
		_C_ AiPlayer->Player->Index _C_ cache[0].type->Name.c_str() _C_ needed.c_str());
#endif
	return true;
}
Beispiel #2
0
/**
**  Check if everything is fine, send new requests to resource manager.
*/
static void AiCheckUnits()
{
	//  Count the already made build requests.
	int counter[UnitTypeMax];
	AiGetBuildRequestsCount(*AiPlayer, counter);

	//  Remove non active units.
	const int unitCount = AiPlayer->Player->GetUnitCount();
	for (int i = 0; i < unitCount; ++i) {
		const CUnit &unit = AiPlayer->Player->GetUnit(i);

		if (!unit.Active) {
			counter[unit.Type->Slot]--;
		}
	}
	const int *unit_types_count = AiPlayer->Player->UnitTypesCount;

	//  Look if some unit-types are missing.
	int n = AiPlayer->UnitTypeRequests.size();
	for (int i = 0; i < n; ++i) {
		const unsigned int t = AiPlayer->UnitTypeRequests[i].Type->Slot;
		const int x = AiPlayer->UnitTypeRequests[i].Count;

		// Add equivalent units
		int e = unit_types_count[t];
		if (t < AiHelpers.Equiv.size()) {
			for (unsigned int j = 0; j < AiHelpers.Equiv[t].size(); ++j) {
				e += unit_types_count[AiHelpers.Equiv[t][j]->Slot];
			}
		}
		const int requested = x - e - counter[t];
		if (requested > 0) {  // Request it.
			AiAddUnitTypeRequest(*AiPlayer->UnitTypeRequests[i].Type, requested);
			counter[t] += requested;
		}
		counter[t] -= x;
	}

	AiPlayer->Force.CheckUnits(counter);

	//  Look if some upgrade-to are missing.
	n = AiPlayer->UpgradeToRequests.size();
	for (int i = 0; i < n; ++i) {
		const unsigned int t = AiPlayer->UpgradeToRequests[i]->Slot;
		const int x = 1;

		//  Add equivalent units
		int e = unit_types_count[t];
		if (t < AiHelpers.Equiv.size()) {
			for (unsigned int j = 0; j < AiHelpers.Equiv[t].size(); ++j) {
				e += unit_types_count[AiHelpers.Equiv[t][j]->Slot];
			}
		}

		const int requested = x - e - counter[t];
		if (requested > 0) {  // Request it.
			AiAddUpgradeToRequest(*AiPlayer->UpgradeToRequests[i]);
			counter[t] += requested;
		}
		counter[t] -= x;
	}

	//  Look if some researches are missing.
	n = (int)AiPlayer->ResearchRequests.size();
	for (int i = 0; i < n; ++i) {
		if (UpgradeIdAllowed(*AiPlayer->Player, AiPlayer->ResearchRequests[i]->ID) == 'A') {
			AiAddResearchRequest(AiPlayer->ResearchRequests[i]);
		}
	}
}
void AiNewDepotRequest(CUnit &worker) {
/*
	DebugPrint("%d: Worker %d report: Resource [%d] too far from depot, returning time [%d].\n"
				_C_ worker->Player->Index _C_ worker->Slot
				_C_ worker->CurrentResource
				_C_ worker->Data.Move.Cycles
				);
	*/

	Vec2i pos = {-1, -1};
	ResourceInfo *resinfo = worker.Type->ResInfo[worker.CurrentResource];

	if (resinfo->TerrainHarvester) {
		pos = worker.CurrentOrder()->Arg1.Resource.Pos;
	} else {
		CUnit *mine = worker.CurrentOrder()->Arg1.Resource.Mine;
		if (mine) {
			pos = mine->tilePos;
		}
	}

	if (pos.x != -1 && NULL != FindDepositNearLoc(worker.Player,
				pos.x, pos.y, 10, worker.CurrentResource)) {
		/*
		 * New Depot has just be finished and worker just return to old depot
		 * (far away) from new Deopt.
		 */
		return;
	}
	CUnitType *best_type = NULL;
	int best_cost = 0;
	//int best_mask = 0;
	// Count the already made build requests.
	int counter[UnitTypeMax];

	AiGetBuildRequestsCount(worker.Player->Ai, counter);

	const int n = AiHelpers.Depots[worker.CurrentResource - 1].size();

	for (int i = 0; i < n; ++i) {
		CUnitType &type = *AiHelpers.Depots[worker.CurrentResource - 1][i];

		if (counter[type.Slot]) { // Already ordered.
			return;
		}
		if (!AiRequestedTypeAllowed(worker.Player, type)) {
			continue;
		}

		// Check if resources available.
		//int needmask = AiCheckUnitTypeCosts(type);
		int cost = 0;
		for (int c = 1; c < MaxCosts; ++c) {
			cost += type.Stats[worker.Player->Index].Costs[c];
		}

		if (best_type == NULL || (cost < best_cost)) {
			best_type = &type;
			best_cost = cost;
			//best_mask = needmask;
		}

	}

	if (best_type) {
		//if(!best_mask) {
			AiBuildQueue queue;

			queue.Type = best_type;
			queue.Want = 1;
			queue.Made = 0;
			queue.X = pos.x;
			queue.Y = pos.y;

			worker.Player->Ai->UnitTypeBuilt.push_back(queue);

			DebugPrint("%d: Worker %d report: Requesting new depot near [%d,%d].\n"
				_C_ worker.Player->Index _C_ worker.Slot
				_C_ queue.X _C_ queue.Y
				);
			/*
		} else {
			AiPlayer->NeededMask |= best_mask;
		}
		*/
	}
}
Beispiel #4
0
void AiNewDepotRequest(CUnit &worker)
{
#if 0
    DebugPrint("%d: Worker %d report: Resource [%d] too far from depot, returning time [%d].\n"
               _C_ worker->Player->Index _C_ worker->Slot
               _C_ worker->CurrentResource
               _C_ worker->Data.Move.Cycles);
#endif
    Assert(worker.CurrentAction() == UnitActionResource);
    COrder_Resource &order = *static_cast<COrder_Resource *>(worker.CurrentOrder());

    const Vec2i pos = order.GetHarvestLocation();

    if (pos.x != -1 && NULL != FindDepositNearLoc(*worker.Player, pos, 10, worker.CurrentResource)) {
        /*
         * New Depot has just be finished and worker just return to old depot
         * (far away) from new Deopt.
         */
        return;
    }
    CUnitType *best_type = NULL;
    int best_cost = 0;
    //int best_mask = 0;
    // Count the already made build requests.
    int counter[UnitTypeMax];

    AiGetBuildRequestsCount(*worker.Player->Ai, counter);

    const int n = AiHelpers.Depots[worker.CurrentResource - 1].size();

    for (int i = 0; i < n; ++i) {
        CUnitType &type = *AiHelpers.Depots[worker.CurrentResource - 1][i];

        if (counter[type.Slot]) { // Already ordered.
            return;
        }
        if (!AiRequestedTypeAllowed(*worker.Player, type)) {
            continue;
        }

        // Check if resources available.
        //int needmask = AiCheckUnitTypeCosts(type);
        int cost = 0;
        for (int c = 1; c < MaxCosts; ++c) {
            cost += type.Stats[worker.Player->Index].Costs[c];
        }

        if (best_type == NULL || (cost < best_cost)) {
            best_type = &type;
            best_cost = cost;
            //best_mask = needmask;
        }
    }

    if (best_type) {
        //if(!best_mask) {
        AiBuildQueue queue;

        queue.Type = best_type;
        queue.Want = 1;
        queue.Made = 0;
        queue.Pos = pos;

        worker.Player->Ai->UnitTypeBuilt.push_back(queue);

        DebugPrint("%d: Worker %d report: Requesting new depot near [%d,%d].\n"
                   _C_ worker.Player->Index _C_ UnitNumber(worker)
                   _C_ queue.Pos.x _C_ queue.Pos.y);
        /*
        } else {
        	AiPlayer->NeededMask |= best_mask;
        }
        */
    }
}