Clone wiki

BWTA2 / Getting Started

Getting Started

This is an example of how to use BWTA with the ExampleAIModule of BWAPI.

Download

Download the last version of BWTA. It should contain 3 folders:

  • include: add the content to your include folder of your project
  • lib: add the content to your lib folder of your project
  • windows: move the files in your C:\Windows folder

We also need to create the folder for the cache files of BWTA in your bwapi-data folder.
Usually C:\StarCraft\bwapi-data\BWTA2

Edit ExampleAIModule Project

BWAPI comes with some project examples to start working. We are going to modify the ExampleAIModule project in order to analyze the map using BWTA

Project Properties

We need to edit the project properties in order to add the new libraries.

project_properties.png

Edit ExampleAIModule.h file

We need to include BWTA.h and windows.h (to use threads) and declare a couple of new functions.

#pragma once
#include <BWAPI.h>
#include <BWTA.h>
#include <windows.h>

DWORD WINAPI AnalyzeThread();

class ExampleAIModule : public BWAPI::AIModule
{
public:
  // Virtual functions for callbacks, leave these as they are.
  // ...
  // Everything below this line is safe to modify.
  void drawTerrainData();
};

Edit ExampleAIModule.cpp file

First we need variables to know if the map analysis is completed.

bool analyzed;
bool analysis_just_finished;

At the end of onStart() we will read the map information into BWTA so the terrain analysis can be done in another thread.

void ExampleAIModule::onStart()
{
   // ...
  BWTA::readMap();
  analyzed = false;
  analysis_just_finished = false;
}

At the beginning of onFrame() we will call our function to draw the terrain if the analysis have been completed.

void ExampleAIModule::onFrame()
{
  //...

  // Return if the game is a replay or is paused
  if ( Broodwar->isReplay() || Broodwar->isPaused() || !Broodwar->self() )
    return;

  //BWTA draw
  if (analyzed)
	  drawTerrainData();

  if (analysis_just_finished)
  {
	  Broodwar << "Finished analyzing map." << std::endl;;
	  analysis_just_finished = false;
  }

  // Prevent spamming by only running our onFrame once every number of latency frames.
  // Latency frames are the number of frames before commands are processed.
  if ( Broodwar->getFrameCount() % Broodwar->getLatencyFrames() != 0 )
    return;
  // ...

We modify onSendText() to detect the text "/analyze" and start the analysis of the map.

void ExampleAIModule::onSendText(std::string text)
{
	if (text == "/analyze") {
		if (analyzed == false) {
			Broodwar << "Analyzing map... this may take a minute" << std::endl;;
			CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)AnalyzeThread, NULL, 0, NULL);
		}
	} else {
		// Send the text to the game if it is not being processed.
		Broodwar->sendText("%s", text.c_str());
	}
}

Finally we define the functions to start the analysis and to draw the regions and chokepoints detected from BWTA.

DWORD WINAPI AnalyzeThread()
{
	BWTA::analyze();

	analyzed = true;
	analysis_just_finished = true;
	return 0;
}

void ExampleAIModule::drawTerrainData()
{
	//we will iterate through all the base locations, and draw their outlines.
	for (const auto& baseLocation : BWTA::getBaseLocations()) {
		TilePosition p = baseLocation->getTilePosition();

		//draw outline of center location
		Position leftTop(p.x * TILE_SIZE, p.y * TILE_SIZE);
		Position rightBottom(leftTop.x + 4 * TILE_SIZE, leftTop.y + 3 * TILE_SIZE);
		Broodwar->drawBoxMap(leftTop, rightBottom, Colors::Blue);

		//draw a circle at each mineral patch
		for (const auto& mineral : baseLocation->getStaticMinerals()) {
			Broodwar->drawCircleMap(mineral->getInitialPosition(), 30, Colors::Cyan);
		}

		//draw the outlines of Vespene geysers
		for (const auto& geyser : baseLocation->getGeysers()) {
			TilePosition p1 = geyser->getInitialTilePosition();
			Position leftTop1(p1.x * TILE_SIZE, p1.y * TILE_SIZE);
			Position rightBottom1(leftTop1.x + 4 * TILE_SIZE, leftTop1.y + 2 * TILE_SIZE);
			Broodwar->drawBoxMap(leftTop1, rightBottom1, Colors::Orange);
		}

		//if this is an island expansion, draw a yellow circle around the base location
		if (baseLocation->isIsland()) {
			Broodwar->drawCircleMap(baseLocation->getPosition(), 80, Colors::Yellow);
		}
	}

	//we will iterate through all the regions and ...
	for (const auto& region : BWTA::getRegions()) {
		// draw the polygon outline of it in green
		BWTA::Polygon p = region->getPolygon();
		for (size_t j = 0; j < p.size(); ++j) {
			Position point1 = p[j];
			Position point2 = p[(j + 1) % p.size()];
			Broodwar->drawLineMap(point1, point2, Colors::Green);
		}
		// visualize the chokepoints with red lines
		for (auto const& chokepoint : region->getChokepoints()) {
			Position point1 = chokepoint->getSides().first;
			Position point2 = chokepoint->getSides().second;
			Broodwar->drawLineMap(point1, point2, Colors::Red);
		}
	}
}

Running

Run StarCraft through ChaosLauncher and start a game. Then send the message /analyze and after a while (the first time it can take 2 minutes) we should be able to see the polygons of the decomposed regions and the chokepoints.

Updated