Package jnibwapi

Source Code of jnibwapi.JNIBWAPI

package jnibwapi;

import java.awt.Point;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

import jnibwapi.model.Map;
import jnibwapi.model.Player;
import jnibwapi.model.Region;
import jnibwapi.model.Unit;
import jnibwapi.model.Bullet;
import jnibwapi.types.*;

/**
* JNI interface for the Brood War API.<br>
*
* This focus of this interface is to provide the callback and game state query functionality in
* BWAPI. Utility functions such as can buildHere have not yet been implemented.<br>
*
* Note: for thread safety and game state sanity, all native calls should be invoked from the
* callback methods.<br>
*
* For BWAPI documentation see: {@link http://code.google.com/p/bwapi/}<br>
*
* API Pages<br>
* Game: {@link http://code.google.com/p/bwapi/wiki/Game}<br>
* Unit: {@link http://code.google.com/p/bwapi/wiki/Unit}<br>
*/
public class JNIBWAPI {

  // load the BWAPI client library
  static {
    try {
      System.loadLibrary("client-bridge-" + System.getProperty("os.arch"));
      System.out.println("Loaded client bridge library.");
    } catch (UnsatisfiedLinkError e) {
      System.err.println("Native code library failed to load.\n" + e);
    }
  }

  /** callback listener for BWAPI events */
  private BWAPIEventListener listener;

  // game state
  private int gameFrame = 0;
  private Map map;
  private HashMap<Integer, Unit> units = new HashMap<Integer, Unit>();
  private HashMap<Integer, Bullet> bullets = new HashMap<Integer, Bullet>();
  private ArrayList<Unit> playerUnits = new ArrayList<Unit>();
  private ArrayList<Unit> alliedUnits = new ArrayList<Unit>();
  private ArrayList<Unit> enemyUnits = new ArrayList<Unit>();
  private ArrayList<Unit> neutralUnits = new ArrayList<Unit>();

  // player lists
  private Player self;
  private Player neutralPlayer;
  private HashSet<Integer> allyIDs = new HashSet<Integer>();
  private HashSet<Integer> enemyIDs = new HashSet<Integer>();
  private HashMap<Integer, Player> players = new HashMap<Integer, Player>();
  private ArrayList<Player> allies = new ArrayList<Player>();
  private ArrayList<Player> enemies = new ArrayList<Player>();

  // invokes the main native method
  private native void startClient(JNIBWAPI jniBWAPI);

  // query methods
  private native int getFrame();
  public native int getReplayFrameTotal();
  private native int[] getPlayersData();
  private native int[] getPlayerUpdate(int playerID);
  /** Returns string as a byte[] to properly handle ASCII-extended characters */
  private native byte[] getPlayerName(int playerID);
  private native int[] getResearchStatus(int playerID);
  private native int[] getUpgradeStatus(int playerID);
  private native int[] getAllUnitsData();
  private native int[] getAllBulletsData();
  private native int[] getRaceTypes();
  private native String getRaceTypeName(int typeID);
  private native int[] getUnitTypes();
  private native String getUnitTypeName(int typeID);
  private native int[] getTechTypes();
  private native String getTechTypeName(int techID);
  private native int[] getUpgradeTypes();
  private native String getUpgradeTypeName(int upgradeID);
  private native int[] getWeaponTypes();
  private native String getWeaponTypeName(int weaponID);
  private native int[] getUnitSizeTypes();
  private native String getUnitSizeTypeName(int sizeID);
  private native int[] getBulletTypes();
  private native String getBulletTypeName(int bulletID);
  private native int[] getDamageTypes();
  private native String getDamageTypeName(int damageID);
  private native int[] getExplosionTypes();
  private native String getExplosionTypeName(int explosionID);
  private native int[] getUnitCommandTypes();
  private native String getUnitCommandTypeName(int unitCommandID);
  private native int[] getOrderTypes();
  private native String getOrderTypeName(int unitCommandID);
  private native int[] getUnitIdsOnTile(int tx, int ty);

