Modified colors for compatibility with Tektronix 4107 terminal in ANSI mode.
[sgk-go] / interface / play_gmp.c
CommitLineData
7eeb782e
AT
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
2 * This is GNU Go, a Go program. Contact gnugo@gnu.org, or see *
3 * http://www.gnu.org/software/gnugo/ for more information. *
4 * *
5 * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
6 * 2008 and 2009 by the Free Software Foundation. *
7 * *
8 * This program is free software; you can redistribute it and/or *
9 * modify it under the terms of the GNU General Public License as *
10 * published by the Free Software Foundation - version 3 or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License in file COPYING for more details. *
17 * *
18 * You should have received a copy of the GNU General Public *
19 * License along with this program; if not, write to the Free *
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
21 * Boston, MA 02111, USA. *
22\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
23
24#include "gnugo.h"
25#include "liberty.h"
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <assert.h>
30
31#include "interface.h"
32#include "gmp.h"
33#include "sgftree.h"
34#include "gg_utils.h"
35
36/* --------------------------------------------------------------*/
37/* Play a game against a go-modem-protocol (GMP) client. */
38/* --------------------------------------------------------------*/
39void
40play_gmp(Gameinfo *gameinfo, int simplified)
41{
42 SGFTree sgftree;
43
44 Gmp *ge;
45 GmpResult message;
46 const char *error;
47
48 int i, j;
49 int passes = 0; /* two passes and its over */
50 int to_move; /* who's turn is next ? */
51
52 int mycolor = -1; /* who has which color */
53 int yourcolor;
54
55 if (gameinfo->computer_player == WHITE)
56 mycolor = 1;
57 else if (gameinfo->computer_player == BLACK)
58 mycolor = 0;
59
60 sgftree_clear(&sgftree);
61 sgftreeCreateHeaderNode(&sgftree, board_size, komi, gameinfo->handicap);
62
63 ge = gmp_create(0, 1);
64 TRACE("board size=%d\n", board_size);
65
66 /*
67 * The specification of the go modem protocol doesn't even discuss
68 * komi. So we have to guess the komi. If the komi is set on the
69 * command line, keep it. Otherwise, its value will be 0.0 and we
70 * use 5.5 in an even game, 0.5 otherwise.
71 */
72 if (komi == 0.0) {
73 if (gameinfo->handicap == 0)
74 komi = 5.5;
75 else
76 komi = 0.5;
77 }
78
79 if (!simplified) {
80 /* Leave all the -1's so the client can negotiate the game parameters. */
81 if (chinese_rules)
82 gmp_startGame(ge, -1, -1, 5.5, -1, mycolor, 0);
83 else
84 gmp_startGame(ge, -1, -1, 5.5, 0, mycolor, 0);
85 }
86 else {
87 gmp_startGame(ge, board_size, gameinfo->handicap,
88 komi, chinese_rules, mycolor, 1);
89 }
90
91 do {
92 message = gmp_check(ge, 1, NULL, NULL, &error);
93 } while (message == gmp_nothing || message == gmp_reset);
94
95 if (message == gmp_err) {
96 fprintf(stderr, "gnugo-gmp: Error \"%s\" occurred.\n", error);
97 exit(EXIT_FAILURE);
98 }
99 else if (message != gmp_newGame) {
100 fprintf(stderr, "gnugo-gmp: Expecting a newGame, got %s\n",
101 gmp_resultString(message));
102 exit(EXIT_FAILURE);
103 }
104
105 gameinfo->handicap = gmp_handicap(ge);
106 if (!check_boardsize(gmp_size(ge), stderr))
107 exit(EXIT_FAILURE);
108
109 gnugo_clear_board(gmp_size(ge));
110
111 /* Let's pretend GMP knows about komi in case something will ever change. */
112 komi = gmp_komi(ge);
113
114#if ORACLE
115 if (metamachine && oracle_exists)
116 oracle_clear_board(board_size);
117#endif
118
119 sgfOverwritePropertyInt(sgftree.root, "SZ", board_size);
120
121 TRACE("size=%d, handicap=%d, komi=%f\n", board_size,
122 gameinfo->handicap, komi);
123
124 if (gameinfo->handicap)
125 to_move = WHITE;
126 else
127 to_move = BLACK;
128
129 if (gmp_iAmWhite(ge)) {
130 mycolor = WHITE; /* computer white */
131 yourcolor = BLACK; /* human black */
132 }
133 else {
134 mycolor = BLACK;
135 yourcolor = WHITE;
136 }
137
138 gameinfo->computer_player = mycolor;
139 sgf_write_header(sgftree.root, 1, get_random_seed(), komi,
140 gameinfo->handicap, get_level(), chinese_rules);
141 gameinfo->handicap = gnugo_sethand(gameinfo->handicap, sgftree.root);
142 sgfOverwritePropertyInt(sgftree.root, "HA", gameinfo->handicap);
143
144 /* main GMP loop */
145 while (passes < 2) {
146
147 if (to_move == yourcolor) {
148 int move;
149 /* Get opponent's move from gmp client. */
150 message = gmp_check(ge, 1, &j, &i, &error);
151
152 if (message == gmp_err) {
153 fprintf(stderr, "GNU Go: Sorry, error from gmp client\n");
154 sgftreeAddComment(&sgftree, "got error from gmp client");
155 sgffile_output(&sgftree);
156 return;
157 }
158
159 if (message == gmp_undo) {
160 int k;
161 assert(j > 0);
162
163 for (k = 0; k < j; k++) {
164 if (!undo_move(1)) {
165 fprintf(stderr, "GNU Go: play_gmp UNDO: can't undo %d moves\n",
166 j - k);
167 break;
168 }
169 sgftreeAddComment(&sgftree, "undone");
170 sgftreeBack(&sgftree);
171 to_move = OTHER_COLOR(to_move);
172 }
173 continue;
174 }
175
176 if (message == gmp_pass) {
177 passes++;
178 move = PASS_MOVE;
179 }
180 else {
181 passes = 0;
182 move = POS(i, j);
183 }
184
185 TRACE("\nyour move: %1m\n\n", move);
186 sgftreeAddPlay(&sgftree, to_move, I(move), J(move));
187 gnugo_play_move(move, yourcolor);
188 sgffile_output(&sgftree);
189
190 }
191 else {
192 /* Generate my next move. */
193 float move_value;
194 int move;
195 if (autolevel_on)
196 adjust_level_offset(mycolor);
197 move = genmove(mycolor, &move_value, NULL);
198 gnugo_play_move(move, mycolor);
199 sgffile_add_debuginfo(sgftree.lastnode, move_value);
200
201 if (is_pass(move)) {
202 /* pass */
203 sgftreeAddPlay(&sgftree, to_move, -1, -1);
204 gmp_sendPass(ge);
205 ++passes;
206 }
207 else {
208 /* not pass */
209 sgftreeAddPlay(&sgftree, to_move, I(move), J(move));
210 gmp_sendMove(ge, J(move), I(move));
211 passes = 0;
212 TRACE("\nmy move: %1m\n\n", move);
213 }
214 sgffile_add_debuginfo(sgftree.lastnode, 0.0);
215 sgffile_output(&sgftree);
216 }
217
218 to_move = OTHER_COLOR(to_move);
219 }
220
221 /* two passes: game over */
222 gmp_sendPass(ge);
223
224 if (!quiet)
225 fprintf(stderr, "Game over - waiting for client to shut us down\n");
226 who_wins(mycolor, stderr);
227
228 if (showtime) {
229 gprintf("\nSLOWEST MOVE: %d at %1m ", slowest_movenum, slowest_move);
230 fprintf(stderr, "(%.2f seconds)\n", slowest_time);
231 fprintf(stderr, "\nAVERAGE TIME: %.2f seconds per move\n",
232 total_time / movenum);
233 fprintf(stderr, "\nTOTAL TIME: %.2f seconds\n",
234 total_time);
235 }
236
237
238 /* play_gmp() does not return to main(), therefore the score
239 * writing code is here.
240 */
241 {
242 float score = gnugo_estimate_score(NULL, NULL);
243 sgfWriteResult(sgftree.root, score, 1);
244 }
245 sgffile_output(&sgftree);
246
247 if (!simplified) {
248 /* We hang around here until cgoban asks us to go, since
249 * sometimes cgoban crashes if we exit first.
250 *
251 * FIXME: Check if this is still needed. I made it dependand on
252 * `simplifed' just to avoid changes in GMP mode.
253 */
254 while (1) {
255 message = gmp_check(ge, 1, &j, &i, &error);
256 if (!quiet)
257 fprintf(stderr, "Message %d from gmp\n", message);
258 if (message == gmp_err)
259 break;
260 }
261 }
262
263#if ORACLE
264 if (metamachine && oracle_exists)
265 dismiss_oracle();
266#endif
267
268 if (!quiet)
269 fprintf(stderr, "gnugo going down\n");
270}
271
272/*
273 * Local Variables:
274 * tab-width: 8
275 * c-basic-offset: 2
276 * End:
277 */