Insomniumm / bwsal

Automatically exported from code.google.com/p/bwsal
0 stars 0 forks source link

Error in "isCompleted()" (the Unit* enum) for vespene geysers when refinery is destroyed and then rebuilt #22

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
What steps will reproduce the problem?
1. AI builds an assimilator
2. AIs assimilator gets destroyed
3. AI rebuilds assimilator

What is the expected output? What do you see instead?
Expected:
WorkerManager should rebalance workers after 120 frames.
Probes should return to mining the geyser

Actual:
WorkerManager rebalances its workers - check
WorkerManager fails to reassign probes to geyser.

What version of the product are you using? On what operating system?
BWAPI_Beta_2.6.1
Windows XP 32 bit

Please provide any additional information below.

Cause of problem:
The following IF statement (incorrectly?) becomes false:

"if ((*g)->getType().isRefinery() && (*g)->getPlayer()==Broodwar->self() &&
(*g)->isCompleted())"

STATE OF "(*g)->isCompleted()" AT VARIOUS POINTS IN TIME(where *g is the
current basegeyser):

Initial state - True, geyser exists
Assimilator under construction - False, Geyser is unaccessible
Assimilator completed - True, geyser is accessible (Probes start gathering
from geyser)
Assimilator is destroyed - False

Once set to False on destruction of assimilator, "isCompleted()" now
remains at false regardless of wheter a new assimilator is built, hence AI
can never mine from this geyser again. 
Note: Removing the iscompleted() check causes the game to crash.

Original issue reported on code.google.com by Kali...@gmail.com on 12 Mar 2010 at 6:57

GoogleCodeExporter commented 8 years ago

I’ve made my own solution for the problem:

GENERAL IDEA:
Once refinery is destroyed (*g)->isCompleted() becomes permanently False, AI 
ignores
geyser and will never send workers to it again.

We can get around this by assigning the workers to the refinery instead (not the
geyser), since desiredWorkerCount applies to units, not resources.

It still stands the isCompleted() behaviour for geysers may be incorrect?
And that this is merely a “hacked” solution in BWSAL for something that 
should really
be fixed in BWAPI.

    ORIGINAL CODE SECTION – BWSAL 0.9.7

    set<Unit*> baseGeysers = (*b)->getGeysers();

    //
    for(set<Unit*>::iterator g = baseGeysers.begin(); g != baseGeysers.end(); g++)
    {
      resourceBase[*g] = *b;
      desiredWorkerCount[*g]=0;
      optimalWorkerCount+=3;

      if ((*g)->getType().isRefinery() && (*g)->getPlayer()==Broodwar->self() &&
(*g)->isCompleted())
      {
        for(int w=0;((w < this->WorkersPerGas) && (remainingWorkers > 0));w++)
        {
          desiredWorkerCount[*g]++;
          remainingWorkers--;
        }
      }
    }

    NEW CODE

    set<Unit*> baseGeysers = (*b)->getGeysers();

    BWAPI::Unit* geyserRefinery = NULL; //Local variable added
    BWAPI::TilePosition geyserlocation; //Local variable added

    //cycle through geysers
    for(set<Unit*>::iterator g = baseGeysers.begin(); g != baseGeysers.end(); g++)
    {
      resourceBase[*g] = *b;
      //REMOVED: desiredWorkerCount[*g]=0;
      optimalWorkerCount+=3;

      geyserlocation = (*g)->getInitialTilePosition();//get tile location for this geyser

      //check for refinery on geyser
      std::set<BWAPI::Unit*> unitsOnGeyser =
BWAPI::Broodwar->unitsOnTile(geyserlocation.x(),geyserlocation.y());

      //cycle through units on geyser
      for(std::set<BWAPI::Unit*>::iterator u = unitsOnGeyser.begin(); u !=
unitsOnGeyser.end(); u++)
      {

        if ((*u)->getType().isRefinery())//if unit is a refinery
        {
          geyserRefinery=(*u);
          desiredWorkerCount[geyserRefinery]=0;
          break;
        }
      }

      //IF geyser has a refinery AND geyser owned by self AND refinery completed
      if (geyserRefinery!=NULL && (*g)->getPlayer()==Broodwar->self() &&
(geyserRefinery)->isCompleted())
      {
        for(int w=0;w < this->WorkersPerGas && remainingWorkers > 0;w++)
        {
          desiredWorkerCount[geyserRefinery]++;//assign workers to refinery, not geyser
          remainingWorkers--;
        }
      }
    }
  }

NOTES: 
- Workers are freed from destroyed refinerys by the 
“desiredWorkerCount.clear();” at
start of rebalanceWorkers().
- “geyserRefinery!=NULL” check means “geyserRefinery->isCompleted()” 
will never get
called when refinery is NULL. (prevents program crash)

Original comment by Kali...@gmail.com on 13 Mar 2010 at 8:51

GoogleCodeExporter commented 8 years ago
also when you destroy an enemy refinery it can still be found in 
SelectAllEnemy()

Original comment by JoshHil...@gmail.com on 21 Sep 2010 at 11:07