#include "NovaStdAfx.h"
#include "BuildManager.h"

using namespace BWAPI;

#define BLOCKED 0
#define BUILDABLE 1
#define TURRETS_PER_BASE 2
#define WALL_KITE_AREA 2

BuildManager::BuildManager()
	:_workerBuildingRefinery(0)
{
	//Init build map
	mapW = Broodwar->mapWidth();
	mapH = Broodwar->mapHeight();

	buildMap = new int*[mapW];
	for(int x = 0 ; x < mapW ; ++x) {
		buildMap[x] = new int[mapH];

		//Fill from static map and Buildings
		for (int y = 0; y < mapH; ++y) {
			int ok = BUILDABLE;
			if (!Broodwar->isBuildable(x, y)) {
				ok = BLOCKED;
			}

			buildMap[x][y] = ok;
		}
	}

	//Block minerals locations
	for(UnitSet::iterator m = Broodwar->getMinerals().begin(); m != Broodwar->getMinerals().end(); ++m) {
		MyRectangle mineral = getBuildRectangle((*m)->getTilePosition(), (*m)->getType());
		mapArea(mineral, BLOCKED, 2);
	}

	//Block gas locations
	for(UnitSet::iterator g = Broodwar->getGeysers().begin(); g != Broodwar->getGeysers().end(); ++g) {
		MyRectangle gas = getBuildRectangle((*g)->getTilePosition(), (*g)->getType());
		mapArea(gas, BLOCKED, 2);
	}
};

void BuildManager::reserveBaseLocations()
{
	// Our bases
	for(std::map<BWTA::BaseLocation*, BWAPI::TilePosition>::const_iterator i=informationManager->_ourBases.begin();i!=informationManager->_ourBases.end();++i) {
		MyRectangle base = getBuildRectangle(i->first->getTilePosition(), UnitTypes::Terran_Command_Center);
		mapArea(base, BLOCKED);
	}

	// Empty bases
	for(std::set<BWTA::BaseLocation*>::const_iterator i=informationManager->_emptyBases.begin();i!=informationManager->_emptyBases.end();++i) {
		MyRectangle base = getBuildRectangle((*i)->getTilePosition(), UnitTypes::Terran_Command_Center);
		mapArea(base, BLOCKED);
	}

	// Ignore bases
	for(std::set<TilePosition>::const_iterator i=informationManager->_ignoreBases.begin();i!=informationManager->_ignoreBases.end();++i) {
		MyRectangle base = getBuildRectangle((*i), UnitTypes::Terran_Command_Center);
		mapArea(base, BLOCKED);
	}

	// Enemy bases
	for(std::set<BWTA::BaseLocation*>::const_iterator i=informationManager->_enemyBases.begin();i!=informationManager->_enemyBases.end();++i) {
		MyRectangle base = getBuildRectangle((*i)->getTilePosition(), UnitTypes::Terran_Command_Center);
		mapArea(base, BLOCKED);
	}
}

BuildManager::~BuildManager() 
{
	for(int i = 0 ; i < mapW ; i++) {
		delete[] buildMap[i];
	}
	delete[] buildMap;
}

MyRectangle BuildManager::getBuildRectangle(TilePosition position, UnitType type)
{
	MyRectangle area;
	area.x1 = position.x();
	area.y1 = position.y();
	area.x2 = position.x() + type.tileWidth() - 1;
	area.y2 = position.y() + type.tileHeight() - 1;

	//make sure we leave space for add-ons
	if (type==BWAPI::UnitTypes::Terran_Command_Center ||
		type==BWAPI::UnitTypes::Terran_Factory || 
		type==BWAPI::UnitTypes::Terran_Starport ||
		type==BWAPI::UnitTypes::Terran_Science_Facility)
	{
		area.x2+=2;
	}

	//leave more space for production buildings
	if (type==BWAPI::UnitTypes::Terran_Command_Center ||
		type==BWAPI::UnitTypes::Terran_Factory || 
		type==BWAPI::UnitTypes::Terran_Barracks)
	{
		area.x1--;
		area.y2++;
	}

	return area;
}

