001 /**
002 *
003 */
004 package jagafa.view.newui;
005
006 import jagafa.JassRound;
007 import jagafa.flags.AIFlags;
008 import jagafa.flags.TestingFlags;
009 import jagafa.object.Player;
010 import jagafa.rule.RuleSet;
011 import jagafa.scores.ScoreTable;
012
013 import java.awt.event.ActionEvent;
014 import java.awt.event.ActionListener;
015 import java.util.Observable;
016 import java.util.Observer;
017
018 import javax.swing.Timer;
019
020 /**
021 * RoundController2 collects UI actions from the view and sends it to the
022 * round object.
023 * He also gets UI-update notification of the round and sends it to the view
024 *
025 * This version of RoundController does not show anything on the screen. It just creates
026 * the views. A top-level controller can fetch those views (JPanel) by calling the get...()
027 * methods.
028 */
029 public class RoundController2 extends Observable implements ActionListener, Observer {
030
031 private static final int PLAYERS = 4;
032
033 private JassRound round_;
034
035 private JassRoundPanel roundPanel_;
036
037 private RoundStatsPanel statView_;
038
039 private ScoreTable scoreTable_;
040
041 private RuleChoicePanel ruleChoice_;
042
043 private SimpleSTPanel stPanel_;
044
045 /**
046 * Constructor does nothing. Game has to be started by calling
047 * startGame(Rules r)
048 */
049 public RoundController2() {
050 installRestartTimer();
051
052 }
053
054 /** Update the ui according to changes in the round_ */
055 private void updateUI() {
056
057 for (int i = 0; i < PLAYERS; i++) {
058 if (TestingFlags.showAllHands_) {
059 roundPanel_.showHand(i);
060 } else {
061
062 if (this.round_.getPlayer(i).isComputer()) {
063 if (!TestingFlags.showHand_[i]) {
064 roundPanel_.hideHand(i);
065 } else {
066 roundPanel_.showHand(i);
067 }
068 } else {
069 roundPanel_.showHand(i);
070 }
071 }
072 roundPanel_.updateHandPanel(round_.getPlayer(i).getHand(), i);
073
074 }
075
076 roundPanel_.getBoardPanel().updateBoardUI(round_.activeBoard());
077
078 roundPanel_.repaint();
079 this.stPanel_.update();
080 if (TestingFlags.showRoundStats_) {
081 this.updateStats();
082 }
083
084 this.setChanged();
085 this.notifyObservers();
086 this.clearChanged();
087
088 }
089
090 /**
091 * Called by the top-level UI's cardPressed() method
092 */
093 public void actionPerformed(ActionEvent e) {
094 userAction(e);
095
096 }
097
098 /**
099 * Called when the User pushes a CardButton (through a ActionListener)
100 */
101 private void userAction(ActionEvent e) {
102 /* Extract hand and card-number */
103 String message = e.getActionCommand();
104
105 String hand = message.substring(0, 1);
106 String card = message.substring(1);
107
108 int playerNrOfHand = Integer.valueOf(hand).intValue();
109 int cardNrOfHand = Integer.valueOf(card).intValue();
110
111 /* check wether the hand is from the active player or not */
112 if (round_.activePlayerNr() == playerNrOfHand) {
113 if (!round_.activePlayer().isComputer()) {
114 round_.activePlayer().playCard(cardNrOfHand, round_);
115 }
116 }
117
118 /* update the UI */
119 updateUI();
120 }
121
122 /**
123 * Restart the controller
124 * Should not be used though a controller should only be used for one round
125 * HINT: Create a new Controller for another round.
126 * Just reuse the same ScoreTable object for the new Controller
127 *
128 * @deprecated
129 */
130
131 /**
132 * Starts the game with the ruleSet given
133 */
134 public void startRound(ScoreTable scoreTable) {
135 this.scoreTable_ = scoreTable;
136
137 /* create the UI */
138 this.stPanel_ = new SimpleSTPanel(this.scoreTable_);
139 roundPanel_ = new JassRoundPanel();
140
141 /* Add the card Listeners which will call cardPressed */
142 roundPanel_.addCardListener(this);
143
144 /* create the game engine with no RuleSet
145 * The ruleset will be defined before calling start() with
146 * round_.setRules(RuleSet rule)
147 * */
148 round_ = new JassRound(null);
149 round_.addObserver(this);
150
151 round_.setScoreTable(this.scoreTable_);
152
153 /* create stats UI if needed */
154 if (TestingFlags.showRoundStats_) {
155 statView_ = new RoundStatsPanel(round_);
156 statView_.setRound(round_);
157 }
158
159 /* Init RuleChoice UI */
160 ruleChoice_ = new RuleChoicePanel(round_, roundPanel_);
161
162 /* update the UI */
163 updateUI();
164 if (TestingFlags.automatedTest_) {
165 this.runAutomated();
166 }
167 this.stPanel_.update();
168 }
169
170 /* Update the stat view */
171 public void updateStats() {
172 statView_.update(this.round_.activePlayer());
173 this.stPanel_.update();
174 }
175
176 /**
177 * Update the UI when an observable calls this observer
178 */
179 public void update(Observable o, Object arg) {
180 updateScoreTable();
181
182 if (!TestingFlags.silentTest_) {
183 updateUI();
184 }
185
186 /* If the round is over, try a restart */
187 if (this.round_.isRoundOver()) {
188
189 if (TestingFlags.repeatedTest_) {
190 if (TestingFlags.maxRepeats_ > 0) {
191 if (TestingFlags.repeats_ == TestingFlags.maxRepeats_) {
192 TestingFlags.repeatedTest_ = false;
193 System.out.println("Stopped after " + TestingFlags.repeats_
194 + " rounds");
195 System.out.println("GradeWeight: " + AIFlags.GRADE_WEIGHT);
196
197 System.out.println(scoreTable_);
198 return;
199 }
200 TestingFlags.repeats_++;
201 }
202
203 restartTimer_.setRepeats(false);
204 restartTimer_.start();
205
206 }
207 }
208
209 }
210
211 /**
212 * Does nothing yet
213 *
214 */
215 private void updateScoreTable() {
216
217 }
218
219 /* The restart timer:
220 * TODO: remove after a top-level GameController is introduced
221 */
222 private Timer restartTimer_;
223
224 /**
225 * Install the restart timer
226 *
227 */
228 private void installRestartTimer() {
229 /**
230 * The restart timer is needed to wait for a new game to start
231 * If he is called, then the game waits 6 seconds, then the game
232 * will reset and restart itself if the game is endless
233 */
234 restartTimer_ = new Timer(TestingFlags.RESTART_DELAY, new ActionListener() {
235
236 public void actionPerformed(ActionEvent e) {
237 if (TestingFlags.repeatedTest_) {
238 round_.reset();
239
240 if (round_.getPlayer(scoreTable_.getStartPlayer()).isComputer()) {
241 runAutomated();
242 } else {
243 System.out.println("Current player is not a Computer player!");
244 }
245 }
246 }
247
248 });
249 restartTimer_.setRepeats(false);
250 }
251
252 /**
253 * Get the round instance of the controller
254 */
255 public JassRound getRound() {
256 return this.round_;
257 }
258
259 /**
260 * Get the rounds UI panel
261 */
262 public JassRoundPanel getRoundPanel() {
263 return this.roundPanel_;
264 }
265
266 /**
267 * Get the stats panel
268 */
269 public RoundStatsPanel getStatsPanel() {
270 return this.statView_;
271 }
272
273 /**
274 * Get the RuleChoice panel
275 */
276 public RuleChoicePanel getRuleChoicePanel() {
277 return this.ruleChoice_;
278 }
279
280 public void runAutomated() {
281 this.round_.reset();
282 Player startPlayer = this.round_.getPlayer(this.scoreTable_.getStartPlayer());
283
284 Player choosingPlayer = this.round_.getPlayer(this.scoreTable_.getChoosingPlayer());
285
286 RuleSet choice = choosingPlayer.getAI().chooseRuleSet();
287 if (choice == null) {
288 this.scoreTable_.changeChoosingPlayer();
289 choosingPlayer = this.round_.getPlayer(this.scoreTable_
290 .getChoosingPlayer());
291 startPlayer = this.round_
292 .getPlayer(this.scoreTable_.getStartPlayer());
293
294 choice = choosingPlayer.getAI().chooseRuleSet();
295 }
296 this.round_.setRules(choice);
297 this.round_.start(startPlayer);
298 this.ruleChoice_.updateRuleLabel();
299
300 this.round_.toggleNotify();
301 }
302
303
304 public SimpleSTPanel getSTPanel() {
305 return this.stPanel_;
306 }
307
308 public void toggleNoify() {
309 this.setChanged();
310 this.notifyObservers();
311 this.clearChanged();
312
313 }
314 }