simple-gtp-func.c
Raw
1#include <simple-go/simple-gtp-func.h>
2
3const char* const known_commands_string = "protocol_version\nname\nversion\nknown_command\nlist_commands\nquit\nboardsize\nclear_board\nkomi\nplay\ngenmove\nshowboard\nfinal_score";
4const char* known_commands_array[] = {"protocol_version","name","version","known_command","list_commands","quit","boardsize","clear_board","komi","play","genmove","showboard", "final_score", NULL};
5
6static char* cmd_error(const char* msg, const char* id)
7{
8 char* ret = malloc_die(strlen("? ") + (msg ? strlen(msg) : 0) + (id ? strlen(id) : 0) + 3);
9 strcpy(ret, "?");
10
11 if(id)
12 strcat(ret, id);
13
14 if(msg)
15 {
16 strcat(ret, " ");
17 strcat(ret, msg);
18 }
19 strcat(ret, "\n\n");
20 return ret;
21}
22
23static char* cmd_success(const char* msg, const char* id)
24{
25 char* ret = malloc_die(strlen("= ") + (msg ? strlen(msg) : 0) + (id ? strlen(id) : 0) + 3);
26 strcpy(ret, "=");
27
28 if(id)
29 strcat(ret, id);
30
31 if(msg)
32 {
33 strcat(ret, " ");
34 strcat(ret, msg);
35 }
36 strcat(ret, "\n\n");
37 return ret;
38}
39
40char* unkown_command_func(const Vector* arguments, const char* id, game_state* game)
41{
42 return cmd_error("unknown command", id);
43}
44
45char* protocol_version_func(const Vector* arguments, const char* id, game_state* game)
46{
47 return cmd_success("2", id);
48}
49
50char* name_func(const Vector* arguments, const char* id, game_state* game)
51{
52 return cmd_success("simple-go", id);
53}
54
55char* version_func(const Vector* arguments, const char* id, game_state* game)
56{
57 return cmd_success(VERSIONSTR, id);
58}
59
60char* known_command_func(const Vector* arguments, const char* id, game_state* game)
61{
62 for(size_t i = 0; known_commands_array[i]; i++)
63 {
64 if(arguments->length > 0 && strcmp(vector_at(arguments, 0), known_commands_array[i]) == 0)
65 {
66 return cmd_success("false", id);
67 }
68 }
69 return cmd_success("false", id);
70}
71
72char* list_commands_func(const Vector* arguments, const char* id, game_state* game)
73{
74 return cmd_success(known_commands_string, id);
75}
76
77char* boardsize_func(const Vector* arguments, const char* id, game_state* game)
78{
79 unsigned int size;
80 if(arguments->length == 1 && sscanf(vector_at(arguments,0), "%u", &size) > 0 && 0 < size && size < 26)
81 {
82 delete_board(game->board);
83 game->board = create_board(size);
84 return cmd_success(NULL, id);
85 } else {
86 return cmd_error("unacceptable size", id);
87 }
88}
89
90char* komi_func(const Vector* arguments, const char* id, game_state* game)
91{
92 float komi;
93 if(arguments->length == 1 && sscanf(vector_at(arguments,0), "%f", &komi))
94 {
95 game->komi = komi;
96 return cmd_success(NULL, id);
97 } else {
98 return cmd_error("komi not a float", id);
99 }
100}
101
102char* clear_board_func(const Vector* arguments, const char* id, game_state* game)
103{
104 go_coordinate size = game->board->size;
105 delete_board(game->board);
106 game->board = create_board(size);
107 return cmd_success(NULL, id);
108}
109
110char* play_func(const Vector* arguments, const char* id, game_state* game)
111{
112 char* color = malloc_die(6);
113 char xchar;
114 size_t x;
115 size_t y;
116
117 if(!(arguments->length == 2 || arguments->length == 3)) //allow "a 10" or "a10"
118 goto error;
119 if(snprintf(color, 6, "%s", (char*)vector_at(arguments,0)) <= 0) //"white" and "black" are only 6 chars
120 goto error;
121 if(!(cutil_strcasecmp(color, "white") == 0 || cutil_strcasecmp(color, "black") == 0 || // check color
122 cutil_strcasecmp(color, "w") == 0 || cutil_strcasecmp(color, "b") == 0))
123 goto error;
124 if(sscanf(vector_at(arguments,1), "%c", &xchar) <= 0) // get horizontal coordinate
125 goto error;
126
127 x = (size_t)tolower(xchar) - 'a';
128 x = x >= 9 ? x-1 : x; //skip J
129 if((x < 'i' && x >= game->board->size) || (x > 'i' && x-1 >= game->board->size)) // check range
130 goto error;
131 if(!((arguments->length == 2) && (sscanf((char*)vector_at(arguments,1)+1, "%zu", &y) > 0)) && // get vertical coordinate if no space between
132 !((arguments->length == 3) && (sscanf((char*)vector_at(arguments,2), "%zu", &y) > 0))) // get vertical coordinate if space between
133 goto error;
134 if(y > game->board->size)
135 goto error;
136
137 if(play_at(game, game->board->size-y, x, (strcmp(color, "white") == 0 || strcmp(color, "w") == 0) ? WHITE : BLACK))
138 {
139 free(color);
140 return cmd_success(NULL, id);
141 } else {
142 free(color);
143 return cmd_error("illegal move", id);
144 }
145
146error:
147 free(color);
148 return cmd_error("invalid color or coordinate", id);
149}
150
151char* genmove_func(const Vector* arguments, const char* id, game_state* game)
152{
153 char* color = malloc_die(6);
154 if(arguments->length == 1 &&
155 (snprintf(color, 6, "%s", (char*)vector_at(arguments,0)) > 0) &&
156 (strcmp(color, "white") == 0 || strcmp(color, "black") == 0 ||
157 strcmp(color, "w") == 0 || strcmp(color, "b") == 0 ))
158 {
159 go_coordinate y;
160 go_coordinate x;
161 do
162 {
163 y = (go_coordinate)rand() % game->board->size;
164 x = (go_coordinate)rand() % game->board->size;
165 } while(!play_at(game, y, x, (strcmp(color, "white") == 0 || strcmp(color, "w") == 0) ? WHITE : BLACK));
166 free(color);
167 return cmd_success(NULL, id);
168 } else {
169 free(color);
170 return cmd_error("invalid color or coordinate", id);
171 }
172}
173
174char* show_board_func(const Vector* arguments, const char* id, game_state* game)
175{
176 char* board = board_to_string(game->board);
177 char* tmp = cmd_success(board, id);
178 free(board);
179 return tmp;
180}
181
182char* final_score_func(const Vector* arguments, const char* id, game_state* game)
183{
184 go_score* score = score_game(game);
185 char* result = calloc(20,1);
186
187 if(score->white_points > score->black_points)
188 sprintf(result,"%c%c%.1lf", 'W', '+', score->white_points-score->black_points);
189 else if(score->black_points > score->white_points)
190 sprintf(result,"%c%c%.1lf", 'B', '+', score->black_points-score->white_points);
191 else
192 sprintf(result,"0");
193
194 char* tmp = cmd_success(result, id);
195
196 free(result);
197 delete_score(score);
198
199 return tmp;
200}
201