void BuildManager::mapArea(MyRectangle c, int label, int expand) {
	for (int x = c.x1-expand; x <= c.x2+expand; x++) {
		for (int y = c.y1-expand; y <= c.y2+expand; y++) {
			if (x >= 0 && x < mapW && y >= 0 && y < mapH) {
				buildMap[x][y] = label;
			}
		}
	}
}

void BuildManager::onFrame()
{
	// Debug info
	if (PRINT_BUILD_MAP) drawBuildMap();
	if (PRINT_BUILD_ORDER) drawBuildOrder();

	//Debug info
// 	Broodwar->drawTextScreen(290,39,"Workers building: %d", workerManager->_workerBuildOrder.size() );
// 	for(WorkerToBuildOrderMap::const_iterator workerMap=workerManager->_workerBuildOrder.begin();workerMap!=workerManager->_workerBuildOrder.end();++workerMap) {
// 		Position q = workerMap->first->getPosition();
// 		Broodwar->drawCircle(CoordinateType::Map,q.x(),q.y(),30,Colors::Yellow,false);
// 	}
	// Check if we have buildings under construction list and any building worker
	if (!_toConstruct.empty() && workerManager->_workerBuildOrder.empty()) {
		for (std::vector<UnitType>::iterator it = _toConstruct.begin(); it != _toConstruct.end(); ++it) {
			_buildOrder.insert(_buildOrder.begin(), *it);
			informationManager->removeReservedMinerals((*it).mineralPrice());
			informationManager->removeReservedGas((*it).gasPrice());
		}
		_toConstruct.clear();
	}

	// Process build requests
	while ( !informationManager->_buildRequest.empty() ) {
		UnitType buildType = informationManager->_buildRequest.at(0);
		_buildOrder.push_back(buildType);
		informationManager->_buildRequest.erase(informationManager->_buildRequest.begin()); //pop
	}

	// Process Supply Depots
	if (needSupply()) {
		_buildOrder.insert(_buildOrder.begin(), UnitTypes::Terran_Supply_Depot);
	}

	// Process critical build requests
	while ( !informationManager->_criticalBuildRequest.empty() ) {
		UnitType buildType = informationManager->_criticalBuildRequest.at(0);
		if ( !alreadyBuilding(buildType) )
			_buildOrder.insert(_buildOrder.begin(), buildType);
		else { // look if there is on buildOrder list and put it first
			UnitTypeVector::iterator found = std::find(_buildOrder.begin(), _buildOrder.end(), buildType);
			if(found != _buildOrder.end()) {
				_buildOrder.erase(found);
				_buildOrder.insert(_buildOrder.begin(), buildType);
			}
		}

		informationManager->_criticalBuildRequest.erase(informationManager->_criticalBuildRequest.begin()); //pop
	}

	// Try to execute first in order list
	if ( _buildOrder.size() > 0  && workerManager->_workerUnits.size() > 8) {
		UnitType buildType = _buildOrder.at(0);
		if (buildType.isAddon()) {
			informationManager->addonRequest(buildType);
			_buildOrder.erase(_buildOrder.begin());
		} else if ( canBuild(buildType) ) {
			if ( !executeBuildOrder(buildType) && _buildOrder.size() > 1) {
				//to prevent build order block, check if we can execute second order
				UnitType buildType2 = _buildOrder.at(1);
				int moneyNeeded = buildType.mineralPrice() + buildType2.mineralPrice();
				int gasNeeded = buildType.gasPrice() + buildType2.gasPrice();
				if ( informationManager->minerals() >= moneyNeeded && informationManager->gas() >= gasNeeded) {
					executeBuildOrder(buildType2);
				}
			}
		}
	}

	// Check if we need build turret defenses
	if (informationManager->_turretDefenses) {
		int numTurrets = Broodwar->self()->visibleUnitCount(UnitTypes::Terran_Missile_Turret); //turrets already build
		numTurrets += std::count( _buildOrder.begin(), _buildOrder.end(), UnitTypes::Terran_Missile_Turret ); //turrets on build order list
		int numBases = informationManager->_ourBases.size();
		int ratio = (numBases*TURRETS_PER_BASE) - numTurrets;
		if (ratio > 0) {
			informationManager->criticalBuildRequest(UnitTypes::Terran_Missile_Turret);

			// Check if we are already building the Engineering Bay
			if ( std::find(_toConstruct.begin(), _toConstruct.end(), UnitTypes::Terran_Engineering_Bay) == _toConstruct.end() ) { 
				// remove any previous Engineering Bay on build order
				UnitTypeVector::iterator found = std::find(_buildOrder.begin(), _buildOrder.end(), UnitTypes::Terran_Engineering_Bay);
				if (found != _buildOrder.end()) _buildOrder.erase(found);
				informationManager->criticalBuildRequest(UnitTypes::Terran_Engineering_Bay, true);
			}
		}
	}

}

bool BuildManager::executeBuildOrder(UnitType buildType)
{
	TilePosition seedPosition = Broodwar->self()->getStartLocation();

	// check for proxy seed
	if ( buildOnProxy(buildType) ) {
		seedPosition = TilePosition(informationManager->_proxyPosition);
        //LOG("We had a proxy seed position (" << seedPosition.x() << "," << seedPosition.y() << ")");
	}
	// check for missile turret seed
	if (buildType == UnitTypes::Terran_Missile_Turret) {
		seedPosition = getSeedForTurret();
	}
	// check for Bunker seed
	if (buildType == UnitTypes::Terran_Bunker) {
		seedPosition = TilePosition(informationManager->_initialRallyPosition);
	}

	// find location
	TilePosition locationToBuild = TilePositions::None;
	if (buildType == UnitTypes::Terran_Command_Center) {
		if (informationManager->_expandType == InformationManager::Natural) {
			locationToBuild = informationManager->getNaturalExpandPosition();
		} else {
			locationToBuild = informationManager->getGasExpandPosition();
		}
	} else if (buildType == UnitTypes::Terran_Refinery) {
		locationToBuild = getGeyserTilePosition();
	} else if (buildType.isAddon()) { // get building without addon
		informationManager->addonRequest(buildType);
		_buildOrder.erase(_buildOrder.begin());
	} else {
		locationToBuild = getBuildLocationNear(seedPosition,buildType);
	}
    //LOG("Final building position (" << locationToBuild.x() << "," << locationToBuild.y() << ")");

	// build order
	if (locationToBuild != TilePositions::None) {
		workerManager->buildRequest(locationToBuild, buildType);
		if (!buildType.isAddon()) {
			informationManager->reserveMinerals(buildType.mineralPrice());
			informationManager->reserveGas(buildType.gasPrice());
		}
		UnitTypeVector::iterator found = std::find(_buildOrder.begin(), _buildOrder.end(), buildType);
		if(found != _buildOrder.end())
			_buildOrder.erase(found);
		_toConstruct.push_back(buildType); // add to toConstruct list
		return true;
	} else {
		return false;
	}
}

TilePosition BuildManager::getGeyserTilePosition()
{
	bool enemyRefinery = false;
	for(std::map<BWTA::BaseLocation*, BWAPI::TilePosition>::const_iterator base = informationManager->_ourBases.begin(); base != informationManager->_ourBases.end(); ++base) {
		if ( base->second == TilePositions::None ) continue;
		TilePosition geyserLocation = base->second;
		// check if refinery is already build it
		bool refineryExist = false;
		UnitSet unitsOnGeyser = BWAPI::Broodwar->getUnitsOnTile(geyserLocation.x(), geyserLocation.y());
		for(UnitSet::iterator u = unitsOnGeyser.begin(); u != unitsOnGeyser.end(); ++u) {
			if ((*u)->getType().isRefinery()) {
				refineryExist = true;
				if ((*u)->getPlayer() != BWAPI::Broodwar->self())
					enemyRefinery = true;
			}
		}
		if (!refineryExist)
			return geyserLocation;
	}

	if (!enemyRefinery) { // we don't have any free Geyser, erase build order
		_buildOrder.erase(_buildOrder.begin());
	} else {
		// be sure that we have barracks
		informationManager->criticalBuildRequest(UnitTypes::Terran_Barracks, true);
		// reset supply depot priority
		UnitTypeVector::iterator found = std::find(_buildOrder.begin(), _buildOrder.end(), UnitTypes::Terran_Supply_Depot);
		if(found != _buildOrder.end()) _buildOrder.erase(found);
	}
	return TilePositions::None;	
}

