View Javadoc

1   /*
2    @See License.txt@
3    */
4   
5   package spellcast.game;
6   
7   import java.beans.PropertyChangeEvent;
8   import java.io.Serializable;
9   import java.util.ArrayList;
10  import java.util.List;
11  
12  import org.apache.commons.chain.Catalog;
13  import org.apache.commons.chain.Command;
14  import org.apache.commons.chain.Context;
15  import org.apache.commons.lang.StringUtils;
16  import org.apache.commons.lang.Validate;
17  import org.apache.log4j.Logger;
18  
19  import spellcast.beings.IBeing;
20  import spellcast.beings.IMonster;
21  import spellcast.beings.IWizard;
22  import spellcast.model.Id;
23  
24  /***
25   * The Game class is the model for the Spellcast game. No control logic is
26   * contained in this class.
27   *
28   * @author Barrie Treloar
29   */
30  public class Game implements Serializable, IGame {
31      /***
32       * Default Listener List Size.
33       */
34      private static final int DEFAULT_LISTENER_LIST_SIZE = 2;
35  
36      /***
37       * Default Monster List Size.
38       */
39      private static final int DEFAULT_MONSTER_LIST_SIZE = 5;
40  
41      /***
42       * Default Wizard List Size.
43       */
44      private static final int DEFAULT_WIZARD_LIST_SIZE = 10;
45  
46      /***
47       * Logger for this class.
48       */
49      private static Logger logger = Logger.getLogger(Game.class);
50  
51      /***
52       * serialVersionUID for Serializable.
53       */
54      private static final long serialVersionUID = 1L;
55  
56      /***
57       * Contains the commands needed by the <code>Game</code>.
58       */
59      private Catalog commandCatalog;
60  
61      /***
62       * Create a game.
63       * @param theGameName
64       *            the name of the game.
65       * @param theCommandCatalog contains the commands needed by the <code>Game</code>.
66       */
67      public Game(final String theGameName, Catalog theCommandCatalog) {
68          Validate.isTrue(StringUtils.isNotEmpty(theGameName));
69          Validate.notNull(theCommandCatalog);
70          gameName = theGameName;
71          commandCatalog = theCommandCatalog;
72          turn = Turn.BEFORE_GAME;
73      }
74  
75      /***
76       * {@inheritDoc}
77       */
78      public final void addWizard(final IWizard w) {
79          if (hasStarted()) {
80              throw new IllegalStateException("Can not add a Wizard as the Game has started.");
81          }
82          wizards.add(w);
83      }
84  
85      /***
86       * Find the specified being by Id. If no match found then return null.
87       * Checks amongst all Wizards and Monsters.
88       *
89       * @param idToMatch
90       *            the Id to match
91       * @return the matching <code>IBeing</code> or null if no match found.
92       */
93      private IBeing getBeing(final Id idToMatch) {
94          IBeing result = null;
95  
96          result = getWizard(idToMatch);
97          if (result == null) {
98              result = getMonster(idToMatch);
99          }
100 
101         return result;
102     }
103 
104     /***
105      * {@inheritDoc}
106      */
107     public final GameLog getGameLog() {
108         return gameLog;
109     }
110 
111     /***
112      * Find the specified monster by Id. If no match found then return null.
113      *
114      * @param idToMatch
115      *            the Id to match
116      * @return the matchin <code>IMonster</code> or null if no match found.
117      */
118     private IMonster getMonster(final Id idToMatch) {
119         for (IMonster potentialMatchingMonster : monsters) {
120             if (potentialMatchingMonster.getId().equals(idToMatch)) {
121                 return potentialMatchingMonster;
122             }
123         }
124         return null;
125     }
126 
127     /***
128      * {@inheritDoc}
129      */
130     public final List<IMonster> getMonsters() {
131         return new ArrayList<IMonster>(monsters);
132     }
133 
134     /***
135      * {@inheritDoc}
136      */
137     public final String getName() {
138         return gameName;
139     }
140 
141     /***
142      * {@inheritDoc}
143      */
144     public final Turn getTurn() {
145         return turn;
146     }
147 
148     /***
149      * Find the specified wizard by Id. If no match found then return null.
150      *
151      * @param idToMatch
152      *            the <code>Id</code> to match
153      * @return the wizard with the matching <code>Id</code> or null otherwise.
154      */
155     public final IWizard getWizard(final Id idToMatch) {
156         for (IWizard potentialMatchingWizard : wizards) {
157             if (potentialMatchingWizard.getId().equals(idToMatch)) {
158                 return potentialMatchingWizard;
159             }
160         }
161         return null;
162     }
163 
164     /***
165      * {@inheritDoc}
166      */
167     public final List<IWizard> getWizards() {
168         return new ArrayList<IWizard>(wizards);
169     }
170 
171     /***
172      * {@inheritDoc}
173      */
174     public final boolean hasFinished() {
175         return (turn.equals(Turn.AFTER_GAME));
176     }
177 
178     /***
179      * {@inheritDoc}
180      */
181     public final boolean hasStarted() {
182         return (!turn.equals(Turn.BEFORE_GAME));
183     }
184 
185     /***
186      * {@inheritDoc}
187      */
188     public void processTurn() {
189         Command processTurnCommand = commandCatalog.getCommand("processTurn");
190         try {
191             Context theContext = new GameContext();
192             processTurnCommand.execute(theContext);
193         } catch (Exception e) {
194             logger.warn("Unexpected exception", e);
195         }
196     }
197 
198     /***
199      * {@inheritDoc}
200      */
201     public final void removeWizard(final IWizard w) {
202         if (hasStarted()) {
203             throw new IllegalStateException("Can not remove a Wizard as the Game has started.");
204         }
205         wizards.remove(w);
206     }
207 
208     /***
209      * Set the value of gameLog.
210      *
211      * @param v
212      *            Value to assign to gameLog.
213      */
214     public final void setGameLog(final GameLog v) {
215         gameLog = v;
216     }
217 
218     /***
219      * {@inheritDoc}
220      */
221     public final void setTurn(final Turn v) {
222         turn = v;
223     }
224 
225     /***
226      * Update the client's local copy of the game with the value contained in
227      * the property change event.
228      *
229      * @param pce
230      *            needs more work here.
231      */
232     public final void update(final PropertyChangeEvent pce) {
233         IBeing target = getBeing((Id) pce.getSource());
234         if (target != null) {
235             // TODO: Replace usage of
236             // target.update(pce);
237             // with reflection.
238             int todo = 0;
239         } else {
240             logger.error("Received update for unknown object: "
241                     + pce.getSource() + "\n" + "Property ("
242                     + pce.getPropertyName() + ") = " + pce.getNewValue());
243 
244         }
245     }
246 
247     /***
248      * The <code>GameLog</code> for this game.
249      */
250     private transient GameLog gameLog;
251 
252     /***
253      * The name of the game.
254      */
255     private String gameName;
256 
257     /***
258      * The property listeners, probably to be removed.
259      */
260     private transient ArrayList listeners = new ArrayList(
261             DEFAULT_LISTENER_LIST_SIZE);
262 
263     /***
264      * List of the <code>IMonster</code>s in the game.
265      */
266     private List<IMonster> monsters = new ArrayList<IMonster>(
267             DEFAULT_MONSTER_LIST_SIZE);
268 
269     /***
270      * The current <code>Turn</code>.
271      */
272     private Turn turn;
273 
274     /***
275      * List of the <code>IWizard</code>s in the game.
276      */
277     private ArrayList<IWizard> wizards = new ArrayList<IWizard>(
278             DEFAULT_WIZARD_LIST_SIZE);
279 
280 }