// // @(#)TurnState.java 4/2002 // // Copyright 2002 Zachary DelProposto. All rights reserved. // Use is subject to license terms. // // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // Or from http://www.gnu.org/ // package dip.world; import java.io.Serializable; import java.io.ObjectOutputStream; import java.io.IOException; import java.util.Map; import java.util.Map.Entry; import java.util.HashMap; import java.util.List; import java.util.Set; import java.util.LinkedList; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import javax.persistence.Basic; import javax.persistence.ElementCollection; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Lob; import javax.persistence.MapKeyColumn; import javax.persistence.Transient; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; import org.hibernate.annotations.Sort; import org.hibernate.annotations.SortType; import dip.order.Order; import dip.order.Orderable; import dip.order.result.OrderResult; /** * * A TurnState represents a snapshot of the game for the given Phase. * The essential components of a TurnState are, then: * <ul> * <li>A Phase object (represents the TurnState in time) * <li>A Position object (stores the current unit and powers state) * <li>Orders for the units * <li>Order Results (if the TurnState has been resolved) * </ul> * <p> * Note that we store Map (Province) adjacency data seperately from * the Map (it's in the World object), so Map objects are re-constituted * from a list of Provinces and Powers. This occurs behind-the-scenes when * a World (or TurnState) object is deserialized. * <p> * This object is NOT SYNCHRONIZED and therefore not inherently threadsafe. * <p> * Also note that when a List of orders is obtained for a power, we do not * check that the list contains only orders for that power. (e.g., are * non-power orders 'snuck in' for a given power) * */ @Entity @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) public class TurnState implements Serializable { /** * */ private static final long serialVersionUID = -507830632257884049L; @Id @GeneratedValue(strategy=GenerationType.AUTO) private int id; // instance variables (we serialize all of this) @Lob private Phase phase = null; @ElementCollection @Lob private List<Serializable> resultList = null; // order results, post-adjudication @ElementCollection @MapKeyColumn(columnDefinition="VARCHAR(255)") @Lob private Map<Power, ArrayList<?>> orderMap = null; // Map of power=>orders private boolean isSCOwnerChanged = false; // 'true' if any supply centers changed ownership @Lob private Position position = null; // Position data (majority of game state) @Transient private transient World world = null; // makes it easier when we just pass a turnstate private boolean isEnded = false; // true if game over (won, draw, etc.) private boolean isResolved = false; // true if phase has been adjudicated private transient HashMap<Orderable, Boolean> resultMap = null; // transient result map /** Creates a TurnState object. */ protected TurnState() { }// TurnState() /** Creates a TurnState object. */ public TurnState(Phase phase) { if(phase == null) { throw new IllegalArgumentException("null phase"); } this.phase = phase; this.resultList = new ArrayList(80); this.orderMap = new HashMap(29); }// TurnState() /** * Set the World object associated with this TurnState. * A <code>null</code> World is not permitted. */ public void setWorld(World world) { if(world == null) { throw new IllegalArgumentException(); } this.world = world; }// setWorld() /** Gets the World object associated with this TurnState. Never should be null. */ public World getWorld() { return world; }// getWorld() /** Returns the current Phase */ public Phase getPhase() { return phase; }// getTurnInfo() /** This should be used with the utmost care. Null Phases are not allowed. */ public void setPhase(Phase phase) { if(phase == null) { throw new IllegalArgumentException("null phase"); } this.phase = phase; }// setPhase() /** Gets the Position data for this TurnState */ public Position getPosition() { return position; }// getPosition() /** Sets the Position data for this TurnState */ public void setPosition(Position position) { if(position == null) { throw new IllegalArgumentException(); } this.position = position; }// setPosition() /** Returns the result list */ public List<Serializable> getResultList() { return resultList; }// getResultList() /** Sets the Result list, erasing any previously existing result list. */ public void setResultList(List<Serializable> list) { if(list == null) { throw new IllegalArgumentException("null result list"); } resultList = list; }// setResultList() /** * A flag indicating if, after adjudication, any supply centers * have changed ownership. */ public boolean getSCOwnerChanged() { return isSCOwnerChanged; }// getSCOwnerChanged() /** * Sets the flag indicating if, after adjudication, any supply centers * have changed ownership. */ public void setSCOwnerChanged(boolean value) { isSCOwnerChanged = value; }// setSCOwnerChanged() /** * Returns a List of orders for all powers. * <p> * Manipulations to this list will not be reflected in the TurnState object. */ public List getAllOrders() { List list = new ArrayList(75); Iterator esIter = orderMap.entrySet().iterator(); while(esIter.hasNext()) { Map.Entry mapEntry = (Map.Entry) esIter.next(); List orders = (List) mapEntry.getValue(); Iterator ordIter = orders.iterator(); while(ordIter.hasNext()) { list.add( ordIter.next() ); } } return list; }// getOrderList() /** * Clear all Orders, for all Powers. */ public void clearAllOrders() { orderMap.clear(); }// clearAllOrders() /** * Returns the List of orders for a given Power. * <p> * Note that modifications to the returned order List will be reflected * in the TurnState. */ public ArrayList getOrders(Power power) { if(power == null) { throw new IllegalArgumentException("null power"); } ArrayList orderList = (ArrayList) orderMap.get(power); if(orderList == null) { orderList = new ArrayList(15); orderMap.put(power, orderList); } return orderList; }// getOrders() /** Sets the orders for the given Power, deleting any existing orders for the power */ public void setOrders(Power power, ArrayList list) { if(power == null || list == null) { throw new IllegalArgumentException("power or list null"); } orderMap.put(power, list); }// setOrders() /** Set if game has ended for any reason */ public void setEnded(boolean value) { isEnded = value; } /** Returns <code>true</code> if game has ended */ public boolean isEnded() { return isEnded; } /** Set if the turn has been adjudicated. */ public void setResolved(boolean value) { isResolved = value; } /** Returns the turn has been adjudicated */ public boolean isResolved() { return isResolved; } /** * Returns if an order has failed, based on results. Note that * this only applies once the turnstate has been resolved. If * the TurnState is not resolved, this will always return true. */ public boolean isOrderSuccessful(Orderable o) { if(!isResolved) { return true; } if(resultMap == null) { resultMap = new HashMap(53); Iterator iter = getResultList().iterator(); while(iter.hasNext()) { Object obj = iter.next(); if(obj instanceof OrderResult) { OrderResult ordRes = (OrderResult) obj; // we only map SUCCESSFULL orders. if(ordRes.getResultType() == OrderResult.ResultType.SUCCESS) { resultMap.put(ordRes.getOrder(), Boolean.TRUE); } } } } if(resultMap.get(o) == Boolean.TRUE) { return true; } return false; }// isFailedOrder() public int getId() { return id; } public void setId(int id) { this.id = id; } }// class TurnState