kyle.game.besiege.location.Location.java Source code

Java tutorial

Introduction

Here is the source code for kyle.game.besiege.location.Location.java

Source

/*******************************************************************************
 * Besiege
 * by Kyle Dhillon
 * Source Code available under a read-only license. Do not copy, modify, or distribute.
 ******************************************************************************/
package kyle.game.besiege.location;

import kyle.game.besiege.Assets;
import kyle.game.besiege.Destination;
import kyle.game.besiege.Faction;
import kyle.game.besiege.Kingdom;
import kyle.game.besiege.Point;
import kyle.game.besiege.Siege;
import kyle.game.besiege.army.Army;
import kyle.game.besiege.army.Farmer;
import kyle.game.besiege.army.Patrol;
import kyle.game.besiege.battle.Battle;
import kyle.game.besiege.panels.BottomPanel;
import kyle.game.besiege.party.Party;
import kyle.game.besiege.party.PartyType;
import kyle.game.besiege.party.Soldier;
import kyle.game.besiege.party.Weapon;
import kyle.game.besiege.voronoi.Center;
import kyle.game.besiege.voronoi.Corner;

import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.utils.Array;

public class Location extends Actor implements Destination {
    private final float SCALE = .06f;
    private final int offset = 30;
    private final int HIRE_REFRESH = 120; // seconds it takes for soldiers to refresh in city
    // TODO ^ change this to a variable. later make city wealth affect quality of soldiers.
    private final int CLOSE_LOC_DISTANCE = 1000; // distance away locations are considered "close"

    protected int DAILY_WEALTH_INCREASE_BASE;
    protected double DAILY_POP_INCREASE_BASE;
    protected int POP_MIN;
    protected int POP_MAX;

    private TextureRegion region;

    public enum LocationType {
        CITY, CASTLE, VILLAGE
    };

    public LocationType type;

    //   protected Array<Location> closestFriendlyLocations;
    //   protected Array<Location> closestEnemyLocations;
    private Array<Patrol> patrols;

    protected Array<City> closestFriendlyCities;
    protected Array<Castle> closestFriendlyCastles;
    protected Array<Village> closestFriendlyVillages;

    public Array<City> closestEnemyCities;
    public Array<Castle> closestEnemyCastles;
    public Array<Village> closestEnemyVillages;

    private boolean mouseOver;

    private Kingdom kingdom;
    private String name;
    private int index;
    private Faction faction;

    protected double population;

    private double wealthFactor = 1;

    private Array<Army> garrisonedArmies;
    protected Party toHire;
    protected Party nextHire; // prevents player from loading and quitting to get ideal choice of hire
    public Army garrison;

    private float timeSinceFreshHire;

    public Siege siege;

    private float spawnX; // where should units spawn? must be inside
    private float spawnY;

    private boolean autoManage;
    public boolean playerIn; //is player garrisoned inside (special menu)
    public boolean hostilePlayerTouched;
    public boolean playerWaiting; // is player waiting inside?
    public boolean playerBesieging;

    public Point spawnPoint; // point where armies and farmers should spawn if on water
    public Center center; // one of these will be null
    public Corner corner;

    public Location(Kingdom kingdom, String name, int index, Faction faction, float posX, float posY,
            Party garrison) {
        this.kingdom = kingdom;
        this.name = name;
        this.index = index;
        this.faction = faction;

        setPosition(posX, posY);

        setTextureRegion("Castle"); // default location textureRegion

        garrisonedArmies = new Array<Army>();
        this.garrison = new Army(getKingdom(), this.getName() + " Garrison", getFaction(), getCenterX(),
                getCenterY(), null);
        this.garrison.setParty(garrison);
        //      this.garrison(this.garrison);

        autoManage = true;
        playerIn = false;
        hostilePlayerTouched = false;

        patrols = new Array<Patrol>();

        //      closestFriendlyLocations = new Array<Location>();
        //      closestEnemyLocations = new Array<Location>();

        closestEnemyCities = new Array<City>();
        closestEnemyCastles = new Array<Castle>();
        closestEnemyVillages = new Array<Village>();

        closestFriendlyCities = new Array<City>();
        closestFriendlyCastles = new Array<Castle>();
        closestFriendlyVillages = new Array<Village>();

        timeSinceFreshHire = 0;
        nextHire = new Party(); //empty
        updateToHire();
        updateToHire();

        this.setRotation(0);
        this.setScale(1);
        initializeBox();
    }

