1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.cb.jset.client;
21
22 import org.apache.log4j.Logger;
23 import org.cb.jset.*;
24 import org.cb.jset.server.RemoteSetGame;
25
26 import java.util.List;
27 import java.util.ArrayList;
28
29 /***
30 * A player that finds sets automatically.
31 *
32 * @author jerome@coffeebreaks.org - last modified by $LastChangedBy: jerome $
33 * @version $Id: SmartAutoPlayer.java 123 2004-04-14 23:45:53Z jerome $
34 */
35 public class SmartAutoPlayer implements SetGameListener
36 {
37 private Logger _logger;
38 private SetFinderThread _thread;
39 private MatchingSetFinder _finder;
40 private String _name;
41 private NetworkGame _game;
42 private BoardImpl _board = new BoardImpl();
43
44 private final GameController _gameController = new GameController();
45
46 /***
47 * Creates a new instance with the specified player playerName.
48 */
49 public SmartAutoPlayer(final String playerName)
50 {
51 _logger = Logger.getLogger("SmartAutoPlayer-" + playerName);
52 _name = playerName;
53 _finder = new MatchingSetFinder();
54 _thread = new SetFinderThread();
55 }
56
57 public String name()
58 {
59 return _name;
60 }
61
62 private void printCards(final String msg, final CardProperties[] cards)
63 {
64 if (_logger.isInfoEnabled())
65 {
66 final StringBuffer buf = new StringBuffer(msg);
67 buf.append(CardProperties.toString(cards));
68 _logger.info(buf.toString());
69 }
70 }
71
72 void startPlayingGame(final RemoteSetGame game)
73 {
74 final NetworkGame networkGame = new NetworkGame("SmartAutoPlayerUser");
75 networkGame.setRemoteGame(game);
76 _game = networkGame;
77 _game.addBoardListener(_gameController);
78 _game.addGameListener(_gameController);
79 _game.start();
80 _thread.start();
81 }
82
83
84 /***
85 * Control events coming from the game instance.
86 *
87 * FIXME we probably need to add multithreading handling on the model.
88 */
89 class GameController implements SetGameBoardListener, SetGameListener
90 {
91 /***
92 * @inheritDoc
93 */
94 public void cardsAdded(final CardProperties[] cards)
95 {
96 _board.addCards(cards);
97 }
98
99 /***
100 * @inheritDoc
101 */
102 public void setRemoved(final CardSet set)
103 {
104 try
105 {
106 _board.matchSet(set);
107 }
108 catch (Exception e)
109 {
110 throw new IllegalStateException("BoardException should not happen here: " + e.getMessage());
111 }
112 }
113
114 /***
115 * @inheritDoc
116 */
117 public void gameChange(final GameEvent event)
118 {
119
120 }
121 }
122
123
124 public synchronized void gameChange(final GameEvent event)
125 {
126 if (event.getType() == GameEvent.END)
127 {
128 notifyAll();
129 }
130 }
131
132 class SetFinderThread extends Thread
133 {
134 public void run()
135 {
136 play();
137 }
138 }
139
140 private void play()
141 {
142 while (! _game.wasDisconnected())
143 {
144 tryToFindSet();
145 }
146 }
147
148 void tryToFindSet()
149 {
150 if (_logger.isInfoEnabled())
151 {
152 _logger.info("-- cards added - starting to find --");
153 }
154 int sleepTime = (int) (Math.random() * 6000);
155 if (_logger.isInfoEnabled())
156 {
157 _logger.info("Sleep for " + sleepTime + "ms.");
158 }
159 try
160 {
161 synchronized (SmartAutoPlayer.this)
162 {
163 wait(sleepTime);
164 }
165 }
166 catch(InterruptedException e)
167 {
168 }
169
170 if (true)
171 {
172 sleepTime = 60000;
173 try
174 {
175 Thread. sleep(sleepTime);
176 }
177 catch (InterruptedException e)
178 {
179 }
180 }
181
182 if (_logger.isInfoEnabled())
183 {
184 _logger.info("-- Awaken! -- ");
185 }
186 if (_game.wasDisconnected())
187 {
188 _logger.info("-- Connection was closed in the meantime -- ");
189 return;
190 }
191 if (_logger.isInfoEnabled())
192 {
193 _logger.info("-- Searching for sets -- ");
194 }
195 printCards("-- Cards on BoardImpl:", _board.getCards());
196
197 final List elements = new ArrayList();
198 for (int i = 0; i < _board.getCards().length; i++)
199 {
200 final CardProperties cardProperties = _board.getCards()[i];
201 elements.add(new JSetCard(cardProperties));
202 }
203 final CardSet[] sets = _finder.findSets(elements);
204 printMatchingSets(sets);
205 if (sets.length > 0)
206 {
207 final int randIdx = (int) (sets.length * Math.random());
208 if (_logger.isInfoEnabled())
209 {
210 _logger.info("Trying to remove set Idx" + randIdx + ": " + sets[randIdx]);
211 }
212 try
213 {
214 _game.removeSet(sets[randIdx]);
215 }
216 catch (MatchingException e)
217 {
218 if (_logger.isInfoEnabled())
219 {
220 _logger.info("Matching not accepted!", e);
221 }
222 }
223 }
224
225
226
227
228
229
230
231 }
232
233 void printMatchingSets(final CardSet[] foundSets)
234 {
235 if (_logger.isInfoEnabled())
236 {
237 final int maxPrinted = 5;
238 _logger.info("Found " + foundSets.length + " sets.");
239 int i;
240 for (i = 0; i < foundSets.length && i < maxPrinted; i++)
241 {
242 _logger.info("CardSet[" + i + "]:" + foundSets[i]);
243 }
244 if (i < foundSets.length)
245 {
246 _logger.info("Skipping " + (foundSets.length - i) + " set(s)...");
247 }
248 }
249 }
250 }