  // map data
  private native void analyzeTerrain();
  private native int getMapWidth();
  private native int getMapHeight();
  /** Returns string as a byte[] to properly handle ASCII-extended characters */
  private native byte[] getMapName();
  private native String getMapFileName();
  private native String getMapHash();
  private native int[] getHeightData();
  /** Returns the regionId for each map tile */
  private native int[] getRegionMap();
  private native int[] getWalkableData();
  private native int[] getBuildableData();
  private native int[] getChokePoints();
  private native int[] getRegions();
  private native int[] getPolygon(int regionID);
  private native int[] getBaseLocations();

  // unit commands: http://code.google.com/p/bwapi/wiki/Unit
  public native boolean attack(int unitID, int x, int y);
  public native boolean attack(int unitID, int targetID);
  public native boolean build(int unitID, int tx, int ty, int typeID);
  public native boolean buildAddon(int unitID, int typeID);
  public native boolean train(int unitID, int typeID);
  public native boolean morph(int unitID, int typeID);
  public native boolean research(int unitID, int techID);
  public native boolean upgrade(int unitID, int updateID);
  public native boolean setRallyPoint(int unitID, int x, int y);
  public native boolean setRallyPoint(int unitID, int targetID);
  public native boolean move(int unitID, int x, int y);
  public native boolean patrol(int unitID, int x, int y);
  public native boolean holdPosition(int unitID);
  public native boolean stop(int unitID);
  public native boolean follow(int unitID, int targetID);
  public native boolean gather(int unitID, int targetID);
  public native boolean returnCargo(int unitID);
  public native boolean repair(int unitID, int targetID);
  public native boolean burrow(int unitID);
  public native boolean unburrow(int unitID);
  public native boolean cloak(int unitID);
  public native boolean decloak(int unitID);
  public native boolean siege(int unitID);
  public native boolean unsiege(int unitID);
  public native boolean lift(int unitID);
  public native boolean land(int unitID, int tx, int ty);
  public native boolean load(int unitID, int targetID);
  public native boolean unload(int unitID, int targetID);
  public native boolean unloadAll(int unitID);
  public native boolean unloadAll(int unitID, int x, int y);
  public native boolean rightClick(int unitID, int x, int y);
  public native boolean rightClick(int unitID, int targetID);
  public native boolean haltConstruction(int unitID);
  public native boolean cancelConstruction(int unitID);
  public native boolean cancelAddon(int unitID);
  public native boolean cancelTrain(int unitID, int slot);
  public native boolean cancelMorph(int unitID);
  public native boolean cancelResearch(int unitID);
  public native boolean cancelUpgrade(int unitID);
  public native boolean useTech(int unitID, int typeID);
  public native boolean useTech(int unitID, int typeID, int x, int y);
  public native boolean useTech(int unitID, int typeID, int targetID);
  public native boolean placeCOP(int unitID, int tx, int ty);

  // utility commands
  public native void drawHealth(boolean enable);
  public native void drawTargets(boolean enable);
  public native void drawIDs(boolean enable);
  public native void enableUserInput();
  public native void enablePerfectInformation();
  public native void setGameSpeed(int speed);
  public native void setFrameSkip(int frameSkip);
  public native void leaveGame();

  // draw commands
  public native void drawBox(int left, int top, int right, int bottom, int color, boolean fill,
      boolean screenCoords);
  public native void drawCircle(int x, int y, int radius, int color, boolean fill,
      boolean screenCoords);
  public native void drawLine(int x1, int y1, int x2, int y2, int color, boolean screenCoords);
  public void drawLine(Point a, Point b, int color, boolean screenCoords) {
    drawLine(a.x, a.y, b.x, b.y, color, screenCoords);
  }
  public native void drawDot(int x, int y, int color, boolean screenCoords);
  public native void drawText(int x, int y, String msg, boolean screenCoords);
  public void drawText(Point a, String msg, boolean screenCoords) {
    drawText(a.x, a.y, msg, screenCoords);
  }