    public void initializeBox() {
        this.setWidth(region.getRegionWidth() * SCALE);
        this.setHeight(region.getRegionHeight() * SCALE);
        this.setOrigin(region.getRegionWidth() * SCALE / 2, region.getRegionHeight() * SCALE / 2);
    }

    public void setCorner(Corner corner) {
        this.corner = corner;
    }

    public void setCenter(Center center) {
        this.center = center;
    }

    /** Initialize containers for armies created at this site 
     * @param army Army to be created */
    public void setContainerForArmy(Army army) {
        if (this.center != null) {
            army.containing = center;
            center.armies.add(army);
        } else if (corner != null) {
            //         assert(army != null);
            //         assert(army.containing != null);
            //         assert(corner.touches != null);
            //         assert(corner.touches.get(0) != null);
            //         assert(false);
            if (corner == null)
                System.out.println("containing is null!");
            army.containing = corner.touches.get(0);
            corner.touches.get(0).armies.add(army);
        } else
            System.out.println("no corner or center!");
    }

    @Override
    public void act(float delta) {
        if (autoManage) {
            autoManage();
        }
        if (timeSinceFreshHire >= HIRE_REFRESH) {
            timeSinceFreshHire = 0;
            updateToHire();
        } else
            timeSinceFreshHire += delta;

        if (!kingdom.isPaused()) {
            hostilePlayerTouched = false; // only can be selected when game is paused;
        }
        //      if (underSiege()) {
        //         if (playerBesieging) {
        //            if (!siege.armies.contains(kingdom.getPlayer(), true)) {
        //               playerBesieging = false;
        //               kingdom.getMapScreen().getSidePanel().setDefault();
        //            }
        //         }
        //         if (!playerBesieging) {
        //            if (siege.armies.contains(kingdom.getPlayer(), true))
        //               playerBesieging = true;
        //         }
        //      }

        super.act(delta);
    }

    public void autoManage() {
        //contains actions in extensions
    }

    @Override
    public void draw(SpriteBatch batch, float parentAlpha) {
        setRotation(kingdom.getMapScreen().rotation);
        batch.draw(region, getX(), getY(), getOriginX(), getOriginY(), getWidth(), getHeight(), getScaleX(),
                getScaleY(), getRotation());
    }

    public void drawCrest(SpriteBatch batch) {
        float size_factor = 1.4f;

        if ((this.type == LocationType.VILLAGE))
            size_factor = .5f * size_factor;
        if ((this.type == LocationType.CASTLE))
            size_factor = .7f * size_factor;

        Color temp = batch.getColor();
        float zoom = getKingdom().getMapScreen().getCamera().zoom;
        zoom *= size_factor;

        // TODO do some vector calculations to make this rotate   
        // TODO create a bunch more fonts for smoother scrolling!
        // TODO do this in Kingdom at the end of everything
        // don't draw village names at a certain point.
        if (!(this.type == LocationType.VILLAGE && zoom > 1.5) && !(this.type == LocationType.CASTLE && zoom > 3)) {
            BitmapFont font;

            if (zoom > 7) {
                font = Assets.pixel150;
                zoom = 7;
            } else if (zoom > 5) {
                font = Assets.pixel100;
                zoom = 5;
            } else if (zoom > 4) {
                font = Assets.pixel80;
                zoom = 4;
            } else if (zoom > 3) {
                font = Assets.pixel64;
                zoom = 3;
            }
            // add some fonts here for smoothness
            else if (zoom > 2.5) {
                font = Assets.pixel50;
                zoom = 2.5f;
            } else if (zoom > 2) {
                font = Assets.pixel40;
                zoom = 2f;
            } else if (zoom > 1.5) {
                font = Assets.pixel30;
                zoom = 1.5f;
            } else if (zoom > 1.2) {
                font = Assets.pixel24;
                zoom = 1.2f;
            } else if (zoom > 1) {
                font = Assets.pixel20;
                zoom = 1f;
            } else if (zoom > .75) {
                font = Assets.pixel15;
                zoom = .75f;
            } else {
                font = Assets.pixel12;
                zoom = .6f;
            }

            // draw crest
            Color clear_white = new Color();
            clear_white.b = 1;
            clear_white.r = 1;
            clear_white.g = 1;
            clear_white.a = .6f;
            batch.setColor(clear_white);
            batch.draw(this.getFaction().crest, getCenterX() - 14 * zoom, getCenterY() + 5 + 5 * zoom, 30 * zoom,
                    45 * zoom);
            batch.setColor(temp);

            //         // draw text
            //         font.setColor(clear_white);
            //         String toDraw = getName();
            //         font.draw(batch, toDraw, getX() - (int) (4.3*toDraw.length())*zoom, getY()-5-5*zoom);
        }
    }

