예제 #1
0
/**
**  Check what must be built / trained.
*/
static void AiCheckingWork()
{
	// Supply has the highest priority
	if (AiPlayer->NeedSupply) {
		if (AiPlayer->UnitTypeBuilt.empty() || AiPlayer->UnitTypeBuilt[0].Type->Stats[AiPlayer->Player->Index].Variables[SUPPLY_INDEX].Value == 0) {
			AiPlayer->NeedSupply = false;
			AiRequestSupply();
		}
	}
	// Look to the build requests, what can be done.
	const int sz = AiPlayer->UnitTypeBuilt.size();
	for (int i = 0; i < sz; ++i) {
		AiBuildQueue &queue = AiPlayer->UnitTypeBuilt[AiPlayer->UnitTypeBuilt.size() - sz + i];
		CUnitType &type = *queue.Type;
		bool new_supply = false;

		// FIXME: must check if requirements are fulfilled.
		// Buildings can be destroyed.

		// Check if we have enough food.
		if (type.Stats[AiPlayer->Player->Index].Variables[DEMAND_INDEX].Value && !AiCheckSupply(*AiPlayer, type)) {
			AiPlayer->NeedSupply = true;
			new_supply = true;
		}
		// Check limits, AI should be broken if reached.
		if (queue.Want > queue.Made && AiPlayer->Player->CheckLimits(type) < 0) {
			continue;
		}
		// Check if resources available.
		const int c = AiCheckUnitTypeCosts(type);
		if (c) {
			AiPlayer->NeededMask |= c;
			// NOTE: we can continue and build things with lesser
			//  resource or other resource need!
			continue;
		} else if (queue.Want > queue.Made && queue.Wait <= GameCycle) {
			if (AiMakeUnit(type, queue.Pos)) {
				// AiRequestSupply can change UnitTypeBuilt so recalculate queue
				AiBuildQueue &queue2 = AiPlayer->UnitTypeBuilt[AiPlayer->UnitTypeBuilt.size() - sz + i];
				++queue2.Made;
				queue2.Wait = 0;
			} else if (queue.Type->Building) {
				// Finding a building place is costly, don't try again for a while
				if (queue.Wait == 0) {
					queue.Wait = GameCycle + 150;
				} else {
					queue.Wait = GameCycle + 450;
				}
			}
		}
		if (new_supply) {
			// trigger this last, because it may re-arrange the queue and invalidate our queue item
			AiRequestSupply();
		}
	}
}
예제 #2
0
/**
**  Check if the upgrade-to can be done.
**
**  @param type  FIXME: docu
*/
void AiAddUpgradeToRequest(CUnitType &type)
{
	// Check if resources are available.
	const int resourceNeeded = AiCheckUnitTypeCosts(type);
	if (resourceNeeded) {
		AiPlayer->NeededMask |= resourceNeeded;
		return;
	}
	if (AiPlayer->Player->CheckLimits(type) < 0) {
		return;
	}
	//
	// Check if we have a place for the upgrade to.
	//
	const int n = AiHelpers.Upgrade.size();
	std::vector<std::vector<CUnitType *> > &tablep = AiHelpers.Upgrade;

	if (type.Slot > n) { // Oops not known.
		DebugPrint("%d: AiAddUpgradeToRequest I: Nothing known about `%s'\n"
				   _C_ AiPlayer->Player->Index _C_ type.Ident.c_str());
		return;
	}
	std::vector<CUnitType *> &table = tablep[type.Slot];
	if (table.empty()) { // Oops not known.
		DebugPrint("%d: AiAddUpgradeToRequest II: Nothing known about `%s'\n"
				   _C_ AiPlayer->Player->Index _C_ type.Ident.c_str());
		return;
	}

	const int *unit_count = AiPlayer->Player->UnitTypesCount;
	for (unsigned int i = 0; i < table.size(); ++i) {
		//
		// The type is available
		//
		if (unit_count[table[i]->Slot]) {
			if (AiUpgradeTo(*table[i], type)) {
				return;
			}
		}
	}
}
예제 #3
0
/**
**  Assign worker to gather a certain resource.
**
**  @param unit      pointer to the unit.
**  @param resource  resource identification.
**
**  @return          1 if the worker was assigned, 0 otherwise.
*/
static int AiAssignHarvester(CUnit &unit, int resource)
{
	ResourceInfo *resinfo;

	// It can't.
	if (unit.Removed) {
		return 0;
	}

	resinfo = unit.Type->ResInfo[resource];
	Assert(resinfo);
	if (resinfo->TerrainHarvester) {
		Vec2i forestPos;

		//
		// Code for terrain harvesters. Search for piece of terrain to mine.
		//
		if (FindTerrainType(unit.Type->MovementMask, MapFieldForest, 0, 1000,
				unit.Player, unit.tilePos, &forestPos)) {
			CommandResourceLoc(unit, forestPos, FlushCommands);
			return 1;
		}
		// Ask the AI to explore...
		AiExplore(unit.tilePos, MapFieldLandUnit);
	} else {
		int exploremask = 0;
		//
		// Find a resource to harvest from.
		//
		CUnit *dest = UnitFindResource(unit,
				unit.tilePos.x, unit.tilePos.y, 1000, resource, true);

		if (dest) {
			//FIXME: rb - when workers can speedup building then such assign may be ok.
			//if(dest->CurrentAction() == UnitActionBuilt)
				//CommandBuildBuilding(unit, dest->tilePos, dest->Type, FlushCommands);
			//else
				CommandResource(unit, *dest, FlushCommands);
			return 1;
		}
#if 0
		//may this code touch needmask which will be reseted before next cycle
		if (resinfo->RefineryHarvester &&
			 (dest = UnitFindMiningArea(unit, unit.X, unit.Y, 1000, resource))) {
			int needmask;
			//int counter[UnitTypeMax];

			//
			// Count the already made build requests.
			//
			//AiGetBuildRequestsCount(counter);
			int n = AiHelpers.Refinery[resource - 1].size();
			for (int i = 0; i < n; ++i) {
				CUnitType *type = AiHelpers.Refinery[resource - 1][i];
				//if (counter[type->Slot]) { // Already ordered.
				//	return 0;
				//}

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

				//
				// Check if resources available.
				//
				needmask = AiCheckUnitTypeCosts(type);
				if(!needmask && AiMakeUnit(type)) {
					AiBuildQueue newqueue;
					newqueue.Type = type;
					newqueue.Want = 1;
					newqueue.Made = 1;
					newqueue.X = dest->X;
					newqueue.Y = dest->Y;
					AiPlayer->UnitTypeBuilt.insert(
						AiPlayer->UnitTypeBuilt.begin(), newqueue);
					return 0;
				}

			}

			return 0;
		}
#endif

		for (std::vector<CUnitType *>::iterator i = UnitTypes.begin();
			 i != UnitTypes.end(); i++) {
			if (*i && (*i)->GivesResource == resource) {
				switch ((*i)->UnitType) {
				case UnitTypeLand:
					exploremask |= MapFieldLandUnit;
					break;
				case UnitTypeFly:
					exploremask |= MapFieldAirUnit;
					break;
				case UnitTypeNaval:
					exploremask |= MapFieldSeaUnit;
					break;
				default:
					Assert(0);
				}
			}
		}
		// Ask the AI to explore
		AiExplore(unit.tilePos, exploremask);
	}

	// Failed.
	return 0;
}
예제 #4
0
/**
**  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;
}