1 // Dummy.java
2 
3 package net.sf.gogui.tools.dummy;
4 
5 import java.io.File;
6 import java.io.IOException;
7 import java.io.PrintStream;
8 import java.util.Random;
9 import net.sf.gogui.go.GoPoint;
10 import net.sf.gogui.go.PointList;
11 import net.sf.gogui.gtp.GtpCallback;
12 import net.sf.gogui.gtp.GtpCommand;
13 import net.sf.gogui.gtp.GtpEngine;
14 import net.sf.gogui.gtp.GtpError;
15 import net.sf.gogui.version.Version;
16 
17 /** Dummy Go program for testing GTP controlling programs.
18     See the gogui-dummy documentation for information about the extension
19     commands. */
20 public class Dummy
21     extends GtpEngine
22 {
Dummy(PrintStream log, boolean useRandomSeed, long randomSeed, int resign)23     public Dummy(PrintStream log, boolean useRandomSeed, long randomSeed,
24                  int resign)
25         throws Exception
26     {
27         super(log);
28         registerCommands();
29         setName("gogui-dummy");
30         setVersion(Version.get());
31         m_random = new Random();
32         m_resign = resign;
33         if (useRandomSeed)
34             m_random.setSeed(randomSeed);
35         initSize(GoPoint.DEFAULT_SIZE);
36     }
37 
cmdBWBoard(GtpCommand cmd)38     public void cmdBWBoard(GtpCommand cmd)
39     {
40         cmd.getResponse().append('\n');
41         for (int x = 0; x < m_size; ++x)
42         {
43             for (int y = 0; y < m_size; ++y)
44             {
45                 cmd.getResponse().append(m_random.nextBoolean() ? 'B' : 'W');
46                 if (y < m_size - 1)
47                     cmd.getResponse().append(' ');
48             }
49             cmd.getResponse().append('\n');
50         }
51     }
52 
cmdBoardsize(GtpCommand cmd)53     public void cmdBoardsize(GtpCommand cmd) throws GtpError
54     {
55         cmd.checkNuArg(1);
56         int size = cmd.getIntArg(0, 1, GoPoint.MAX_SIZE);
57         initSize(size);
58     }
59 
cmdCrash(GtpCommand cmd)60     public void cmdCrash(GtpCommand cmd)
61     {
62         System.err.println("Aborting gogui-dummy");
63         System.exit(1);
64     }
65 
cmdClearBoard(GtpCommand cmd)66     public void cmdClearBoard(GtpCommand cmd) throws GtpError
67     {
68         initSize(m_size);
69     }
70 
cmdEcho(GtpCommand cmd)71     public void cmdEcho(GtpCommand cmd)
72     {
73         cmd.setResponse(cmd.getArgLine());
74     }
75 
cmdEchoErr(GtpCommand cmd)76     public void cmdEchoErr(GtpCommand cmd)
77     {
78         System.err.println(cmd.getArgLine());
79     }
80 
cmdDelay(GtpCommand cmd)81     public void cmdDelay(GtpCommand cmd) throws GtpError
82     {
83         cmd.checkNuArgLessEqual(1);
84         if (cmd.getNuArg() == 1)
85             m_delay = cmd.getIntArg(0, 0, Integer.MAX_VALUE);
86         else
87             cmd.getResponse().append(m_delay);
88     }
89 
cmdFileOpen(GtpCommand cmd)90     public void cmdFileOpen(GtpCommand cmd) throws GtpError
91     {
92         try
93         {
94             File f = new File(cmd.getArg());
95             cmd.setResponse("CanonicalPath: " + f.getCanonicalPath() + "\n" +
96                             "Exists:        " + f.exists() + "\n" +
97                             "CanRead:       " + f.canRead() + "\n" +
98                             "CanWrite:      " + f.canWrite() + "\n");
99         }
100         catch (IOException e)
101         {
102             throw new GtpError(e.getMessage());
103         }
104     }
105 
cmdFileSave(GtpCommand cmd)106     public void cmdFileSave(GtpCommand cmd) throws GtpError
107     {
108         File file = new File(cmd.getArg());
109         try
110         {
111             PrintStream out = new PrintStream(file);
112             out.println("Hello world!");
113             out.close();
114         }
115         catch (IOException e)
116         {
117             throw new GtpError(e.getMessage());
118         }
119     }
120 
cmdEPList(GtpCommand cmd)121     public void cmdEPList(GtpCommand cmd) throws GtpError
122     {
123         if (cmd.getNuArg() == 1 && cmd.getArg(0).equals("show"))
124             cmd.setResponse(GoPoint.toString(m_ePList));
125         else
126             m_ePList = cmd.getPointListArg(m_size);
127     }
128 
cmdGfx(GtpCommand cmd)129     public void cmdGfx(GtpCommand cmd)
130     {
131         cmd.setResponse("LABEL A4 test\n" +
132                         "COLOR green A5 A7 B9\n" +
133                         "COLOR #980098 B7 B8\n" +
134                         "SQUARE B5 C9\n" +
135                         "MARK A6 B6\n" +
136                         "TRIANGLE A9\n" +
137                         "WHITE A1\n" +
138                         "BLACK B1\n" +
139                         "CIRCLE c8\n" +
140                         "INFLUENCE a7 -1 b7 -0.75 c7 -0.5 d7 -0.25 e7 0"
141                         + " f7 0.25 g7 0.5 h7 0.75 j7 1\n" +
142                         "VAR b c1 w c2 b c3 b c4 w pass b c5\n" +
143                         "TEXT Graphics Demo\n");
144     }
145 
cmdGoGuiAnalyzeCommands(GtpCommand cmd)146     public void cmdGoGuiAnalyzeCommands(GtpCommand cmd) throws GtpError
147     {
148         cmd.checkArgNone();
149         String response =
150             "bwboard/BWBoard/gogui-dummy-bwboard\n" +
151             "none/Crash/gogui-dummy-crash\n" +
152             "none/Delay/gogui-dummy-delay %o\n" +
153             "eplist/EPList/gogui-dummy-eplist\n" +
154             "string/File Open/gogui-dummy-file_open %r\n" +
155             "none/File Save/gogui-dummy-file_save %w\n" +
156             "gfx/Gfx/gogui-dummy-gfx\n" +
157             "none/Invalid/gogui-dummy-invalid\n" +
158             "none/Live Gfx/gogui-dummy-live_gfx\n" +
159             "string/Long Response/gogui-dummy-long_response %s\n" +
160             "none/Next Failure/gogui-dummy-next_failure %s\n" +
161             "none/Next Success/gogui-dummy-next_success %s\n" +
162             "sboard/SBoard/gogui-dummy-sboard\n" +
163             "none/Sleep/gogui-dummy-sleep %s\n" +
164             "none/Sleep 20s/gogui-dummy-sleep\n";
165         cmd.setResponse(response);
166     }
167 
cmdGenmove(GtpCommand cmd)168     public void cmdGenmove(GtpCommand cmd)
169     {
170         ++m_numberGenmove;
171         if (m_numberGenmove == m_resign)
172         {
173             cmd.setResponse("resign");
174             return;
175         }
176         int numberPossibleMoves = 0;
177         for (int x = 0; x < m_size; ++x)
178             for (int y = 0; y < m_size; ++y)
179                 if (! m_alreadyPlayed[x][y])
180                     ++numberPossibleMoves;
181         GoPoint point = null;
182         if (numberPossibleMoves > 0)
183         {
184             int rand = m_random.nextInt(numberPossibleMoves);
185             int index = 0;
186             for (int x = 0; x < m_size && point == null; ++x)
187                 for (int y = 0; y < m_size && point == null; ++y)
188                     if (! m_alreadyPlayed[x][y])
189                     {
190                         if (index == rand)
191                             point = GoPoint.get(x, y);
192                         ++index;
193                     }
194         }
195         cmd.setResponse(GoPoint.toString(point));
196         if (point != null)
197             m_alreadyPlayed[point.getX()][point.getY()] = true;
198     }
199 
cmdInterrupt(GtpCommand cmd)200     public void cmdInterrupt(GtpCommand cmd) throws GtpError
201     {
202         cmd.checkArgNone();
203     }
204 
cmdInvalid(GtpCommand cmd)205     public void cmdInvalid(GtpCommand cmd) throws GtpError
206     {
207         cmd.checkArgNone();
208         printInvalidResponse("This is an invalid GTP response.\n" +
209                              "It does not start with a status character.\n");
210     }
211 
cmdLiveGfx(GtpCommand cmd)212     public void cmdLiveGfx(GtpCommand cmd) throws GtpError
213     {
214         cmd.checkArgNone();
215         System.err.println("gogui-gfx: TEXT Live Graphics Demo");
216         System.err.println("gogui-gfx: LABEL A4 test");
217         sleep(1000);
218         System.err.println("gogui-gfx: COLOR green A5 A7 B9");
219         sleep(1000);
220         System.err.println("gogui-gfx: COLOR #980098 B7 B8");
221         sleep(1000);
222         System.err.println("gogui-gfx:\n" +
223                            "SQUARE B5 C9\n" +
224                            "MARK A6 B6\n" +
225                            "TRIANGLE A9\n");
226         sleep(1000);
227         System.err.println("gogui-gfx: WHITE A1");
228         sleep(1000);
229         System.err.println("gogui-gfx: BLACK B1");
230         sleep(1000);
231         System.err.println("gogui-gfx: CIRCLE c8");
232         sleep(1000);
233         System.err.println("gogui-gfx: INFLUENCE a7 -1 b7 -0.75 c7 "
234                            + "-0.5 d7 -0.25 e7 0 f7 0.25 g7 0.5 h7 0.75 "
235                            + "j7 1");
236         sleep(1000);
237         System.err.println("gogui-gfx: VAR b c1 w c2 b c3 b c4 w pass "
238                            + "b c5");
239         sleep(1000);
240         System.err.println("gogui-gfx: CLEAR");
241     }
242 
cmdLongResponse(GtpCommand cmd)243     public void cmdLongResponse(GtpCommand cmd) throws GtpError
244     {
245         cmd.checkNuArg(1);
246         int n = cmd.getIntArg(0, 1, Integer.MAX_VALUE);
247         for (int i = 1; i <= n; ++i)
248         {
249             cmd.getResponse().append(i);
250             cmd.getResponse().append("\n");
251         }
252     }
253 
cmdNextFailure(GtpCommand cmd)254     public void cmdNextFailure(GtpCommand cmd) throws GtpError
255     {
256         nextResponseFixed(cmd, false);
257     }
258 
cmdNextSuccess(GtpCommand cmd)259     public void cmdNextSuccess(GtpCommand cmd) throws GtpError
260     {
261         nextResponseFixed(cmd, true);
262     }
263 
cmdPlay(GtpCommand cmd)264     public void cmdPlay(GtpCommand cmd) throws GtpError
265     {
266         cmd.checkNuArg(2);
267         cmd.getColorArg(0);
268         GoPoint point = cmd.getPointArg(1, m_size);
269         if (point != null)
270             m_alreadyPlayed[point.getX()][point.getY()] = true;
271     }
272 
cmdSBoard(GtpCommand cmd)273     public void cmdSBoard(GtpCommand cmd)
274     {
275         cmd.getResponse().append('\n');
276         for (int x = 0; x < m_size; ++x)
277         {
278             for (int y = 0; y < m_size; ++y)
279             {
280                 if (x == 1 && y == 1)
281                     cmd.getResponse().append("\"a b\"");
282                 else if (x == 1 && y == 2)
283                     cmd.getResponse().append("ab   ");
284                 else if (x == 1 && y == 3)
285                     cmd.getResponse().append("abc  ");
286                 else if (x == 2 && y == 1)
287                     cmd.getResponse().append("abcde");
288                 else
289                     cmd.getResponse().append("\"\"   ");
290                 if (y < m_size - 1)
291                     cmd.getResponse().append(' ');
292             }
293             cmd.getResponse().append('\n');
294         }
295     }
296 
cmdSleep(GtpCommand cmd)297     public void cmdSleep(GtpCommand cmd) throws GtpError
298     {
299         cmd.checkNuArgLessEqual(1);
300         long millis = 20000;
301         if (cmd.getNuArg() == 1)
302             millis = (long)(cmd.getDoubleArg(0) * 1000.0);
303         long showProgressInterval = Math.max(millis / 100, 1000);
304         long steps = millis / showProgressInterval;
305         long remaining = millis - steps * showProgressInterval;
306         for (long i = 0; i < steps && ! isInterrupted(); ++i)
307         {
308             System.err.println("gogui-gfx: TEXT " + (100L * i / steps) + " %");
309             sleep(showProgressInterval);
310         }
311         sleep(remaining);
312     }
313 
handleCommand(GtpCommand cmd)314     public void handleCommand(GtpCommand cmd) throws GtpError
315     {
316         if (m_nextResponseFixed)
317         {
318             m_nextResponseFixed = false;
319             if (! m_nextStatus)
320                 throw new GtpError(m_nextResponse);
321             cmd.setResponse(m_nextResponse);
322         }
323         else
324             super.handleCommand(cmd);
325         if (m_delay > 0)
326         {
327             try
328             {
329                 Thread.sleep(1000L * m_delay);
330             }
331             catch (InterruptedException e)
332             {
333             }
334         }
335     }
336 
337     private boolean m_nextResponseFixed;
338 
339     private boolean m_nextStatus;
340 
341     /** Delay every command (seconds) */
342     private int m_delay;
343 
344     private int m_numberGenmove;
345 
346     private final int m_resign;
347 
348     private int m_size;
349 
350     private boolean[][] m_alreadyPlayed;
351 
352     private final Random m_random;
353 
354     private String m_nextResponse;
355 
356     /** Editable point list for gogui-dummy-eplist command. */
357     private PointList m_ePList = new PointList();
358 
initSize(int size)359     private void initSize(int size)
360     {
361         m_alreadyPlayed = new boolean[size][size];
362         m_size = size;
363         m_numberGenmove = 0;
364     }
365 
nextResponseFixed(GtpCommand cmd, boolean nextStatus)366     private void nextResponseFixed(GtpCommand cmd, boolean nextStatus)
367     {
368         m_nextResponseFixed = true;
369         m_nextStatus = nextStatus;
370         m_nextResponse = cmd.getArgLine();
371     }
372 
registerCommands()373     private void registerCommands()
374     {
375         register("boardsize", new GtpCallback() {
376                 public void run(GtpCommand cmd) throws GtpError {
377                     cmdBoardsize(cmd); } });
378         register("clear_board", new GtpCallback() {
379                 public void run(GtpCommand cmd) throws GtpError {
380                     cmdClearBoard(cmd); } });
381         register("gogui-dummy-bwboard", new GtpCallback() {
382                 public void run(GtpCommand cmd) throws GtpError {
383                     cmdBWBoard(cmd); } });
384         register("gogui-dummy-crash", new GtpCallback() {
385                 public void run(GtpCommand cmd) throws GtpError {
386                     cmdCrash(cmd); } });
387         register("gogui-dummy-delay", new GtpCallback() {
388                 public void run(GtpCommand cmd) throws GtpError {
389                     cmdDelay(cmd); } });
390         register("gogui-dummy-eplist", new GtpCallback() {
391                 public void run(GtpCommand cmd) throws GtpError {
392                     cmdEPList(cmd); } });
393         register("gogui-dummy-file_open", new GtpCallback() {
394                 public void run(GtpCommand cmd) throws GtpError {
395                     cmdFileOpen(cmd); } });
396         register("gogui-dummy-file_save", new GtpCallback() {
397                 public void run(GtpCommand cmd) throws GtpError {
398                     cmdFileSave(cmd); } });
399         register("gogui-dummy-gfx", new GtpCallback() {
400                 public void run(GtpCommand cmd) throws GtpError {
401                     cmdGfx(cmd); } });
402         register("gogui-dummy-invalid", new GtpCallback() {
403                 public void run(GtpCommand cmd) throws GtpError {
404                     cmdInvalid(cmd); } });
405         register("gogui-dummy-live_gfx", new GtpCallback() {
406                 public void run(GtpCommand cmd) throws GtpError {
407                     cmdLiveGfx(cmd); } });
408         register("gogui-dummy-long_response", new GtpCallback() {
409                 public void run(GtpCommand cmd) throws GtpError {
410                     cmdLongResponse(cmd); } });
411         register("gogui-dummy-next_failure", new GtpCallback() {
412                 public void run(GtpCommand cmd) throws GtpError {
413                     cmdNextFailure(cmd); } });
414         register("gogui-dummy-next_success", new GtpCallback() {
415                 public void run(GtpCommand cmd) throws GtpError {
416                     cmdNextSuccess(cmd); } });
417         register("gogui-dummy-sboard", new GtpCallback() {
418                 public void run(GtpCommand cmd) throws GtpError {
419                     cmdSBoard(cmd); } });
420         register("gogui-dummy-sleep", new GtpCallback() {
421                 public void run(GtpCommand cmd) throws GtpError {
422                     cmdSleep(cmd); } });
423         register("echo", new GtpCallback() {
424                 public void run(GtpCommand cmd) throws GtpError {
425                     cmdEcho(cmd); } });
426         register("echo_err", new GtpCallback() {
427                 public void run(GtpCommand cmd) throws GtpError {
428                     cmdEchoErr(cmd); } });
429         register("genmove", new GtpCallback() {
430                 public void run(GtpCommand cmd) throws GtpError {
431                     cmdGenmove(cmd); } });
432         register("gogui-analyze_commands", new GtpCallback() {
433                 public void run(GtpCommand cmd) throws GtpError {
434                     cmdGoGuiAnalyzeCommands(cmd); } });
435         register("gogui-interrupt", new GtpCallback() {
436                 public void run(GtpCommand cmd) throws GtpError {
437                     cmdInterrupt(cmd); } });
438         register("play", new GtpCallback() {
439                 public void run(GtpCommand cmd) throws GtpError {
440                     cmdPlay(cmd); } });
441     }
442 
sleep(long millis)443     private void sleep(long millis)
444     {
445         try
446         {
447             Thread.sleep(millis);
448         }
449         catch (InterruptedException e)
450         {
451         }
452     }
453 }
454