    public void drawText(SpriteBatch batch) {
        float size_factor = 1.4f;

        if ((this.type == LocationType.VILLAGE))
            size_factor = .5f * size_factor;
        if ((this.type == LocationType.CASTLE))
            size_factor = .7f * size_factor;

        Color temp = batch.getColor();
        float zoom = getKingdom().getMapScreen().getCamera().zoom;
        zoom *= size_factor;

        // TODO do some vector calculations to make this rotate   
        // TODO create a bunch more fonts for smoother scrolling!
        // TODO do this in Kingdom at the end of everything
        // don't draw village names at a certain point.
        if (!(this.type == LocationType.VILLAGE && zoom > 1.5) && !(this.type == LocationType.CASTLE && zoom > 3)) {
            BitmapFont font;

            if (zoom > 7) {
                font = Assets.pixel150;
                zoom = 7;
            } else if (zoom > 5) {
                font = Assets.pixel100;
                zoom = 5;
            } else if (zoom > 4) {
                font = Assets.pixel80;
                zoom = 4;
            } else if (zoom > 3) {
                font = Assets.pixel64;
                zoom = 3;
            }
            // add some fonts here for smoothness
            else if (zoom > 2.5) {
                font = Assets.pixel50;
                zoom = 2.5f;
            } else if (zoom > 2) {
                font = Assets.pixel40;
                zoom = 2f;
            } else if (zoom > 1.5) {
                font = Assets.pixel30;
                zoom = 1.5f;
            } else if (zoom > 1.2) {
                font = Assets.pixel24;
                zoom = 1.2f;
            } else if (zoom > 1) {
                font = Assets.pixel20;
                zoom = 1f;
            } else if (zoom > .75) {
                font = Assets.pixel15;
                zoom = .75f;
            } else {
                font = Assets.pixel12;
                zoom = .6f;
            }
            String toDraw = getName();

            Matrix4 mx4Font = new Matrix4();
            mx4Font.trn((getX() - (int) (4.3 * toDraw.length()) * zoom), (getY() - 5 - 5 * zoom), 0);
            mx4Font.setToRotation(new Vector3(0, 0, 1), getKingdom().getMapScreen().getRotation());
            Matrix4 tempMatrix = batch.getTransformMatrix();
            batch.setTransformMatrix(mx4Font);

            //         // draw crest
            Color clear_white = new Color();
            clear_white.b = 1;
            clear_white.r = 1;
            clear_white.g = 1;
            clear_white.a = .8f;
            //         batch.setColor(clear_white);
            //         batch.draw(this.getFaction().crest, getCenterX() - 14*zoom, getCenterY() + 13, 30*zoom, 45*zoom);
            //         batch.setColor(temp);

            // draw text
            font.setColor(clear_white);
            font.draw(batch, toDraw, getX() - (int) (4.3 * toDraw.length()) * zoom, getY() - 5 - 5 * zoom);

            batch.setTransformMatrix(tempMatrix);
        }
    }

    //   public void drawInfo(SpriteBatch batch, float parentAlpha) {
    //      Kingdom.arial.setColor(Kingdom.factionColors.get(getFaction()));
    //      Kingdom.arial.draw(batch, getName() + " (" + garrison.wealth + ")", getX(), getY());   
    //      
    //      float offset = 0;
    //      for (Army army : getGarrisoned()) {
    //         offset -= getOffset()*getKingdom().getZoom();
    //         Kingdom.arial.draw(batch, army.getName() + ": " + army.getTroopCount(), getX(), getY() + offset);
    //      }   
    //   }

    /** initializes closeLocation arrays with close locations
     */
    public void findCloseLocations() {
        closestEnemyCities.clear();
        closestEnemyCastles.clear();
        closestEnemyVillages.clear();

        for (City that : getKingdom().getCities()) {
            if (that != this && Kingdom.distBetween(this, that) < CLOSE_LOC_DISTANCE) {
                if (!Faction.isAtWar(getFaction(), that.getFaction()))
                    closestFriendlyCities.add(that);
                else
                    closestEnemyCities.add(that);
            }
        }
        for (Castle castle : getKingdom().castles) {
            if (castle != this && Kingdom.distBetween(this, castle) < CLOSE_LOC_DISTANCE) {
                if (!Faction.isAtWar(getFaction(), castle.getFaction()))
                    closestFriendlyCastles.add(castle);
                else
                    closestEnemyCastles.add(castle);
            }
        }
        // when is village faction info initialized?
        //      for (Village village : getKingdom().villages) {
        //         if (village != this && Kingdom.distBetween(this, village) < CLOSE_LOC_DISTANCE) {
        //            if (!Faction.isAtWar(getFaction(), village.getFaction()))
        //               closestFriendlyVillages.add(village);
        //            else closestEnemyVillages.add(village);
        //         }
        //      }
    }

    /** Update closeLocation arrays (doesn't look for new cities)
     * 
     */
    public void updateCloseLocations() {
        Array<City> newCloseEnemyCities = new Array<City>();
        Array<City> newCloseFriendlyCities = new Array<City>();

        // cities
        for (City c : closestEnemyCities) {
            if (Faction.isAtWar(this.getFaction(), c.getFaction())) {
                if (!newCloseEnemyCities.contains(c, true))
                    newCloseEnemyCities.add(c);
            } else if (!newCloseFriendlyCities.contains(c, true))
                newCloseFriendlyCities.add(c);
        }
        for (City c : closestFriendlyCities) {
            if (Faction.isAtWar(this.getFaction(), c.getFaction())) {
                if (!newCloseEnemyCities.contains(c, true))
                    newCloseEnemyCities.add(c);
            } else if (!newCloseFriendlyCities.contains(c, true))
                newCloseFriendlyCities.add(c);
        }
        closestEnemyCities = new Array<City>(newCloseEnemyCities);
        closestFriendlyCities = new Array<City>(newCloseFriendlyCities);

        Array<Castle> newCloseEnemyCastles = new Array<Castle>();
        Array<Castle> newCloseFriendlyCastles = new Array<Castle>();

        // castles
        for (Castle c : closestEnemyCastles) {
            if (Faction.isAtWar(this.getFaction(), c.getFaction())) {
                if (!newCloseEnemyCastles.contains(c, true))
                    newCloseEnemyCastles.add(c);
            } else if (!newCloseFriendlyCastles.contains(c, true))
                newCloseFriendlyCastles.add(c);
        }
        for (Castle c : closestFriendlyCastles) {
            if (Faction.isAtWar(this.getFaction(), c.getFaction())) {
                if (!newCloseEnemyCastles.contains(c, true))
                    newCloseEnemyCastles.add(c);
            } else if (!newCloseFriendlyCastles.contains(c, true))
                newCloseFriendlyCastles.add(c);
        }
        closestEnemyCastles = new Array<Castle>(newCloseEnemyCastles);
        closestFriendlyCastles = new Array<Castle>(newCloseFriendlyCastles);

        Array<Village> newCloseEnemyVillages = new Array<Village>();
        Array<Village> newCloseFriendlyVillages = new Array<Village>();

        // villages
        for (Village v : closestEnemyVillages) {
            if (Faction.isAtWar(this.getFaction(), v.getFaction())) {
                if (!newCloseEnemyVillages.contains(v, true))
                    newCloseEnemyVillages.add(v);
            } else if (!newCloseFriendlyVillages.contains(v, true))
                newCloseFriendlyVillages.add(v);
        }
        for (Village v : closestFriendlyVillages) {
            if (Faction.isAtWar(this.getFaction(), v.getFaction())) {
                if (!newCloseEnemyVillages.contains(v, true))
                    newCloseEnemyVillages.add(v);
            } else if (!newCloseFriendlyVillages.contains(v, true))
                newCloseFriendlyVillages.add(v);
        }
        closestEnemyVillages = new Array<Village>(newCloseEnemyVillages);
        closestFriendlyVillages = new Array<Village>(newCloseFriendlyVillages);
    }

    public Location getCloseEnemyCity() {
        return closestEnemyCities.random();
    }

    public Location getCloseEnemyCastles() {
        return closestEnemyCastles.random();
    }

    public Location getCloseEnemyVillage() {
        return closestEnemyVillages.random();
    }

    public Array<Patrol> getPatrols() {
        return patrols;
    }

    public void removePatrol(Patrol patrol) {
        patrols.removeValue(patrol, true);
    }

    public void dailyWealthIncrease() {
        this.addWealth((int) (DAILY_WEALTH_INCREASE_BASE * wealthFactor));
    }

    public void dailyPopIncrease() {
        this.population += (DAILY_POP_INCREASE_BASE);
        if (this.population > POP_MAX)
            this.population = POP_MAX;
    }

    public void siegeAttack(Array<Army> attackers, Location location) {
        //      Army garrisonArmy = new Army(getKingdom(), this.getName() + " Garrison", getFaction(), getCenterX(), getCenterY(), null);
        //      garrisonArmy.setParty(garrison);
        //      if (this.location. == null) {
        //         System.out.println("FUCK no besieging");
        //         return;
        //      }

        attackers.first().createBattleWith(garrison);
        Battle b = garrison.getBattle();
        b.siegeOf = location;
        b.setPosition(this.getX() - b.getWidth() / 2, this.getY() - b.getHeight() / 2);
        b.dAdvantage = this.getDefenseFactor();
        for (Army a : attackers) {
            if (a.getParty().player)
                ;
            // bring up option to attack, pause/stay etc
            if (a != attackers.first()) {
                a.joinBattle(b);
            }
        }
        for (Army a : garrisonedArmies) {
            //         System.out.println("adding " + a.getName() + " to siege battle");
            a.joinBattle(b);
        }
    }

    public void beginSiege(Army army) {
        siege = new Siege(this, army.getFaction());
        siege.add(army);
        kingdom.addActor(siege);
    }

    public void endSiege() {
        kingdom.removeActor(siege);
        siege = null;
    }

    public boolean underSiege() {
        return siege != null;
    }

    public Siege getSiege() {
        return siege;
    }

    public void updateToHire() {
        //      if (this.toHire.size == 0) toHire.add(new Soldier(Weapon.PITCHFORK, null));
        // contained in extensions
    }

    public void garrison(Soldier soldier) {
        garrison.getParty().addSoldier(soldier);
    }

    public void garrison(Army army) {
        if (army.shouldRepair()) {
            repair(army);
        }
        garrisonedArmies.add(army);
        army.setVisible(false);
        army.setPosition(this.getCenterX() - army.getOriginX(), getCenterY() - army.getOriginY());
        kingdom.removeArmy(army);
    }

    public void eject(Army army) {
        garrisonedArmies.removeValue(army, true);
        army.setGarrisonedIn(null);
        army.setVisible(true);
        kingdom.addArmy(army);
        if (army == getKingdom().getPlayer()) {
            if (playerWaiting)
                stopWait();
        }
    }

    public void repair(Army army) {
        PartyType pt = army.getPartyType();
        army.getParty().repair(pt);
    }

    public void startWait() {
        //      System.out.println("location.startWait()");
        playerWaiting = true;
        getKingdom().getPlayer().setWaiting(true);
        getKingdom().getMapScreen().shouldFastForward = true;
        getKingdom().getMapScreen().shouldLetRun = true;
        getKingdom().setPaused(false);
    }

    public void stopWait() {
        //      System.out.println("location.stopWait()");
        playerWaiting = false;
        getKingdom().getPlayer().setWaiting(false);
        getKingdom().getMapScreen().shouldFastForward = false;
        getKingdom().getMapScreen().shouldLetRun = false;
        getKingdom().setPaused(true);
    }

    public boolean hire(Party party, Soldier s) { // returns true if hired successfully, false if not (not enough money?)
        if (toHire.getHealthy().contains(s, true)) {
            if (party.wealth - Weapon.TIER_COST[s.tier] >= party.minWealth) {
                party.wealth -= Weapon.TIER_COST[s.tier];
                toHire.removeSoldier(s);
                party.addSoldier(s);
                s.party = party;
                return true;
            }
        }
        return false;
    }

    public Party getToHire() {
        return toHire;
    }