  // Extended Commands
  public native boolean isVisible(int tileX, int tileY);
  public native boolean isExplored(int tileX, int tileY);
  public native boolean isBuildable(int tx, int ty, boolean includeBuildings);
  public boolean isBuildable(int tx, int ty) { return isBuildable(tx, ty, false);}
  public native boolean hasCreep(int tileX, int tileY);
  public native boolean hasPower(int tileX, int tileY);
  public native boolean hasPower(int tileX, int tileY, int unitTypeID);
  public native boolean hasPower(int tileX, int tileY, int tileWidth, int tileHeight);
  public native boolean hasPower(int tileX, int tileY, int tileWidth, int tileHeight, int unitTypeID);
  public native boolean hasPowerPrecise(int x, int y);
  public native boolean hasPath(int fromX, int fromY, int toX, int toY);
  public native boolean hasPath(int unitID, int targetID);
  public native boolean hasPath(int unitID, int toX, int toY);
  public native boolean hasLoadedUnit(int unitID1, int unitID2);
  public native boolean canBuildHere(int tileX, int tileY, int unitTypeID, boolean checkExplored);
  public native boolean canBuildHere(int unitID, int tileX, int tileY, int unitTypeID, boolean checkExplored);
  public native boolean canMake(int unitTypeID);
  public native boolean canMake(int unitID, int unitTypeID);
  public native boolean canResearch(int techTypeID);
  public native boolean canResearch(int unitID, int techTypeID);
  public native boolean canUpgrade(int upgradeTypeID);
  public native boolean canUpgrade(int unitID, int upgradeTypeID);
  public native void printText(String message);
  public native void sendText(String message);
  public native void setCommandOptimizationLevel(int level);
  public native boolean isReplay();
  private native boolean isVisibleToPlayer(int unitID, int playerID);
  public boolean isVisibleToPlayer(Unit u, Player p) {
    return isVisibleToPlayer(u.getID(), p.getID());
  }
  public native int getLastError();
  public native int getRemainingLatencyFrames();

  // type data
  private HashMap<Integer, UnitType> unitTypes = new HashMap<Integer, UnitType>();
  private HashMap<Integer, RaceType> raceTypes = new HashMap<Integer, RaceType>();
  private HashMap<Integer, TechType> techTypes = new HashMap<Integer, TechType>();
  private HashMap<Integer, UpgradeType> upgradeTypes = new HashMap<Integer, UpgradeType>();
  private HashMap<Integer, WeaponType> weaponTypes = new HashMap<Integer, WeaponType>();
  private HashMap<Integer, UnitSizeType> unitSizeTypes = new HashMap<Integer, UnitSizeType>();
  private HashMap<Integer, BulletType> bulletTypes = new HashMap<Integer, BulletType>();
  private HashMap<Integer, DamageType> damageTypes = new HashMap<Integer, DamageType>();
  private HashMap<Integer, ExplosionType> explosionTypes = new HashMap<Integer, ExplosionType>();
  private HashMap<Integer, UnitCommandType> unitCommandTypes = new HashMap<Integer, UnitCommandType>();
  private HashMap<Integer, OrderType> orderTypes = new HashMap<Integer, OrderType>();

  // type data accessors
  public UnitType getUnitType(int typeID) { return unitTypes.get(typeID); }
  public RaceType getRaceType(int typeID) { return raceTypes.get(typeID); }
  public TechType getTechType(int typeID) { return techTypes.get(typeID); }
  public UpgradeType getUpgradeType(int upgradeID) { return upgradeTypes.get(upgradeID); }
  public UnitSizeType getUnitSizeType(int sizeID) { return unitSizeTypes.get(sizeID); }

  public WeaponType getWeaponType(int weaponID) { return weaponTypes.get(weaponID); }
  public BulletType getBulletType(int bulletID) { return bulletTypes.get(bulletID); }
  public DamageType getDamageType(int damageID) { return damageTypes.get(damageID); }
  public ExplosionType getExplosionType(int explosionID) { return explosionTypes.get(explosionID); }
  public UnitCommandType getUnitCommandType(int unitCommandID) { return unitCommandTypes.get(unitCommandID); }
  public OrderType getOrderType(int orderID) { return orderTypes.get(orderID); }

  public Collection<UnitType> unitTypes() { return unitTypes.values(); }
  public Collection<RaceType> raceTypes() { return raceTypes.values(); }
  public Collection<TechType> techTypes() { return techTypes.values(); }
  public Collection<UpgradeType> upgradeTypes() { return upgradeTypes.values(); }
  public Collection<WeaponType> weaponTypes() { return weaponTypes.values(); }
  public Collection<UnitSizeType> unitSizeTypes() { return unitSizeTypes.values(); }
  public Collection<BulletType> bulletTypes() { return bulletTypes.values(); }
  public Collection<DamageType> damageTypes() { return damageTypes.values(); }
  public Collection<ExplosionType> explosionTypes() { return explosionTypes.values(); }
  public Collection<UnitCommandType> unitCommandTypes() { return unitCommandTypes.values(); }
  public Collection<OrderType> orderTypes() { return orderTypes.values(); }

