Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- BuildingClass* UnitClass::Find_Best_Refinery(void) const
- {
- /*
- Warning for anyone messing around with this:
- Distance() is ambiguously overloaded -- be careful which verison you're using!
- If the inputs are CELLs, then the output is in terms of cells, but
- If the inputs are COORDINATEs, OBJECTSs, or TARGETs, then the output is in terms of leptons
- (Leptons are 1/256 of a CELL)
- (Also, the CELL version of Distance() uses 1.5 for diagonal distance instead of sqrt(2); should maybe improve that someday...)
- */
- static DynamicVectorClass<RefineryData> _refineries;
- _refineries.Clear();
- if (ActiveCFEPatchConfig.EnableASPathing){
- for (int i = 0; i < Buildings.Count(); ++i) {
- BuildingClass* refinery = Buildings.Ptr(i);
- if (refinery != NULL &&
- refinery->House == House &&
- !refinery->IsInLimbo &&
- *refinery == STRUCT_REFINERY) {
- int astar_result = Find_Path_AStar(nullptr, Coord_Cell(Coord), Coord_Cell(refinery->Center_Coord()), 1, MOVE_NO, -1);
- if (astar_result){
- _refineries.Add(RefineryData{ refinery, astar_result, 0 });
- }
- // A-Star may return zero when you're already right next to the refinery, or because there's no path at all
- // In the former case, fall back to crow-flies distance
- // In the latter case, don't add the refinery to the list
- else{
- int crowflies_result = Distance(Coord_Cell(refinery->Center_Coord()));
- if (crowflies_result <= 6){
- _refineries.Add(RefineryData{ refinery, crowflies_result, 0 });
- }
- //else{
- // CFE_Debug_Printf("Omitted a refinery! Unreachable?\n");
- //}
- }
- }
- }
- }
- else{
- for (int i = 0; i < Buildings.Count(); ++i) {
- BuildingClass* refinery = Buildings.Ptr(i);
- if (refinery != NULL &&
- refinery->House == House &&
- !refinery->IsInLimbo &&
- *refinery == STRUCT_REFINERY) {
- _refineries.Add(RefineryData{ refinery, Distance(refinery), 0 });
- }
- }
- }
- // Base case for zero or one refineries.
- if (_refineries.Count() == 0) {
- return NULL;
- } else if (_refineries.Count() == 1) {
- return _refineries[0].Refinery;
- }
- // Count harvesters going to each refinery as well as the total.
- int num_harvesters = 0;
- for (int i = 0; i < Units.Count(); ++i) {
- UnitClass* unit = Units.Ptr(i);
- if (unit->IsActive && unit->Class->IsToHarvest && unit->House == House) {
- BuildingClass* refinery = unit->Tiberium_Unload_Refinery();
- if (refinery != NULL) {
- int index = _refineries.ID(RefineryData{ refinery });
- //assert(index >= 0); // Chthon CFE NOTE: Bad! _refineries may not be an exhaustive list because you might have refinieries in multiple zones in RA and/or A-Star may have failed to find paths for some refineries.
- if (index >= 0){
- // if queue jumping is enabled, don't count other harvies that are further away b/c you will jump them
- if (ActiveCFEPatchConfig.EnableHarvyOptimize && ActiveCFEPatchConfig.EnableHarvyQueueJump){
- int other_harvy_distance;
- int jumpcutoff;
- if (ActiveCFEPatchConfig.EnableASPathing){
- jumpcutoff = ActiveCFEPatchConfig.HarvyQueueJumpCutoff;
- int other_harvy_distance_astar = unit->Find_Path_AStar(nullptr, Coord_Cell(unit->Coord), Coord_Cell(refinery->Center_Coord()), 1, MOVE_NO, -1);
- if (other_harvy_distance_astar){
- other_harvy_distance = other_harvy_distance_astar;
- }
- // again, A-Star might have returned zero if other harvy is already right by the refinery
- else {
- int other_harvy_distance_astar_crowflies = unit->Distance(Coord_Cell(refinery->Center_Coord()));
- if (other_harvy_distance_astar_crowflies <= 6){
- other_harvy_distance = other_harvy_distance_astar_crowflies;
- }
- else{
- other_harvy_distance = INT_MAX; //unreachable
- }
- }
- }
- // not using A-Star
- else{
- jumpcutoff = Cell_To_Lepton(ActiveCFEPatchConfig.HarvyQueueJumpCutoff);
- other_harvy_distance = unit->Distance(refinery);
- }
- if ((_refineries[index].Distance < other_harvy_distance) && (other_harvy_distance > jumpcutoff)){
- //CFE_Debug_Printf("Expect to jump!\n");
- continue;
- }
- } // end of queue jumping jiggery pokery
- _refineries[index].Harvesters++;
- num_harvesters++;
- }
- }
- }
- }
- // Increase distance to account for wait times for other harvies to unload
- // To prevent thrashing, use a lower penalty if you're already very close to the refinery
- if (ActiveCFEPatchConfig.EnableHarvyOptimize){
- int queuedunloadpenalty;
- int thrashingcutoff;
- // If A-Star was used, the stored distances should be in CELL units; otherwise they'll be in lepton units
- if (ActiveCFEPatchConfig.EnableASPathing){
- queuedunloadpenalty = ActiveCFEPatchConfig.HarvyOptimizeUnloadWaitWeight;
- thrashingcutoff = ActiveCFEPatchConfig.HarvyOptimizeThrashingCutoff;
- }
- else {
- queuedunloadpenalty = Cell_To_Lepton(ActiveCFEPatchConfig.HarvyOptimizeUnloadWaitWeight);
- thrashingcutoff = Cell_To_Lepton(ActiveCFEPatchConfig.HarvyOptimizeThrashingCutoff);
- }
- int thrashingpenalty = (queuedunloadpenalty * ActiveCFEPatchConfig.HarvyOptimizeThrashingNumerator) / ActiveCFEPatchConfig.HarvyOptimizeThrashingDenominator;
- for (int i = 0; i < _refineries.Count(); ++i) {
- //CFE_Debug_Printf("Refinery %i distance is %i.\n", i, _refineries[i].Distance);
- if (_refineries[i].Distance < thrashingcutoff){
- _refineries[i].Distance += (_refineries[i].Harvesters * thrashingpenalty);
- }
- else{
- _refineries[i].Distance += (_refineries[i].Harvesters * queuedunloadpenalty);
- }
- // don't do this -- doesn't look like TiberiumUnloadRefinery is cleared until after it leaves
- //if (_refineries[i].ID->Is_Something_Attached()){
- // _refineries[i].Distance += (queuedunloadpenalty/2); // on average an already-docked harvy has half a load to go.
- //}
- //CFE_Debug_Printf("Refinery %i adjusted distance is %i.\n", i, _refineries[i].Distance);
- }
- }
- // Sort by distance (special case for 2 refineries as that's a single swap).
- if (_refineries.Count() == 2) {
- if (_refineries[0].Distance > _refineries[1].Distance) {
- RefineryData temp = _refineries[0];
- _refineries[0] = _refineries[1];
- _refineries[1] = temp;
- }
- } else {
- qsort(&_refineries[0], _refineries.Count(), sizeof(RefineryData), _refinery_compare);
- }
- // Impact of other harvies is now baked into distance values, so just take the lowest
- if (ActiveCFEPatchConfig.EnableHarvyOptimize){
- return _refineries[0].Refinery;
- }
- // Evenly distribute harvesters among refineries.
- int harvesters_per_refinery = (num_harvesters + _refineries.Count() - 1) / _refineries.Count();
- for (int i = 0; i < _refineries.Count(); ++i) {
- if (_refineries[i].Harvesters < harvesters_per_refinery) {
- return _refineries[i].Refinery;
- }
- }
- // Fall back on closest refinery
- return _refineries[0].Refinery;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement