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";
4const char* known_commands_array[] = {"protocol_version","name","version","known_command","list_commands","quit","boardsize","clear_board","komi","play","genmove","showboard", NULL};
5
6static char* cmd_error(const char* msg, const char* id)
7{
8 char* ret = malloc(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(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("0.1", 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 unsigned int 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(6);
113 char x;
114 int y;
115 if((arguments->length == 2 || arguments->length == 3) && //either its "a 10" or "a10"
116 (snprintf(color, 6, "%s", (char*)vector_at(arguments,0)) > 0) && //"white" and "black" are only 6 chars
117 (strcmp(color, "white") == 0 || strcmp(color, "black") == 0 ||
118 strcmp(color, "w") == 0 || strcmp(color, "b") == 0) && // check color
119 (sscanf(vector_at(arguments,1), "%c", &x) > 0) && // get horizontal coordinate
120 ((unsigned char)(tolower(x) - 'a') < game->board->size) && // check range
121 ((sscanf((char*)vector_at(arguments,1)+1, "%d", &y) > 0) || // get vertical coordinate if no space between
122 ((arguments->length == 3) && (sscanf((char*)vector_at(arguments,2), "%d", &y) > 0))) && // get vertical coordinate if space between
123 ((unsigned int)y <= game->board->size) && y > 0) // check range
124 {
125
126 if(play_at(game, game->board->size-(unsigned int)y, (unsigned char)(x-'a'), (strcmp(color, "white") == 0 || strcmp(color, "w") == 0) ? WHITE : BLACK))
127 {
128 free(color);
129 return cmd_success(NULL, id);
130 } else {
131 free(color);
132 return cmd_error("illegal move", id);
133 }
134 } else {
135 free(color);
136 return cmd_error("invalid color or coordinate", id);
137 }
138
139}
140
141char* genmove_func(const Vector* arguments, const char* id, game_state* game)
142{
143 char* color = malloc(6);
144 if(arguments->length == 1 &&
145 (snprintf(color, 6, "%s", (char*)vector_at(arguments,0)) > 0) &&
146 (strcmp(color, "white") == 0 || strcmp(color, "black") == 0 ||
147 strcmp(color, "w") == 0 || strcmp(color, "b") == 0 ))
148 {
149 go_coordinate y;
150 go_coordinate x;
151 do
152 {
153 y = (go_coordinate)rand() % game->board->size;
154 x = (go_coordinate)rand() % game->board->size;
155 } while(!play_at(game, y, x, (strcmp(color, "white") == 0 || strcmp(color, "w") == 0) ? WHITE : BLACK));
156 free(color);
157 return cmd_success(NULL, id);
158 } else {
159 free(color);
160 return cmd_error("invalid color or coordinate", id);
161 }
162}
163
164char* show_board_func(const Vector* arguments, const char* id, game_state* game)
165{
166 char* board = board_to_string(game->board);
167 char* tmp = cmd_success(board, id);
168 free(board);
169 return tmp;
170}
171
172char* final_score_func(const Vector* arguments, const char* id, game_state* game)
173{
174 go_score* score = score_game(game);
175 char* result = calloc(20,1);
176
177 if(score->white_points > score->black_points)
178 sprintf(result,"%c%c%.1lf", 'W', '+', score->white_points-score->black_points);
179 else if(score->black_points > score->white_points)
180 sprintf(result,"%c%c%.1lf", 'B', '+', score->black_points-score->white_points);
181 else
182 sprintf(result,"0");
183
184 char* tmp = cmd_success(result, id);
185
186 free(result);
187 delete_score(score);
188
189 return tmp;
190}
191