Beispiel #1
0
//Wyrmgus start
//static int AiAssignHarvesterFromTerrain(CUnit &unit, int resource)
static int AiAssignHarvesterFromTerrain(CUnit &unit, int resource, int resource_range)
//Wyrmgus end
{
	// TODO : hardcoded forest
	Vec2i forestPos;
	//Wyrmgus start
	Vec2i rockPos;
	//Wyrmgus end

	// Code for terrain harvesters. Search for piece of terrain to mine.
	//Wyrmgus start
//	if (FindTerrainType(unit.Type->MovementMask, MapFieldForest, 1000, *unit.Player, unit.tilePos, &forestPos)) {
	if (resource == WoodCost && FindTerrainType(unit.Type->MovementMask, MapFieldForest, resource_range, *unit.Player, unit.tilePos, &forestPos, unit.MapLayer)) {
	//Wyrmgus end
		//Wyrmgus start
//		CommandResourceLoc(unit, forestPos, FlushCommands);
		CommandResourceLoc(unit, forestPos, FlushCommands, unit.MapLayer);
		//Wyrmgus end
		return 1;
	}
	//Wyrmgus start
	if (resource == StoneCost && FindTerrainType(unit.Type->MovementMask, MapFieldRocks, resource_range, *unit.Player, unit.tilePos, &rockPos, unit.MapLayer)) {
		CommandResourceLoc(unit, rockPos, FlushCommands, unit.MapLayer);
		return 1;
	}
	//Wyrmgus end
	// Ask the AI to explore...
	//Wyrmgus start
//	AiExplore(unit.tilePos, MapFieldLandUnit);
	//Wyrmgus end

	// Failed.
	return 0;
}
Beispiel #2
0
void FindAndGatherResource(CUnit* unit, int resourceType) {
    CUnit* dest;
    int x, y, result;

    switch (resourceType) {
        case GoldCost:
            dest = UnitFindResource(unit, unit->X, unit->Y, FIND_RESOURCE_RANGE, resourceType);
            if (dest != NoUnitP) {
                SendCommandResource(unit, dest, 1);
                // TODO: don't know what StopResourceFlag corresponds to in 2.2.4 code
                // unit->StopResourceFlag = 1;
            } else {
                SendResponseMessage("Unable to find gold within range.\n", 3);
                return;
            }
            break;
        case WoodCost:
            result = FindTerrainType(unit->Type->MovementMask, MapFieldForest, 0, FIND_RESOURCE_RANGE, unit->Player, unit->X, unit->Y, &x, &y);
            if (result) {
                SendCommandResourceLoc(unit, x, y, 1);
                // TODO: don't know what StopResourceFlag corresponds to in 2.2.4 code
                //unit->StopResourceFlag = 1;
            } else {
                SendResponseMessage("Unable to find wood within range.\n", 3);
                return;
            }
            break;
        default:
            SendResponseMessage("Unknown resource type\n", 3);
    }
    SendResponseMessage("OK\n", 3);
}
Beispiel #3
0
/**
**  Send unit harvest a location
**
**  @param unit   pointer to unit.
**  @param x      X map position for harvest.
**  @param y      Y map position for harvest.
**  @param flush  if true, flush command queue.
*/
void CommandResourceLoc(CUnit *unit, int x, int y, int flush)
{
	COrder *order;
	int nx;
	int ny;

	//
	// Check if unit is still valid? (NETWORK!)
	//
	if (!unit->Removed && unit->Orders[0]->Action != UnitActionDie) {
		if (unit->Type->Building) {
			// FIXME: should find a better way for pending orders.
			order = &unit->NewOrder;
			ReleaseOrder(order);
		} else if (!(order = GetNextOrder(unit, flush))) {
			return;
		}
		order->Init();

		order->Action = UnitActionResource;

		//  Find the closest piece of wood next to a tile where the unit can move
		if (!FindTerrainType(0, (unit->Type->MovementMask), 1, 20,
				unit->Player, x, y, &nx, &ny)) {
			DebugPrint("FIXME: Give up???\n");
		}

		// Max Value > 1
		if ((abs(nx - x) | abs(ny - y)) > 1) {
			if (!FindTerrainType(0, MapFieldForest, 0, 20, unit->Player,
					nx, ny, &nx, &ny)) {
				DebugPrint("FIXME: Give up???\n");
			}
		} else {
			// The destination is next to a reacahble tile.
			nx = x;
			ny = y;
		}
		order->X = nx;
		order->Y = ny;

		order->Range = 1;
	}
	ClearSavedAction(unit);
}
Beispiel #4
0
/**
**  Assign worker to gather a certain resource from terrain.
**
**  @param unit      pointer to the unit.
**  @param resource  resource identification.
**
**  @return          1 if the worker was assigned, 0 otherwise.
*/
static int AiAssignHarvesterFromTerrain(CUnit &unit, int resource)
{
    // TODO : hardcoded forest
    Vec2i forestPos;

    // Code for terrain harvesters. Search for piece of terrain to mine.
    if (FindTerrainType(unit.Type->MovementMask, MapFieldForest, 1000, *unit.Player, unit.tilePos, &forestPos)) {
        CommandResourceLoc(unit, forestPos, FlushCommands);
        return 1;
    }
    // Ask the AI to explore...
    AiExplore(unit.tilePos, MapFieldLandUnit);

    // Failed.
    return 0;
}
Beispiel #5
0
bool COrder_Resource::FindAnotherResource(CUnit &unit)
{
	if (this->CurrentResource) {
		const ResourceInfo *resinfo = unit.Type->ResInfo[this->CurrentResource];
		if (resinfo) {
			//Wyrmgus start
	//		if (!resinfo.TerrainHarvester) {
			if (!Map.Info.IsPointOnMap(this->goalPos)) {
			//Wyrmgus end
				CUnit *newGoal = UnitFindResource(unit, this->Resource.Mine ? *this->Resource.Mine : unit, 8, this->CurrentResource, 1);

				if (newGoal) {
					CUnit *mine = this->Resource.Mine;
					if (mine) {
						unit.DeAssignWorkerFromMine(*mine);
					}
					unit.AssignWorkerToMine(*newGoal);
					this->Resource.Mine = newGoal;
					this->goalPos.x = -1;
					this->goalPos.y = -1;
					this->State = SUB_MOVE_TO_RESOURCE;
					this->SetGoal(newGoal);
					return true;
				}
			} else {
				Vec2i resPos;
				//Wyrmgus start
//				if (FindTerrainType(unit.Type->MovementMask, MapFieldForest, 8, *unit.Player, unit.tilePos, &resPos)) {
				if ((this->CurrentResource == WoodCost && FindTerrainType(unit.Type->MovementMask, MapFieldForest, 8, *unit.Player, unit.tilePos, &resPos)) || (this->CurrentResource == StoneCost && FindTerrainType(unit.Type->MovementMask, MapFieldRocks, 8, *unit.Player, unit.tilePos, &resPos))) {
				//Wyrmgus end
					this->goalPos = resPos;
					this->State = SUB_MOVE_TO_RESOURCE;
					DebugPrint("Found a better place to harvest %d,%d\n" _C_ resPos.x _C_ resPos.y);
					return true;
				}
			}
		}
	}
	return false;
}
/**
**  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;
}
Beispiel #7
0
/**
**  Move unit to terrain.
**
**  @return      1 if reached, -1 if unreacheable, 0 if on the way.
*/
int COrder_Resource::MoveToResource_Terrain(CUnit &unit)
{
	Vec2i pos = this->goalPos;

	// Wood gone, look somewhere else.
	if ((Map.Info.IsPointOnMap(pos) == false || Map.Field(pos)->IsTerrainResourceOnMap(CurrentResource) == false)
		&& (!unit.IX) && (!unit.IY)) {
		//Wyrmgus start
//		if (!FindTerrainType(unit.Type->MovementMask, MapFieldForest, 16, *unit.Player, this->goalPos, &pos)) {
		if ((this->CurrentResource == WoodCost && !FindTerrainType(unit.Type->MovementMask, MapFieldForest, 16, *unit.Player, this->goalPos, &pos)) || (this->CurrentResource == StoneCost && !FindTerrainType(unit.Type->MovementMask, MapFieldRocks, 16, *unit.Player, this->goalPos, &pos))) {
		//Wyrmgus end
			// no wood in range
			return -1;
		} else {
			this->goalPos = pos;
		}
	}
	switch (DoActionMove(unit)) {
		case PF_UNREACHABLE:
			//Wyrmgus start
			//if is unreachable and is on a raft, see if the raft can move closer
			if ((Map.Field(unit.tilePos)->Flags & MapFieldBridge) && !unit.Type->BoolFlag[BRIDGE_INDEX].value && unit.Type->UnitType == UnitTypeLand) {
				std::vector<CUnit *> table;
				Select(unit.tilePos, unit.tilePos, table);
				for (size_t i = 0; i != table.size(); ++i) {
					if (!table[i]->Removed && table[i]->Type->BoolFlag[BRIDGE_INDEX].value && table[i]->CanMove()) {
						if (table[i]->CurrentAction() == UnitActionStill) {
							CommandStopUnit(*table[i]);
							CommandMove(*table[i], this->HasGoal() ? this->GetGoal()->tilePos : this->goalPos, FlushCommands);
						}
						return 0;
					}
				}
			}
			//Wyrmgus end
			unit.Wait = 10;
			if (unit.Player->AiEnabled) {
				this->Range++;
				if (this->Range >= 5) {
					this->Range = 0;
					AiCanNotMove(unit);
				}
			}
			//Wyrmgus start
//			if (FindTerrainType(unit.Type->MovementMask, MapFieldForest, 9999, *unit.Player, unit.tilePos, &pos)) {
			if ((this->CurrentResource == WoodCost && FindTerrainType(unit.Type->MovementMask, MapFieldForest, 9999, *unit.Player, unit.tilePos, &pos)) || (this->CurrentResource == StoneCost && FindTerrainType(unit.Type->MovementMask, MapFieldRocks, 9999, *unit.Player, unit.tilePos, &pos))) {
			//Wyrmgus end
				this->goalPos = pos;
				DebugPrint("Found a better place to harvest %d,%d\n" _C_ pos.x _C_ pos.y);
				// FIXME: can't this overflow? It really shouldn't, since
				// x and y are really supossed to be reachable, checked thorugh a flood fill.
				// I don't know, sometimes stuff happens.
				return 0;
			}
			return -1;
		case PF_REACHED:
			return 1;
		case PF_WAIT:
			if (unit.Player->AiEnabled) {
				this->Range++;
				if (this->Range >= 5) {
					this->Range = 0;
					AiCanNotMove(unit);
				}
			}
		default:
			return 0;
	}
}
Beispiel #8
0
/**
**  Wait in depot, for the resources stored.
**
**  @param unit  Pointer to unit.
**
**  @return      TRUE if ready, otherwise FALSE.
*/
bool COrder_Resource::WaitInDepot(CUnit &unit)
{
	const ResourceInfo &resinfo = *unit.Type->ResInfo[this->CurrentResource];
	const CUnit *depot = ResourceDepositOnMap(unit.tilePos, resinfo.ResourceId);

	//Assert(depot);

	// Range hardcoded. don't stray too far though
	//Wyrmgus start
//	if (resinfo.TerrainHarvester) {
	if (!this->Resource.Mine) {
	//Wyrmgus end
		Vec2i pos = this->Resource.Pos;

		//Wyrmgus start
//		if (FindTerrainType(unit.Type->MovementMask, MapFieldForest, 10, *unit.Player, pos, &pos)) {
		if ((this->CurrentResource == WoodCost && FindTerrainType(unit.Type->MovementMask, MapFieldForest, 10, *unit.Player, pos, &pos)) || (this->CurrentResource == StoneCost && FindTerrainType(unit.Type->MovementMask, MapFieldRocks, 10, *unit.Player, pos, &pos))) {
		//Wyrmgus end
			if (depot) {
				DropOutNearest(unit, pos, depot);
			}
			this->goalPos = pos;
			//Wyrmgus start
			if (this->CurrentResource == WoodCost) { //tree tiles can regrow, so we need to check if any have regrown closer to the worker
				Vec2i forestPos;
				int max_forest_range = std::max<int>(abs(unit.tilePos.x - this->goalPos.x), abs(unit.tilePos.y - this->goalPos.y));
				if (FindTerrainType(unit.Type->MovementMask, MapFieldForest, max_forest_range, *unit.Player, unit.tilePos, &forestPos)) {
					if (PlaceReachable(unit, forestPos, 1, 1, 0, 1, max_forest_range * 4)) {
						this->goalPos = forestPos;
					}
				}
			}
			//Wyrmgus end
		} else {
			if (depot) {
				DropOutOnSide(unit, LookingW, depot);
			}
			this->Finished = true;
			return false;
		}
	} else {
		const unsigned int tooManyWorkers = 15;
		CUnit *mine = this->Resource.Mine;
		const int range = 15;
		CUnit *newdepot = NULL;
		CUnit *goal = NULL;
		const bool longWay = unit.pathFinderData->output.Cycles > 500;

		//Wyrmgus start
//		if (unit.Player->AiEnabled && AiPlayer && AiPlayer->BuildDepots) {
		if (depot && unit.Player->AiEnabled && AiPlayer && AiPlayer->BuildDepots) { //check if the depot is valid
		//Wyrmgus end
			// If the depot is overused, we need first to try to switch into another depot
			// Use depot's ref counter for that
			if (longWay || !mine || (depot->Refs > tooManyWorkers)) {
				newdepot = AiGetSuitableDepot(unit, *depot, &goal);
				if (newdepot == NULL && longWay) {
					// We need a new depot
					AiNewDepotRequest(unit);
				}
			}
		}

		// If goal is not NULL, then we got it in AiGetSuitableDepot
		if (!goal) {
			goal = UnitFindResource(unit, newdepot ? *newdepot : (mine ? *mine : unit), mine ? range : 1000,
									this->CurrentResource, unit.Player->AiEnabled, newdepot ? newdepot : depot);
		}

		if (goal) {
			if (depot) {
				DropOutNearest(unit, goal->tilePos + goal->Type->GetHalfTileSize(), depot);
			}

			if (goal != mine) {
				if (mine) {
					unit.DeAssignWorkerFromMine(*mine);
				}
				unit.AssignWorkerToMine(*goal);
				this->Resource.Mine = goal;
			}
			this->SetGoal(goal);
			this->goalPos.x = this->goalPos.y = -1;
		} else {
#ifdef DEBUG
			const Vec2i &pos = mine ? mine->tilePos : unit.tilePos;
			DebugPrint("%d: Worker %d report: [%d,%d] Resource gone near [%d,%d] in range %d. Sit and play dumb.\n"
					   _C_ unit.Player->Index _C_ UnitNumber(unit)
					   _C_ unit.tilePos.x _C_ unit.tilePos.y
					   _C_ pos.x _C_ pos.y _C_ range);
#endif // DEBUG
			if (depot) {
				DropOutOnSide(unit, LookingW, depot);
			}
			if (mine) {
				unit.DeAssignWorkerFromMine(*mine);
				this->Resource.Mine = NULL;
			}
			this->Finished = true;
			return false;
		}
	}
	return true;
}