  // game state accessors
  public int getFrameCount() {
    return gameFrame;
  }

  public Player getSelf() {
    return self;
  }

  public Player getNeutralPlayer() {
    return neutralPlayer;
  }

  public Player getPlayer(int playerID) {
    return players.get(playerID);
  }

  public Collection<Player> getPlayers() {
    return Collections.unmodifiableCollection(players.values());
  }

  public List<Player> getAllies() {
    return Collections.unmodifiableList(allies);
  }

  public List<Player> getEnemies() {
    return Collections.unmodifiableList(enemies);
  }

  public Unit getUnit(int unitID) {
    return units.get(unitID);
  }

  public Collection<Unit> getAllUnits() {
    return Collections.unmodifiableCollection(units.values());
  }
 
  public Collection<Bullet> getAllBullets() {
    return Collections.unmodifiableCollection(bullets.values());
  }

  public List<Unit> getMyUnits() {
    return Collections.unmodifiableList(playerUnits);
  }

  public List<Unit> getAlliedUnits() {
    return Collections.unmodifiableList(alliedUnits);
  }

  public List<Unit> getEnemyUnits() {
    return Collections.unmodifiableList(enemyUnits);
  }

  public List<Unit> getNeutralUnits() {
    return Collections.unmodifiableList(neutralUnits);
  }

  public List<Unit> getUnits(Player p) {
    List<Unit> pUnits = new ArrayList<Unit>();
    for (Unit u : units.values()) {
      if (u.getPlayerID() == p.getID()) {
        pUnits.add(u);
      }
    }
    return pUnits;
  }

  public List<Unit> getUnitsOnTile(int tx, int ty) {
    // Often will have 0 or few units on tile
    List<Unit> units = new ArrayList<Unit>(0);
    for (int id : getUnitIdsOnTile(tx, ty)) {
      units.add(getUnit(id));
    }
    return units;
  }

  /**
   * Returns the map.
   *
   * Note: returns null if loadMapData has not been called.
   */
  public Map getMap() {
    return map;
  }

  /**
   * Loads type data from BWAPI.
   */
  public void loadTypeData() {
    // race types
    int[] raceTypeData = getRaceTypes();
    for (int index = 0; index < raceTypeData.length; index += RaceType.numAttributes) {
      RaceType type = new RaceType(raceTypeData, index);
      type.setName(getRaceTypeName(type.getID()));
      raceTypes.put(type.getID(), type);
    }

    // unit types
    int[] unitTypeData = getUnitTypes();
    for (int index = 0; index < unitTypeData.length; index += UnitType.numAttributes) {
      UnitType type = new UnitType(unitTypeData, index);
      type.setName(getUnitTypeName(type.getID()));
      unitTypes.put(type.getID(), type);
    }

    // tech types
    int[] techTypeData = getTechTypes();
    for (int index = 0; index < techTypeData.length; index += TechType.numAttributes) {
      TechType type = new TechType(techTypeData, index);
      type.setName(getTechTypeName(type.getID()));
      techTypes.put(type.getID(), type);
    }

    // upgrade types
    int[] upgradeTypeData = getUpgradeTypes();
    for (int index = 0; index < upgradeTypeData.length; index += UpgradeType.numAttributes) {
      UpgradeType type = new UpgradeType(upgradeTypeData, index);
      type.setName(getUpgradeTypeName(type.getID()));
      upgradeTypes.put(type.getID(), type);
    }

    // weapon types
    int[] weaponTypeData = getWeaponTypes();
    for (int index = 0; index < weaponTypeData.length; index += WeaponType.numAttributes) {
      WeaponType type = new WeaponType(weaponTypeData, index);
      type.setName(getWeaponTypeName(type.getID()));
      weaponTypes.put(type.getID(), type);
    }

    // unit size types
    int[] unitSizeTypeData = getUnitSizeTypes();
    for (int index = 0; index < unitSizeTypeData.length; index += UnitSizeType.numAttributes) {
      UnitSizeType type = new UnitSizeType(unitSizeTypeData, index);
      type.setName(getUnitSizeTypeName(type.getID()));
      unitSizeTypes.put(type.getID(), type);
    }

    // bullet types
    int[] bulletTypeData = getBulletTypes();
    for (int index = 0; index < bulletTypeData.length; index += BulletType.numAttributes) {
      BulletType type = new BulletType(bulletTypeData, index);
      type.setName(getBulletTypeName(type.getID()));
      bulletTypes.put(type.getID(), type);
    }

    // damage types
    int[] damageTypeData = getDamageTypes();
    for (int index = 0; index < damageTypeData.length; index += DamageType.numAttributes) {
      DamageType type = new DamageType(damageTypeData, index);
      type.setName(getDamageTypeName(type.getID()));
      damageTypes.put(type.getID(), type);
    }

    // explosion types
    int[] explosionTypeData = getExplosionTypes();
    for (int index = 0; index < explosionTypeData.length; index += ExplosionType.numAttributes) {
      ExplosionType type = new ExplosionType(explosionTypeData, index);
      type.setName(getExplosionTypeName(type.getID()));
      explosionTypes.put(type.getID(), type);
    }

    // unitCommand types
    int[] unitCommandTypeData = getUnitCommandTypes();
    for (int index = 0; index < unitCommandTypeData.length; index += UnitCommandType.numAttributes) {
      UnitCommandType type = new UnitCommandType(unitCommandTypeData, index);
      type.setName(getUnitCommandTypeName(type.getID()));
      unitCommandTypes.put(type.getID(), type);
    }

    // order types
    int[] orderTypeData = getOrderTypes();
    for (int index = 0; index < orderTypeData.length; index += OrderType.numAttributes) {
      OrderType type = new OrderType(orderTypeData, index);
      type.setName(getOrderTypeName(type.getID()));
      orderTypes.put(type.getID(), type);
    }
  }