TilePosition BuildManager::getSeedForTurret()
{
	int turrets;
	BWTA::Region* baseRegion;
	TilePosition bestPlace = TilePositions::None;
	for(std::map<BWTA::BaseLocation*, BWAPI::TilePosition>::iterator ourBase=informationManager->_ourBases.begin();ourBase!=informationManager->_ourBases.end();++ourBase) {
		turrets = 0;
		baseRegion = ourBase->first->getRegion();
		for(std::map<BWAPI::Unit*, BWTA::Region*>::iterator turret=informationManager->_missileTurrets.begin();turret!=informationManager->_missileTurrets.end();++turret) {
			if (baseRegion == turret->second) turrets++;
		}
		if (turrets == 0) return ourBase->first->getTilePosition();
		if (turrets < TURRETS_PER_BASE) bestPlace = ourBase->first->getTilePosition();
	}

	if (bestPlace!=TilePositions::None) return bestPlace;
	else return Broodwar->self()->getStartLocation();
}

bool BuildManager::canBuild(UnitType type)
{
	if (!informationManager->haveResources(type))
		return false;

	if (type.isAddon() && Broodwar->self()->completedUnitCount( type.whatBuilds().first ) <= Broodwar->self()->completedUnitCount(type) ) { // do we have the build for the addon?
		return false;
	} else {
		const std::map<UnitType,int> requiredBuildings = type.requiredUnits();
		for(std::map<UnitType,int>::const_iterator build = requiredBuildings.begin(); build != requiredBuildings.end(); ++build) {
			if (Broodwar->self()->completedUnitCount( (*build).first ) == 0)
				return false;
		}
	}

	// check if we send it a proxy worker
// 	if ( buildOnProxy(type) && workerManager->_proxyWorkers.empty()) {
// 			workerManager->assignProxyWorker();
// 	}

	return true;
}

bool BuildManager::needSupply()
{
	// If command center is next in queue
// 	if (_buildOrder.size() > 0) {
// 		if (_buildOrder.at(0).isResourceDepot()) {
// 			return false;
// 		}
// 	}

	if (!informationManager->_autoBuildSuplies) return false;

	// Check if we need supplies
	int supplyTotal = Broodwar->self()->supplyTotal() / 2;
	int supplyUsed = Broodwar->self()->supplyUsed() / 2;
	int maxProduction = Broodwar->self()->visibleUnitCount(UnitTypes::Terran_Command_Center);
	maxProduction += Broodwar->self()->visibleUnitCount(UnitTypes::Terran_Barracks)*2;
	maxProduction += Broodwar->self()->visibleUnitCount(UnitTypes::Terran_Factory)*2;
	maxProduction += Broodwar->self()->visibleUnitCount(UnitTypes::Terran_Starport)*2;
	if (maxProduction < 4) maxProduction = 4;
	if (supplyTotal - supplyUsed > maxProduction) {
		return false;
	}

	if (supplyTotal >= 200) { //Reached max supply
		return false;
	}

	// Check if there is a supply already building
	if ( alreadyBuilding(UnitTypes::Terran_Supply_Depot) ) {
		if (!alreadyRequested(UnitTypes::Terran_Supply_Depot) && Broodwar->self()->incompleteUnitCount(UnitTypes::Terran_Supply_Depot)==1) {
			return true;
		} else {
			return false;
		}
	}

	return true;
}

bool BuildManager::buildOnProxy(UnitType type)
{
	return ( informationManager->_useProxyPosition && TilePosition(informationManager->_proxyPosition) != TilePositions::None && 
		(type == UnitTypes::Terran_Barracks || type == UnitTypes::Terran_Factory));
}

bool BuildManager::alreadyBuilding(UnitType type)
{
	// Check if there is in the build order list
	if ( alreadyRequested(type) ) {
		return true;
	}

	if (Broodwar->self()->incompleteUnitCount(type) > 0)//	if (supplyTotal == supplyUsed) return true;
		return true;

	return false;
}

bool BuildManager::alreadyRequested(UnitType type)
{
	// Check if there is in the build order list
	if ( std::find(_buildOrder.begin(), _buildOrder.end(), type)!= _buildOrder.end() ) {
		return true;
	}

	// Check if we are already building it
	if ( std::find(_toConstruct.begin(), _toConstruct.end(), type)!= _toConstruct.end() ) {
		return true;
	}

	return false;
}

TilePosition BuildManager::getBuildLocationNear(TilePosition position, UnitType type, BWTA::Region* inRegion)
{
	//returns a valid build location near the specified tile position.
	//searches outward in a spiral.
	int x      = position.x();
	int y      = position.y();
	int length = 1;
	int j      = 0;
	bool first = true;
	int dx     = 0;
	int dy     = 1;	
	while (length < Broodwar->mapWidth()) //We'll ride the spiral to the end
	{
		//if we can build here, return this tile position
		if (x >= 0 && x < Broodwar->mapWidth() && y >= 0 && y < Broodwar->mapHeight())
			if (inRegion==0 || inRegion==BWTA::getRegion(TilePosition(x, y)))
				if (canBuildHere(TilePosition(x, y), type))
					return TilePosition(x, y);

		//otherwise, move to another position
		x = x + dx;
		y = y + dy;
		//count how many steps we take in this direction
		j++;
		if (j == length) { //if we've reached the end, its time to turn
			j = 0;	//reset step counter

			//Spiral out. Keep going.
			if (!first)
				length++; //increment step counter if needed

			
			first =! first; //first=true for every other turn so we spiral out at the right rate

			//turn counter clockwise 90 degrees:
			if (dx == 0) {
				dx = dy;
				dy = 0;
			} else {
				dy = -dx;
				dx = 0;
			}
		}
		//Spiral out. Keep going.
	}
	return TilePositions::None;
}

bool BuildManager::canBuildHere(TilePosition buildPosition, UnitType type) {
	if (!Broodwar->canBuildHere(NULL, buildPosition, type))
		return false;

	if (Broodwar->mapHash() == "4e24f217d2fe4dbfa6799bc57f74d8dc939d425b") { // Map Destination
		BWTA::Region* buildRegion = BWTA::getRegion(buildPosition);
		if (BWTA::getRegion(TilePosition(80,5)) == buildRegion ||
			BWTA::getRegion(TilePosition(20,125)) == buildRegion) {
			return false;
		}
	}

	MyRectangle area = getBuildRectangle(buildPosition, type);

	//Check buildMap
	for (int x = area.x1; x <= area.x2; x++) {
		for (int y = area.y1; y <= area.y2; y++) {
			if (x >= 0 && x < mapW && y >= 0 && y < mapH) {
				if (buildMap[x][y] != BUILDABLE) {
					return false; //Cant build here.
				}
			} else {
				return false; //Out of map
			}
		}
	}

	//Check if we have free space surrounding us
	MyRectangle buildArea;
	buildArea.x1 = buildPosition.x() - 1;
	buildArea.y1 = buildPosition.y() - 1;
	buildArea.x2 = buildPosition.x() + type.tileWidth();
	buildArea.y2 = buildPosition.y() + type.tileHeight();
	informationManager->_topLeft = Position(buildArea.x1,buildArea.y1);
	informationManager->_bottomRight = Position(buildArea.x2,buildArea.y2);
	// Check top and bottom
	bool topFree = true;
	for (int y = buildArea.y1; y <= buildArea.y2; y++) {
		if (buildArea.x1 >= 0 && buildArea.x1 < mapW && y >= 0 && y < mapH) {
			//if (!Broodwar->isBuildable(buildArea.x1, y)) {
			if (buildMap[buildArea.x1][y] != BUILDABLE) {
				topFree = false; //Cant build here.
				break;
			}
		} else {
			topFree = false; //Out of map
			break;
		}
	}
	if (!topFree) {
		for (int y = buildArea.y1; y <= buildArea.y2; y++) {
			if (buildArea.x2 >= 0 && buildArea.x2 < mapW && y >= 0 && y < mapH) {
				//if (!Broodwar->isBuildable(buildArea.x2, y)) {
				if (buildMap[buildArea.x2][y] != BUILDABLE) {
					return false; //Cant build here.
				}
			} else {
				return false; //Out of map
			}
		}
	}
	// Check left and right
	bool leftFree = true;
	for (int x = buildArea.x1; x <= buildArea.x2; x++) {
		if (buildArea.y1 >= 0 && buildArea.y1 < mapH && x >= 0 && x < mapW) {
			//if (!Broodwar->isBuildable(x, buildArea.y1)) {
			if (buildMap[x][buildArea.y1] != BUILDABLE) {
				leftFree = false; //Cant build here.
				break;
			}
		} else {
			leftFree = false; //Out of map
			break;
		}
	}
	if (!leftFree) {
		for (int x = buildArea.x1; x <= buildArea.x2; x++) {
			if (buildArea.y2 >= 0 && buildArea.y2 < mapH && x >= 0 && x < mapW) {
				//if (!Broodwar->isBuildable(x, buildArea.y2)) {
				if (buildMap[x][buildArea.y2] != BUILDABLE) {
					return false; //Cant build here.
				}
			} else {
				return false; //Out of map
			}
		}
	}

	//check turret proximity
	if (type == UnitTypes::Terran_Missile_Turret) {
		return anyMissileTurretsNear(buildPosition);
	}

	return true;
}

bool BuildManager::anyMissileTurretsNear(TilePosition buildPosition)
{
	UnitSet units = Broodwar->getUnitsInRadius(Position((buildPosition.x()*TILE_SIZE)+TILE_SIZE, (buildPosition.y()*TILE_SIZE)+TILE_SIZE), 3*TILE_SIZE);
	informationManager->_center = Position((buildPosition.x()*TILE_SIZE)+TILE_SIZE, (buildPosition.y()*TILE_SIZE)+TILE_SIZE);
	informationManager->_radius = 3*TILE_SIZE;
	for (UnitSet::iterator it = units.begin(); it != units.end(); ++it) {
		if ( (*it)->getType() == UnitTypes::Terran_Missile_Turret ) {
			return false;
		}
	}
	return true;
}

void BuildManager::constructionPlaced(Unit* build)
{
	//Block buildMap
	MyRectangle area = getBuildRectangle(build->getTilePosition(), build->getType());
	mapArea(area, BLOCKED);

	//Remove from toConstruct list
	for (std::vector<UnitType>::iterator it = _toConstruct.begin(); it != _toConstruct.end(); ++it) {
		if (it->getID() == build->getType().getID()) {
			_toConstruct.erase(it);
			return;
		}
	}
}

void BuildManager::onBuildingDestroy(BWAPI::Unit* build)
{
	//Free buildMap
	if (build->getType() == UnitTypes::Terran_Refinery || //don't free space form refinery, command center or addons
		build->getType() == UnitTypes::Terran_Comsat_Station ||
		build->getType() == UnitTypes::Terran_Nuclear_Silo ||
		build->getType() == UnitTypes::Terran_Machine_Shop ||
		build->getType() == UnitTypes::Terran_Control_Tower ||
		build->getType() == UnitTypes::Terran_Physics_Lab ||
		build->getType() == UnitTypes::Terran_Covert_Ops ||
		build->getType() == UnitTypes::Terran_Command_Center) 
		return;
	MyRectangle area = getBuildRectangle(build->getTilePosition(), build->getType());
	mapArea(area, BUILDABLE);
}

void BuildManager::refineryPlaced(Unit* build)
{
	constructionPlaced(build);
	workerManager->workerBuildingRefinery();
}

void BuildManager::drawBuildMap()
{
	for(int x=0; x < mapW; ++x) {
		for(int y=0; y < mapH; ++y) {
			if ( buildMap[x][y] == BUILDABLE)
				Broodwar->drawCircleMap(x*TILE_SIZE+16,y*TILE_SIZE+16,3,Colors::Green,true);
			else
				Broodwar->drawCircleMap(x*TILE_SIZE+16,y*TILE_SIZE+16,3,Colors::Red,true);
		}
	}
}

