/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package rts;
import java.util.*;
import rts.units.Unit;
import rts.units.UnitDefinition;
import rts.units.UnitUpgrade;
/**
* \brief Provides read access to game elements used by AIs
* @author santi
*/
public class GameState {
// these defs should probably be moved into a Map class
public static final int MAP_FOG = 1; /**< (bitmask) the tile has fog of war flag */
public static final int MAP_WALL = 2; /**< (bitmask) the tile has the wall flag */
public static final int MAP_PLAYER = 4; /**< (bitmask) the tile has the current player's unit */
public static final int MAP_NEUTRAL = 8; /**< (bitmask) the tile has the neutral player's unit */
public static final int MAP_NONPLAYER = 16; /**< (bitmask) the tile has a unit that isn't the current or neutral player's */
private PhysicalGameState pgs = null;
private ArrayList<Unit> myUnits; /**< current player's units */
private ArrayList<Unit> otherUnits; /**< other units that the current player sees */
private ArrayList<Unit> neutralUnits; /**< neutral units */
private ArrayList<UnitDefinition> unitList; /**< list of units */
private ArrayList<UnitDefinition> buildingList; /**< list of buildings */
private int[] map; /**< visible map */
public GameState(PhysicalGameState a_pgs) {
pgs = a_pgs;
myUnits = new ArrayList<Unit>();
otherUnits = new ArrayList<Unit>();
neutralUnits = new ArrayList<Unit>();
unitList = new ArrayList<UnitDefinition>();
buildingList = new ArrayList<UnitDefinition>();
map = new int[pgs.width*pgs.height];
for (int i = 0; i < map.length; i++) {
map[i] = 0;
}
}
/**
* Returns the current player's units
* @return
*/
public ArrayList<Unit> getMyUnits() {
return myUnits;
}
/**
* Non-player units
* @return
*/
public ArrayList<Unit> getOtherUnits() {
return otherUnits;
}
/**
* Neutral units
* @return
*/
public ArrayList<Unit> getNeutralUnits() {
return neutralUnits;
}
/**
* Returns the map
* @return
*/
public int[] getMap() {
return map;
}
/**
* Returns the resources for the current player
* @param type
* @return
*/
public int getResources(int type) {
return pgs.getResources(type);
}
/**
* Returns a copy of the list of resources
* @return
*/
public ArrayList<Integer> getResources() {
ArrayList<Integer> r = new ArrayList<Integer>();
for (int i = 0; i < pgs.resources.get(pgs.current_player).size(); i++) {
r.add(pgs.resources.get(pgs.current_player).get(i));
}
return r;
}
/**
* Returns how many resource types there are
* @return
*/
public int getResourceTypes() {
return pgs.resources.size();
}
/**
* Returns the width of the map
* @return
*/
public int getMapWidth() {
return pgs.width;
}
/**
* Returns the height of the map
* @return
*/
public int getMapHeight() {
return pgs.height;
}
/**
* Returns the list of upgrades for units
* @return unit upgrades
*/
public ArrayList<UnitUpgrade> getUnitUpgrades() {
return pgs.unitDefinitions.unit_upgrades.get(pgs.current_player+1);
}
/**
* Returns the list of building upgrades
* @return
*/
public ArrayList<UnitUpgrade> getBuildingUpgrades() {
return pgs.unitDefinitions.building_upgrades.get(pgs.current_player+1);
}
/**
* Returns the list of units that can be built
* @return
*/
public ArrayList<UnitDefinition> getUnitList() {
return unitList;
}
/**
* Retrusn the list of buildings that can be built
* @return
*/
public ArrayList<UnitDefinition> getBuildingList() {
return buildingList;
}
/**
* Whether or not there is fog of war
* @return
*/
public boolean isFog() {
return pgs.fog;
}
/**
* Returns how many different players there are
* @return
*/
public int getPlayers() {
return pgs.armies.size()-1;
}
/**
* Returns the current player's id
* @return
*/
public int getPlayerID() {
return pgs.current_player;
}
/**
* Returns the number of teams
* @return the number of teams
*/
public int numberOfTeams() {
return pgs.teams.size();
}
/**
* Returns the specified team
* @param team the team
* @return the team
*/
public ArrayList<Integer> getTeam(int team) {
ArrayList<Integer> t = new ArrayList<Integer>();
if (team >= 0 && team < pgs.teams.size()) {
t.addAll(pgs.teams.get(team));
}
return t;
}
/**
* Updates the game state for the current player
*/
public void update() {
myUnits.clear();
otherUnits.clear();
neutralUnits.clear();
unitList.clear();
buildingList.clear();
unitList = pgs.unitDefinitions.getCopyOfUnits(pgs.current_player);
buildingList = pgs.unitDefinitions.getCopyOfBuildings(pgs.current_player);
for (int i = 0; i < map.length; i++) {
map[i] = 0;
}
for (int i = 0; i < pgs.armies.get(pgs.current_player).size(); i++) {
Unit u = pgs.armies.get(pgs.current_player).get(i);
if (u.getHP() > 0) {
myUnits.add(u);
map[u.getX()+u.getY()*pgs.width] |= MAP_PLAYER;
}
}
// if we aren't playing with fog, dude can see everything
if (!pgs.fog) {
for (int i = 0; i < pgs.armies.size(); i++) {
if (i != pgs.current_player) {
for (int j = 0; j < pgs.armies.get(i).size(); j++) {
Unit u = pgs.armies.get(i).get(j);
if (i == pgs.numberOfPlayers()) { // neutral player
neutralUnits.add(u.copy());
if (u.getResources() <= 0) {
u.seen_dead();
}
map[u.getX()+u.getY()*pgs.width] |= MAP_NEUTRAL;
} else {
otherUnits.add(u.copy());
if (u.getHP() <= 0) {
u.seen_dead();
} else {
map[u.getX()+u.getY()*pgs.width] |= MAP_NONPLAYER;
}
}
}
}
}
for (int i = 0; i < pgs.terrain.length; i++) {
if (pgs.terrain[i] == PhysicalGameState.TERRAIN_WALL || pgs.unit_map[i] == pgs.reserved) {
map[i] |= MAP_WALL;
}
}
} else { // we can't see everything
int my_team = 0;
for (int i = 0; i < pgs.teams.size(); i++) {
if (pgs.teams.get(i).contains(pgs.current_player)) {
my_team = i;
break;
}
}
for (int i = 0; i < map.length; i++) {
map[i] |= MAP_FOG;
}
// you'd think this could be a lot more efficient
for (int i = 0; i < myUnits.size(); i++) {
Unit u = myUnits.get(i);
for (int j = u.getY()-u.getVision(); j <= u.getY()+u.getVision(); j++) {
if (j >= 0 && j < pgs.height) {
for (int k = u.getX()-u.getVision(); k <= u.getX()+u.getVision(); k++) {
if (k >= 0 && k < pgs.width && k+j*pgs.width >= 0 && k+j*pgs.width < map.length && (j-u.getY())*(j-u.getY())+(k-u.getX())*(k-u.getX()) < u.getVision()*u.getVision()) {
map[k+j*pgs.width] &= ~MAP_FOG;
if (pgs.terrain[k+j*pgs.width] == PhysicalGameState.TERRAIN_WALL || pgs.unit_map[k+j*pgs.width] == pgs.reserved) {
map[k+j*pgs.width] |= MAP_WALL;
}
}
}
}
}
}
for (int i = 0; i < pgs.armies.size(); i++) {
if (i != pgs.current_player) {
for (int j = 0; j < pgs.armies.get(i).size(); j++) {
Unit u = pgs.armies.get(i).get(j);
if ((map[u.getX()+u.getY()*pgs.width]&MAP_FOG) == 0) {
if (i == pgs.numberOfPlayers() || pgs.teams.get(my_team).contains(i)) {
neutralUnits.add(u);
if (u.isResources() && u.getResources() <= 0) {
u.seen_dead();
}
map[u.getX()+u.getY()*pgs.width] |= MAP_NEUTRAL;
} else {
otherUnits.add(u.copy());
if (u.getHP() <= 0) {
u.seen_dead();
} else {
map[u.getX()+u.getY()*pgs.width] |= MAP_NONPLAYER;
}
}
}
}
}
}
}
}
}