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    }