    public void setToHire(Party toHire) {
        this.toHire = toHire;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public Faction getFaction() {
        return faction;
    }

    private void setFaction(Faction faction) {
        this.faction = faction;
    }

    public void changeFaction(Faction newFaction) {
        // TODO updateMerchants();
        // TODO update villagers();
        if (this.type == LocationType.CITY) {
            this.faction.cities.removeValue((City) this, true);
            newFaction.cities.add((City) this);

            this.faction.allocateNoblesFrom((City) this);
            newFaction.allocateNoblesFor((City) this);

            BottomPanel.log(newFaction.name + " has taken " + this.getName() + " from " + this.getFactionName());
        } else if (this.type == LocationType.CASTLE) {
            this.faction.castles.removeValue((Castle) this, true);
            newFaction.castles.add((Castle) this);
            BottomPanel.log(newFaction.name + " has taken " + this.getName() + " from " + this.getFactionName());
        } else if (this.type == LocationType.VILLAGE) {
            for (Farmer f : ((Village) this).farmers) {

            }
        }
        this.faction = newFaction;
        // update friendly arrays, and everything (if this isn't a village)
        if (this.type != LocationType.VILLAGE)
            Faction.updateFactionCityInfo();
    }

    @Override
    public int getType() {
        return 1;
    }

    public int getIndex() {
        return index;
    }

    public Party getParty() {
        return garrison.getParty();
    }

    public void setParty(Party party) {
        this.garrison.setParty(party);
    }

    public double getPop() {
        return population;
    }

    public void addWealth(int wealth) {
        this.getParty().wealth += wealth;
    }

    public void loseWealth(int wealth) {
        this.getParty().wealth -= wealth;
    }

    public double distTo(Location location) {
        return Math.sqrt((this.getCenterY() - location.getCenterY()) * (this.getCenterY() - location.getCenterY())
                + (this.getCenterX() - location.getCenterX()) * (this.getCenterX() - location.getCenterX()));
    }

    public double distTo(double x, double y) {
        return Math.sqrt((this.getCenterY() - y) * (this.getCenterY() - y)
                + (this.getCenterX() - x) * (this.getCenterX() - x));
    }

    //   public int getWealth() {
    //      return wealth;
    //   }
    //   public void setWealth(int wealth) {
    //      this.wealth = wealth;
    //   }
    //   @Override
    //   public double distToCenter(Destination d) {
    //      return Math.sqrt((d.getX()-getCenterX())*(d.getX()-getCenterX())+(d.getY()-getCenterY())*(d.getY()-getCenterY()));
    //   }
    //   @Override
    //   public double distTo(Destination d) {
    //      return Math.sqrt((d.getX()-getX())*(d.getX()-getX())+(d.getY()-getY())*(d.getY()-getY()));
    //   }

    @Override
    public void setMouseOver(boolean mouseOver) {
        if (this.mouseOver) {
            if (!mouseOver) {
                kingdom.getMapScreen().getSidePanel().returnToPrevious();
                this.mouseOver = false;
            }
        } else if (mouseOver) {
            if (!this.mouseOver) {
                System.out.println("MASODFHASIDj");
                kingdom.getMapScreen().getSidePanel().setActiveLocation(this);
                this.mouseOver = true;
            }
        }
    }

    public float getCenterX() {
        return this.getX() + this.getOriginX();
    }

    public float getCenterY() {
        return this.getY() + this.getOriginY();
    }

    public Kingdom getKingdom() {
        return kingdom;
    }

    public void setTextureRegion(String textureRegion) {
        region = Assets.atlas.findRegion(textureRegion);
    }

    public Array<Army> getGarrisoned() {
        return garrisonedArmies;
    }

    public Array<Army> getGarrisonedAndGarrison() {
        Array<Army> garrisoned = new Array<Army>(getGarrisoned());
        //      Army garrisonArmy = new Army(getKingdom(), "Garrison", getFaction(), getCenterX(), getCenterY(), null);
        //      garrisonArmy.setParty(garrison);
        garrisoned.add(garrison);
        return garrisoned;
    }

    public int getOffset() {
        return offset;
    }

    public boolean isVillage() {
        return this.type == LocationType.VILLAGE;
    }

    public boolean isCastle() {
        return this.type == LocationType.CASTLE;
    }

    public String getFactionName() {
        return faction.name;
    }

    public String getTypeStr() {
        if (this.isVillage())
            return "Village";
        else if (this.isCastle())
            return "Castle";
        else
            return "City";
    }

    public float getDefenseFactor() {
        return 1.5f; //TODO
    }
}