001    package jagafa;
002    
003    import jagafa.ai.JassAI;
004    import jagafa.ai.ProbabilityAI;
005    import jagafa.flags.TestingFlags;
006    import jagafa.object.Card;
007    import jagafa.object.Player;
008    import jagafa.rule.RuleSet;
009    
010    import java.awt.event.ActionEvent;
011    import java.awt.event.ActionListener;
012    
013    import javax.swing.Timer;
014    
015    public class JassRound extends JassRoundCore {
016    
017            /**
018             * Constructor: init the game with the ruleSet given
019             */
020            public JassRound(RuleSet rules) {
021                    super(rules);
022    
023            }
024    
025            /**
026             * Initialize all the players
027             * TODO: initPlayers() should be externalized or at least parameterized
028             */
029            protected void initPlayers() {
030                    Player.resetPlayerCount();
031                    for (int i = 0; i < 4; i++) {
032                            Player newPlayer = null;
033                            /* Add human or ai-driven player */
034                            if (TestingFlags.playerIsHuman_[i]) {
035                                    newPlayer = new Player(9, true);
036    
037                            } else {
038                                    newPlayer = new Player(9, false, new ProbabilityAI());
039                                    newPlayer.getAI().init(newPlayer, this);
040                            }
041                            addPlayer(newPlayer);
042    
043                    }
044            }
045    
046            public void start(Player startPlayer) {
047                    if (this.running_) {
048                            return;
049                    }
050                    this.setLastTurnWinner(startPlayer);
051                    this.setActivePlayer(startPlayer);
052                    start();
053            }
054    
055            /**
056             * Start the game by installing the main and refresh timers
057             * Only if the RuleSet is set!
058             */
059            public void start() {
060                    
061                    if (this.running_) {
062                            return;
063                    }
064                    
065                    if (this.getRules() != null) {
066                            
067                            this.running_ = true;
068                            installTimer();
069                    }
070            }
071    
072            /**
073             * Adds a card of Player p to the active Board, if valid
074             */
075            public synchronized void playCard(Card card, Player player) {
076    
077                    this.activeBoard().addCard(card, player);
078    
079                    this.nextPlayer();
080    
081                    /* 
082                     * If four cards are on the board, update scores, cleanup and refresh 
083                     * Otherwise do some AI processing
084                     */
085                    if (this.activeBoard().cardsPlayed() == 4) {
086    
087                            Player winner = getWinner(this.activeBoard());
088                            this.getGoneHeap().addTurn(this.activeBoard(), winner);
089                            winner.addScore(this.getScore(this.activeBoard()));
090    
091                            /* if round is over, add lastRound score, stop the ai timer and report 
092                             * scores to the top-level score table if there is any 
093                             */
094                            if (isRoundOver()) {
095                                    winner.addScore(5);
096    
097                                    reportScores();
098                                    aiTimer_.stop();
099                                    
100                            } else {
101                                    this.getRules().updateAfterTurn();
102                            }
103    
104                            /* Set the active Player to the winner */
105                            this.setLastTurnWinner(winner);
106                            this.setActivePlayer(winner);
107    
108                            /* Start the refresh timer */
109                            refreshTimer_.start();
110                    } else {
111    
112                            aiTimer_.start();
113                            this.toggleNotify();
114                    }
115    
116            }
117    
118            /**
119             * Do all computer movements
120             */
121            public synchronized void doComputer() {
122    
123                    if (activePlayer().isComputer()) {
124                            JassAI ai = activePlayer().getAI();
125                            ai.init(activePlayer(), this);
126                            activePlayer().playCard(ai.computeCard(), this);
127                            toggleNotify();
128    
129                    }
130                    /* If the game is over, repeat the ai timer only once to cleanup */
131                    if (this.isRoundOver()) {
132                            aiTimer_.setRepeats(false);
133                    }
134    
135            }
136    
137            /**
138             * Print the score to stdout
139             */
140            public void printScores() {
141                    int sum1 = this.getPlayer(0).getScore() + this.getPlayer(2).getScore();
142                    int sum2 = this.getPlayer(1).getScore() + this.getPlayer(3).getScore();
143                    System.out.println("Player 0 and 2: " + sum1);
144                    System.out.println("Player 1 and 3: " + sum2);
145            }
146    
147            /**
148             * Install the ai- and refresh-timers
149             */
150            private void installTimer() {
151                    /**
152                     * The refresh timer updates the ui every 1.5 seconds
153                     * In addition he clears the board if a turn/round is over
154                     */
155                    int uiDelay = TestingFlags.UI_REFRESH_DELAY;
156                    if (TestingFlags.speedUp_) {
157                            uiDelay = TestingFlags.FAST_UI_REFRESH_DELAY;
158                    }
159                    refreshTimer_ = new Timer(uiDelay, new ActionListener() {
160    
161                            public void actionPerformed(ActionEvent e) {
162    
163                                    if (activePlayer() == getLastTurnWinner()) {
164                                            activeBoard().clearBoard();
165                                            toggleNotify();
166                                    }
167    
168                            }
169    
170                    });
171                    refreshTimer_.setRepeats(false);
172    
173                    /**
174                     * The AI timer does a computer move and restarts the game if needed
175                     */
176                    int aiDelay = TestingFlags.NORMAL_AI_DELAY;
177                    if (TestingFlags.speedUp_) {
178                            aiDelay = TestingFlags.FAST_AI_DELAY;
179                    }
180    
181                    aiTimer_ = new Timer(aiDelay, new ActionListener() {
182    
183                            public void actionPerformed(ActionEvent e) {
184                                    if (TestingFlags.paused_) {
185                                            return;
186                                    }
187                                    if (!refreshTimer_.isRunning()) {
188                                            //for (int i = 0; i < 4; i++) {
189                                            doComputer();
190                                            //      }
191                                    }
192                                    if (isRoundOver()) {
193                                            running_ = false;
194                                            //restartTimer_.start();
195                                            //restartTimer_.setRepeats(false);
196                                    }
197    
198                            }
199    
200                    });
201                    aiTimer_.setRepeats(true);
202                    aiTimer_.start();
203            }
204    }