Hallo ich erstelle gerade einen Starcraft-Bot für ein Projekt in meiner Ausbildung.
Die API, die ich benutze heißt BWAPI.
Mein Programm funktioniert so, dass ich ständig durch alle meine Einheiten iteriere.
Gebäude zählen auch als Einheiten.
Wenn ich gerade in dem Loop bei meinen Arbeitern bin (SCV) UND die Differenz zwischen totalSupply und actualSupply kleiner als 2 ist UND ich mehr als 100 Mineralien habe (self.getMinerals() >= 100) UND die Bool-Variable allowedToBuildSupplyDepot auf true gesetzt ist passiert folgendes:
Zuerst einmal setze ich die boolsche allowedToBuildSupplyDepot-Variable auf false, weil ich so verhindere, dass alle meine Arbeiter ein Gebäude bauen wollen.
Die Methode build() ist zuerst einmal ein Laufbefehl und erst wenn der Arbeiter neben der Zielposition des SupplyDepots ist wird gebaut.
Ich baue also das SupplyDepot. Jetzt aktiviert sich die OnUnitCreate-Methode.
Die OnUnitCreate()-Methode wird immer aktiviert wenn Einheiten erzeugt werden da muss aber zwischen Einheiten und Gebäuden unterschieden werden.
Bei Einheiten zählt die Einheit als erzeugt wenn sie aus der Produktionsstätte hinausläuft also der Zeitpunkt der Fertigstellung der Einheit.
Ein Gebäude hingegen zählt als erzeugt, wenn es angefangen wird zu bauen.
Ich habe das auch mit einem System.out.println() verifiziert.
Nun das Problem ist, dass meine Arbeiter nur 1 Depot bauen selbst wenn die Bedingung erfüllt ist und sie eigentlich mehrere Depots bauen müssten.
Für eure Hilfe wäre ich euch sehr dankbar
Hier ist der Code:
LG JavaAddict
Die API, die ich benutze heißt BWAPI.
Mein Programm funktioniert so, dass ich ständig durch alle meine Einheiten iteriere.
Gebäude zählen auch als Einheiten.
Wenn ich gerade in dem Loop bei meinen Arbeitern bin (SCV) UND die Differenz zwischen totalSupply und actualSupply kleiner als 2 ist UND ich mehr als 100 Mineralien habe (self.getMinerals() >= 100) UND die Bool-Variable allowedToBuildSupplyDepot auf true gesetzt ist passiert folgendes:
Zuerst einmal setze ich die boolsche allowedToBuildSupplyDepot-Variable auf false, weil ich so verhindere, dass alle meine Arbeiter ein Gebäude bauen wollen.
Die Methode build() ist zuerst einmal ein Laufbefehl und erst wenn der Arbeiter neben der Zielposition des SupplyDepots ist wird gebaut.
Ich baue also das SupplyDepot. Jetzt aktiviert sich die OnUnitCreate-Methode.
Die OnUnitCreate()-Methode wird immer aktiviert wenn Einheiten erzeugt werden da muss aber zwischen Einheiten und Gebäuden unterschieden werden.
Bei Einheiten zählt die Einheit als erzeugt wenn sie aus der Produktionsstätte hinausläuft also der Zeitpunkt der Fertigstellung der Einheit.
Ein Gebäude hingegen zählt als erzeugt, wenn es angefangen wird zu bauen.
Ich habe das auch mit einem System.out.println() verifiziert.
Nun das Problem ist, dass meine Arbeiter nur 1 Depot bauen selbst wenn die Bedingung erfüllt ist und sie eigentlich mehrere Depots bauen müssten.
Für eure Hilfe wäre ich euch sehr dankbar
Hier ist der Code:
Java:
import bwapi.*;
import bwta.BWTA;
import bwta.BaseLocation;
public class TestBot1 extends DefaultBWListener {
private Mirror mirror = new Mirror();
private Game game;
private Player self;
private int totalSupply = 10;
private int actualSupply = 4;
private boolean allowedToBuildSupplyDepot = true;
private enum typeOfUnit {
scv,
commandCenter,
supplyDepot,
marine,
medic,
vulture,
siegeTank,
siegeTankSieged,
other
}
private typeOfUnit getTypeOfUnit (Unit parUnit)
{
typeOfUnit result = typeOfUnit.other;
if (parUnit.getType() == UnitType.Terran_SCV)
{
result = typeOfUnit.scv;
}
else if (parUnit.getType() == UnitType.Terran_Command_Center)
{
result = typeOfUnit.commandCenter;
}
else if (parUnit.getType() == UnitType.Terran_Supply_Depot)
{
result = typeOfUnit.supplyDepot;
}
else if (parUnit.getType() == UnitType.Terran_Marine)
{
result = typeOfUnit.marine;
}
else if (parUnit.getType() == UnitType.Terran_Medic)
{
result = typeOfUnit.medic;
}
else if (parUnit.getType() == UnitType.Terran_Vulture)
{
result = typeOfUnit.vulture;
}
else if (parUnit.getType() == UnitType.Terran_Siege_Tank_Tank_Mode)
{
result = typeOfUnit.siegeTank;
}
else if (parUnit.getType() == UnitType.Terran_Siege_Tank_Siege_Mode)
{
result = typeOfUnit.siegeTankSieged;
}
return result;
}
// Returns a suitable TilePosition to build a given building type near
// specified TilePosition aroundTile, or null if not found. (builder parameter is our worker)
public TilePosition getBuildTile(Unit builder, UnitType buildingType, TilePosition aroundTile) {
TilePosition ret = null;
int maxDist = 3;
int stopDist = 40;
// Refinery, Assimilator, Extractor
if (buildingType.isRefinery()) {
for (Unit n : game.neutral().getUnits()) {
if ((n.getType() == UnitType.Resource_Vespene_Geyser) &&
( Math.abs(n.getTilePosition().getX() - aroundTile.getX()) < stopDist ) &&
( Math.abs(n.getTilePosition().getY() - aroundTile.getY()) < stopDist )
) return n.getTilePosition();
}
}
while ((maxDist < stopDist) && (ret == null)) {
for (int i=aroundTile.getX()-maxDist; i<=aroundTile.getX()+maxDist; i++) {
for (int j=aroundTile.getY()-maxDist; j<=aroundTile.getY()+maxDist; j++) {
if (game.canBuildHere(new TilePosition(i,j), buildingType, builder, false)) {
// units that are blocking the tile
boolean unitsInWay = false;
for (Unit u : game.getAllUnits()) {
if (u.getID() == builder.getID()) continue;
if ((Math.abs(u.getTilePosition().getX()-i) < 4) && (Math.abs(u.getTilePosition().getY()-j) < 4)) unitsInWay = true;
}
if (!unitsInWay) {
return new TilePosition(i, j);
}
// creep for Zerg
if (buildingType.requiresCreep()) {
boolean creepMissing = false;
for (int k=i; k<=i+buildingType.tileWidth(); k++) {
for (int l=j; l<=j+buildingType.tileHeight(); l++) {
if (!game.hasCreep(k, l)) creepMissing = true;
break;
}
}
if (creepMissing) continue;
}
}
}
}
maxDist += 2;
}
if (ret == null) game.printf("Unable to find suitable build position for "+buildingType.toString());
return ret;
}
public void run() {
mirror.getModule().setEventListener(this);
mirror.startGame();
}
@Override
public void onUnitCreate(Unit unit) {
if (unit.getType() == UnitType.Terran_Supply_Depot) {
System.out.println("Supply Depot wird gebaut...");
allowedToBuildSupplyDepot = true;
}
}
@Override
public void onUnitComplete(Unit unit) {
if (unit.getType() == UnitType.Terran_Supply_Depot) {
System.out.println("Supply Depot wurde gebaut...");
totalSupply += 8;
}
}
@Override
public void onStart() {
game = mirror.getGame();
self = game.self();
//Use BWTA to analyze map
//This may take a few minutes if the map is processed first time!
System.out.println("Analyzing map...");
BWTA.readMap();
BWTA.analyze();
System.out.println("Map data ready");
int i = 0;
for(BaseLocation baseLocation : BWTA.getBaseLocations()){
System.out.println("Base location #" + (++i) + ". Printing location's region polygon:");
for(Position position : baseLocation.getRegion().getPolygon().getPoints()){
System.out.print(position + ", ");
}
System.out.println();
}
}
@Override
public void onFrame() {
//game.setTextSize(10);
game.drawTextScreen(10, 10, "Playing as " + self.getName() + " - " + self.getRace());
//StringBuilder units = new StringBuilder("My units:\n");
//iterate through my units
for (Unit myUnit : self.getUnits()) {
//units.append(myUnit.getType()).append(" ").append(myUnit.getTilePosition()).append("\n");
switch (getTypeOfUnit(myUnit)) {
case scv:
if ((totalSupply - actualSupply) < 2 && (self.minerals() >= 100) && allowedToBuildSupplyDepot) {
//Boolean allowedToBuild set on false so that not 10 SCV try to build SupplyDepot
allowedToBuildSupplyDepot = false;
//get a nice place to build a supply depot
TilePosition buildTile =
getBuildTile(myUnit, UnitType.Terran_Supply_Depot, self.getStartLocation());
//and, if found, send the worker to build it (and leave others alone - break;)
if (buildTile != null) {
myUnit.build(UnitType.Terran_Supply_Depot, buildTile);
break;
}
}
//if it's a worker and it's idle, send it to the closest mineral patch
else if (myUnit.isIdle()) {
Unit closestMineral = null;
//find the closest mineral
for (Unit neutralUnit : game.neutral().getUnits()) {
if (neutralUnit.getType().isMineralField()) {
if (closestMineral == null || myUnit.getDistance(neutralUnit) < myUnit.getDistance(closestMineral)) {
closestMineral = neutralUnit;
}
}
}
//if a mineral patch was found, send the worker to gather it
if (closestMineral != null) {
myUnit.gather(closestMineral, false);
}
}
break;
case commandCenter:
//if there's enough minerals, train an SCV
if (self.minerals() >= 50 && (totalSupply - actualSupply) >1) {
myUnit.train(UnitType.Terran_SCV);
actualSupply++;
}
break;
case supplyDepot:
{}
break;
case marine:
{}
break;
case medic:
{}
break;
case vulture:
{}
break;
case siegeTank:
{}
break;
case siegeTankSieged:
{}
break;
case other:
{}
break;
}
}
//draw my units on screen
//game.drawTextScreen(10, 25, units.toString());
}
public static void main(String[] args) {
new TestBot1().run();
}
}
LG JavaAddict