  /**
   * Loads map data and BWTA data.
   *
   * TODO: figure out how to use BWTA's internal map storage
   */
  public void loadMapData(boolean enableBWTA) {
    String mapName = new String(getMapName());
    map = new Map(getMapWidth(), getMapHeight(), mapName, getMapFileName(), getMapHash(),
        getHeightData(), getBuildableData(), getWalkableData());
    if (!enableBWTA) {
      return;
    }

    // get region and choke point data
    File bwtaFile = new File(map.getHash() + ".jbwta");
    boolean analyzed = bwtaFile.exists();
    int[] regionMapData = null;
    int[] regionData = null;
    int[] chokePointData = null;
    int[] baseLocationData = null;
    HashMap<Integer, int[]> polygons = new HashMap<Integer, int[]>();

    // run BWTA
    if (!analyzed) {
      analyzeTerrain();
      regionMapData = getRegionMap();
      regionData = getRegions();
      chokePointData = getChokePoints();
      baseLocationData = getBaseLocations();
      for (int index = 0; index < regionData.length; index += Region.numAttributes) {
        int id = regionData[index];
        polygons.put(id, getPolygon(id));
      }

      // store the results to a local file (bwta directory)
      try {
        BufferedWriter writer = new BufferedWriter(new FileWriter(bwtaFile));

        writeMapData(writer, regionMapData);
        writeMapData(writer, regionData);
        writeMapData(writer, chokePointData);
        writeMapData(writer, baseLocationData);
        for (int id : polygons.keySet()) {
          writer.write("" + id + ",");
          writeMapData(writer, polygons.get(id));
        }

        writer.close();
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
    // load from file
    else {
      try {
        BufferedReader reader = new BufferedReader(new FileReader(bwtaFile));

        regionMapData = readMapData(reader);
        regionData = readMapData(reader);
        chokePointData = readMapData(reader);
        baseLocationData = readMapData(reader);
        // polygons (first integer is ID)
        int[] polygonData;
        while ((polygonData = readMapData(reader)) != null) {
          int[] coordinateData = Arrays.copyOfRange(polygonData, 1, polygonData.length);

          polygons.put(polygonData[0], coordinateData);
        }

        reader.close();
      } catch (Exception e) {
        e.printStackTrace();
      }
    }

    map.initialize(regionMapData, regionData, polygons, chokePointData, baseLocationData);
  }

  /** Convenience method to write out each part of BWTA map data to a stream */
  private static void writeMapData(BufferedWriter writer, int[] data) throws IOException {
    boolean first = true;
    for (int val : data) {
      if (first) {
        first = false;
        writer.write("" + val);
      }
      else {
        writer.write("," + val);
      }
    }
    writer.write("\n");
  }

  /**
   * Convenience method to read each part of BWTA map data from a stream
   *
   * @return null when end of stream is reached, otherwise an int array (possibly empty)
   */
  private static int[] readMapData(BufferedReader reader) throws IOException {
    int[] data = new int[0];
    String line = reader.readLine();
    if (line == null)
      return null;
    String[] stringData = line.split(",");
    if (stringData.length > 0 && !stringData[0].equals("")) {
      data = new int[stringData.length];
      for (int i = 0; i < stringData.length; i++) {
        data[i] = Integer.parseInt(stringData[i]);
      }
    }
    return data;
  }

  /**
   * Instantiates a BWAPI instance, but does not connect to the bridge. To connect, the start
   * method must be invoked.
   *
   * @param listener - listener for BWAPI callback events.
   */
  public JNIBWAPI(BWAPIEventListener listener) {
    this.listener = listener;
  }

  /**
   * Invokes the native library which will connect to the bridge and then invoke callback
   * functions.
   *
   * Note: this method never returns, it should be invoked from a separate thread if concurrent
   * java processing is needed.
   */
  public void start() {
    startClient(this);
  }

  /**
   * C++ callback function.
   *
   * Utility function for printing to the java console from C++.
   */
  public void javaPrint(String msg) {
    try {
      System.out.println("Bridge: " + msg);
    } catch (Error e) {
      e.printStackTrace();
    }
  }

  /**
   * C++ callback function.
   *
   * Notifies the event listener that a connection has been formed to the bridge.
   */
  public void connected() {
    try {
      listener.connected();
    } catch (Error e) {
      e.printStackTrace();
    }
  }

  /**
   * C++ callback function.
   *
   * Notifies the event listener that a game has started.
   */
  public void gameStarted() {
    try {
      // get the players
      self = null;
      allies.clear();
      allyIDs.clear();
      enemies.clear();
      enemyIDs.clear();
      players.clear();

      int[] playerData = getPlayersData();
      for (int index = 0; index < playerData.length; index += Player.numAttributes) {
        String name = new String(getPlayerName(playerData[index]));
        Player player = new Player(playerData, index, name);

        players.put(player.getID(), player);

        if (player.isSelf()) {
          self = player;
        }
        else if (player.isAlly()) {
          allies.add(player);
          allyIDs.add(player.getID());
        }
        else if (player.isEnemy()) {
          enemies.add(player);
          enemyIDs.add(player.getID());
        }
        else if (player.isNeutral()) {
          neutralPlayer = player;
        }
      }

      // get unit data
      units.clear();
      playerUnits.clear();
      alliedUnits.clear();
      enemyUnits.clear();
      neutralUnits.clear();
      int[] unitData = getAllUnitsData();

      for (int index = 0; index < unitData.length; index += Unit.numAttributes) {
        int id = unitData[index];
        Unit unit = new Unit(id);
        unit.update(unitData, index);

        units.put(id, unit);
        if (self != null && unit.getPlayerID() == self.getID()) {
          playerUnits.add(unit);
        }
        else if (allyIDs.contains(unit.getPlayerID())) {
          alliedUnits.add(unit);
        }
        else if (enemyIDs.contains(unit.getPlayerID())) {
          enemyUnits.add(unit);
        }
        else {
          neutralUnits.add(unit);
        }
      }

      listener.gameStarted();
    } catch (Error e) {
      e.printStackTrace();
    }
  }

  /**
   * C++ callback function.
   *
   * Notifies the event listener that a game update occurred.
   */
  private void gameUpdate() {
    try {
      // update game state
      gameFrame = getFrame();
      if (!isReplay()) {
        self.update(getPlayerUpdate(self.getID()));
        self.updateResearch(getResearchStatus(self.getID()), getUpgradeStatus(self.getID()));
      } else {
        for (Integer playerID : players.keySet()) {
          players.get(playerID).update(getPlayerUpdate(playerID));
          players.get(playerID).updateResearch(getResearchStatus(playerID),
              getUpgradeStatus(playerID));
        }
      }
      // update units
      int[] unitData = getAllUnitsData();
      int[] bulletData = getAllBulletsData();
      HashSet<Integer> deadUnits = new HashSet<Integer>(units.keySet());
      ArrayList<Unit> playerList = new ArrayList<Unit>();
      ArrayList<Unit> alliedList = new ArrayList<Unit>();
      ArrayList<Unit> enemyList = new ArrayList<Unit>();
      ArrayList<Unit> neutralList = new ArrayList<Unit>();
     
      for (int index = 0; index < bulletData.length; index += Bullet.numAttributes) {
        int id = bulletData[index];
        Bullet bullet = bullets.get(id);
        if (bullet == null) {
          bullet = new Bullet(id);
          bullets.put(id, bullet);
        }
        bullet.update(bulletData, index);
      }

      for (int index = 0; index < unitData.length; index += Unit.numAttributes) {
        int id = unitData[index];

        // bugfix - unit list was emptying itself every second frame
        deadUnits.remove(id);

        Unit unit = units.get(id);
        if (unit == null) {
          unit = new Unit(id);
          units.put(id, unit);
        }

        unit.update(unitData, index);

        if (self != null)
        {
          if (unit.getPlayerID() == self.getID()) {
            playerList.add(unit);
          }
          else if (allyIDs.contains(unit.getPlayerID())) {
            alliedList.add(unit);
          }
          else if (enemyIDs.contains(unit.getPlayerID())) {
            enemyList.add(unit);
          }
          else {
            neutralList.add(unit);
          }
        }
        else if (allyIDs.contains(unit.getPlayerID())) {
          alliedList.add(unit);
        }
        else if (enemyIDs.contains(unit.getPlayerID())) {
          enemyList.add(unit);
        }
        else {
          neutralList.add(unit);
        }
      }

      // update the unit lists
      playerUnits = playerList;
      alliedUnits = alliedList;
      enemyUnits = enemyList;
      neutralUnits = neutralList;
      for (Integer unitID : deadUnits) {
        units.get(unitID).setDestroyed();
        units.remove(unitID);
      }

      listener.gameUpdate();
    } catch (Error e) {
      e.printStackTrace();
    }
  }

  /**
   * C++ callback function.
   *
   * Notifies the event listener that the game has terminated.
   *
   * Note: this is always called after matchEnded(bool), and is meant as a way of notifying the AI
   * client to clear up state.
   */
  private void gameEnded() {
    try {
      listener.gameEnded();
    } catch (Error e) {
      e.printStackTrace();
    }
  }

  /**
   * C++ callback function.
   *
   * Sends BWAPI callback events to the event listener.
   *
   * @param type - event type (should probably be an enum)
   */
  private void eventOccurred(int type, int param1, int param2, String param3) {
    try {
      switch (type) {
        case 0:
          listener.matchEnded(param1 == 1);
          break;
        case 1:
          listener.sendText(param3);
          break;
        case 2:
          listener.receiveText(param3);
          break;
        case 3:
          listener.playerLeft(param1);
          break;
        case 4:
          listener.nukeDetect(param2, param2);
          break;
        case 5:
          listener.nukeDetect();
          break;
        case 6:
          listener.unitDiscover(param1);
          break;
        case 7:
          listener.unitEvade(param1);
          break;
        case 8:
          listener.unitShow(param1);
          break;
        case 9:
          listener.unitHide(param1);
          break;
        case 10:
          listener.unitCreate(param1);
          break;
        case 11:
          listener.unitDestroy(param1);
          break;
        case 12:
          listener.unitMorph(param1);
          break;
        case 13:
          listener.unitRenegade(param1);
          break;
        case 14:
          listener.saveGame(param3);
          break;
        case 15:
          listener.unitComplete(param1);
          break;
        case 16:
          listener.playerDropped(param1);
          break;
      }
    } catch (Error e) {
      e.printStackTrace();
    }
  }

  /**
   * C++ callback function.
   *
   * Notifies the event listener that a key was pressed.
   */
  public void keyPressed(int keyCode) {
    try {
      listener.keyPressed(keyCode);
    } catch (Error e) {
      e.printStackTrace();
    }
  }
}
TOP

Related Classes of jnibwapi.JNIBWAPI

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.