void BuildManager::drawBuildOrder()
{
	int line = 1;
	// Build order list
	Broodwar->drawTextScreen(437,27,"%cBuild Order List", 0x07);
	for (std::vector<UnitType>::iterator it = _toConstruct.begin(); it != _toConstruct.end(); ++it) {
		Broodwar->drawTextScreen(437,27+(10*line),"%c%s", 0x03, (*it).getName().c_str() );
		++line;
	}
	for (std::vector<UnitType>::iterator it = _buildOrder.begin(); it != _buildOrder.end(); ++it) {
		Broodwar->drawTextScreen(437,27+(10*line),"%c%s", 0x11, (*it).getName().c_str() );
		++line;
	}
	for (std::vector<UnitType>::iterator it = informationManager->_buildRequest.begin(); it != informationManager->_buildRequest.end(); ++it) {
		Broodwar->drawTextScreen(437,27+(10*line),"%s", (*it).getName().c_str() );
		++line;
	}

	// Research order list
	if (!informationManager->_researchOrder.empty()) {
		for (BuildingToTechMap::iterator it = informationManager->_researchOrder.begin(); it != informationManager->_researchOrder.end(); ++it) {
			for (std::vector<TechType>::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) {
				Broodwar->drawTextScreen(437,27+(10*line),"%c[Research] %s", 0x11, (*it2).getName().c_str() );
				++line;
			}
		}
	}

	// Upgrade order list
	if (!informationManager->_upgradeOrder.empty()) {
		for (BuildingToUpgradeMap::iterator it = informationManager->_upgradeOrder.begin(); it != informationManager->_upgradeOrder.end(); ++it) {
			for (std::vector<UpgradeType>::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) {
				Broodwar->drawTextScreen(437,27+(10*line),"%c[Upgrade] %s", 0x11, (*it2).getName().c_str() );
				++line;
			}
		}
	}
}

bool BuildManager::wallNear(TilePosition destination)
{
	//Check if we have free space surrounding us
	MyRectangle buildArea;
	buildArea.x1 = destination.x() - WALL_KITE_AREA;
	buildArea.y1 = destination.y() - WALL_KITE_AREA;
	buildArea.x2 = destination.x() + WALL_KITE_AREA;
	buildArea.y2 = destination.y() + WALL_KITE_AREA;
	informationManager->_topLeft = Position(buildArea.x1,buildArea.y1);
	informationManager->_bottomRight = Position(buildArea.x2,buildArea.y2);
	// Check top and bottom
	bool topFree = true;
	for (int y = buildArea.y1; y <= buildArea.y2; y++) {
		if (buildArea.x1 >= 0 && buildArea.x1 < mapW && y >= 0 && y < mapH) {
			//if (!Broodwar->isBuildable(buildArea.x1, y)) {
			if (buildMap[buildArea.x1][y] != BUILDABLE) {
				topFree = false; //Cant build here.
				break;
			}
		} else {
			topFree = false; //Out of map
			break;
		}
	}
	if (!topFree) {
		for (int y = buildArea.y1; y <= buildArea.y2; y++) {
			if (buildArea.x2 >= 0 && buildArea.x2 < mapW && y >= 0 && y < mapH) {
				//if (!Broodwar->isBuildable(buildArea.x2, y)) {
				if (buildMap[buildArea.x2][y] != BUILDABLE) {
					return true; //Cant build here.
				}
			} else {
				return true; //Out of map
			}
		}
	}
	// Check left and right
	bool leftFree = true;
	for (int x = buildArea.x1; x <= buildArea.x2; x++) {
		if (buildArea.y1 >= 0 && buildArea.y1 < mapH && x >= 0 && x < mapW) {
			//if (!Broodwar->isBuildable(x, buildArea.y1)) {
			if (buildMap[x][buildArea.y1] != BUILDABLE) {
				leftFree = false; //Cant build here.
				break;
			}
		} else {
			leftFree = false; //Out of map
			break;
		}
	}
	if (!leftFree) {
		for (int x = buildArea.x1; x <= buildArea.x2; x++) {
			if (buildArea.y2 >= 0 && buildArea.y2 < mapH && x >= 0 && x < mapW) {
				//if (!Broodwar->isBuildable(x, buildArea.y2)) {
				if (buildMap[x][buildArea.y2] != BUILDABLE) {
					return true; //Cant build here.
				}
			} else {
				return true; //Out of map
			}
		}
	}

	return false;
}