added test5(), refactored simple-gtp.c, added gtp input sanitizer, added game-scoring functions

AuthorKonata <konata@posteo.jp>
Date
Commit4cf3cbaacf300b2679ec0253b1fe5a00f34553eb
Parent77454c8
9 files changed, 447 insertions(+), 145 deletions(-)
Minclude/simple-go/simple-go.h
@@ -6,6 +6,7 @@
66 #include <stdio.h>
77 #include <assert.h>
88 #include <string.h>
9+#include <cutils/cutils.h>
910
1011 #define BLACK 'b'
1112 #define WHITE 'w'
@@ -27,9 +28,19 @@ typedef struct game_state
2728 {
2829 go_board* board;
2930 float komi;
31+ unsigned long white_captured;
32+ unsigned long black_captured;
3033 bool black_turn;
3134 } game_state;
3235
36+typedef struct go_score
37+{
38+ Vector* white_groups;
39+ Vector* black_groups;
40+ unsigned long white_points;
41+ unsigned long black_points;
42+} go_score;
43+
3344
3445 go_board* create_board(go_coordinate size);
3546 void delete_board(go_board* board);
@@ -40,15 +51,21 @@ bool check_bounds(const go_board* board, go_coordinate y, go_coordinate x);
4051 char get_board_at(const go_board* board, go_coordinate y, go_coordinate x);
4152 void set_board_at(go_board* board, go_coordinate y, go_coordinate x, char item);
4253
43-void kill_group(go_board* board, go_board* overlay);
54+void kill_group(go_board* board, const go_board* overlay);
4455 bool group_killable(game_state* game, go_coordinate y, go_coordinate x);
4556 bool group_attachable(const game_state* game, go_coordinate y, go_coordinate x);
4657 bool play_at(game_state* game, go_coordinate y, go_coordinate x, go_symbol color);
4758
48-void print_board(go_board* board);
49-char* board_to_string(go_board* board);
59+void print_board(const go_board* board);
60+char* board_to_string(const go_board* board);
5061 void find_group(const go_board* board, go_board* overlay, go_coordinate y, go_coordinate x);
51-unsigned long count_liberties(go_board* board, go_board* overlay);
62+go_symbol group_belongs(const go_board* board, const go_board* overlay);
63+unsigned long count_liberties(const go_board* board, const go_board* overlay);
64+unsigned long group_size(go_board* group);
65+
66+go_score* score_game(const game_state* board);
67+void delete_score(go_score* score);
68+
5269
5370
5471
Ainclude/simple-go/simple-gtp-func.h
@@ -0,0 +1,29 @@
1+#ifndef SIMPLE_GTP_FUNC_H
2+#define SIMPLE_GTP_FUNC_H
3+#include <string.h>
4+#include <stdlib.h>
5+#include <stdio.h>
6+#include <string.h>
7+#include <ctype.h>
8+#include <simple-go/simple-go.h>
9+#include <cutils/cutils.h>
10+
11+extern const char* const known_commands_string ;
12+extern const char* known_commands_array[];
13+
14+char* protocol_version_func(const Vector* arguments, const char* id, game_state* game);
15+char* name_func(const Vector* arguments, const char* id, game_state* game);
16+char* version_func(const Vector* arguments, const char* id, game_state* game);
17+char* known_command_func(const Vector* arguments, const char* id, game_state* game);
18+char* list_commands_func(const Vector* arguments, const char* id, game_state* game);
19+char* boardsize_func(const Vector* arguments, const char* id, game_state* game);
20+char* komi_func(const Vector* arguments, const char* id, game_state* game);
21+char* clear_board_func(const Vector* arguments, const char* id, game_state* game);
22+char* play_func(const Vector* arguments, const char* id, game_state* game);
23+char* genmove_func(const Vector* arguments, const char* id, game_state* game);
24+char* show_board_func(const Vector* arguments, const char* id, game_state* game);
25+char* final_score_func(const Vector* arguments, const char* id, game_state* game);
26+
27+
28+
29+#endif //SIMPLE_GTP_FUNC_H
Mmeson.build
@@ -1,9 +1,9 @@
11 project('simple-go', 'c')
22
3-CFLAGS = ['-std=c11', '-fstrict-aliasing', '-Wall', '-Wpedantic', '-Wextra']
3+CFLAGS = ['-std=c11', '-fstrict-aliasing', '-Wall', '-Wpedantic', '-Wextra', '-Wno-unused-parameter']
44
55 cutils_sp = subproject('cutils')
6-dep = cutils_sp.get_variable('cutils_dep')
6+dep = dependency('cutils', fallback : ['cutils', 'cutils_dep'])
77
88 subdir('include')
99 subdir('src')
Asrc/gtp-start.c
@@ -0,0 +1,21 @@
1+#include <simple-go/simple-go.h>
2+#include <simple-go/simple-gtp.h>
3+
4+int main(int argc, char** argv)
5+{
6+ game_state* game = create_game(19, 6.5);
7+ char input[50] = {0};
8+ char* answer;
9+
10+ while(1)
11+ {
12+ fgets(input, 49, stdin);
13+ if(strcmp(input, "quit\n") == 0)
14+ break;
15+ answer = handle_gtp_cmd(input, game);
16+ printf("%s", answer);
17+ free(answer);
18+ }
19+
20+ delete_game(game);
21+}
Msrc/meson.build
@@ -1,6 +1,7 @@
11 cutils_sp = subproject('cutils')
22 dep = cutils_sp.get_variable('cutils_dep')
33
4-src = ['simple-go.c', 'simple-gtp.c']
4+src = ['simple-go.c', 'simple-gtp.c', 'simple-gtp-func.c']
55
6-executable('test_go', src + ['test.c'], include_directories : inc, dependencies : dep, c_args: CFLAGS )
6+executable('test_go', src + ['test.c'], include_directories : inc, dependencies : dep, c_args: CFLAGS )
7+executable('gtp-start', src + ['gtp-start.c'], include_directories : inc, dependencies : dep, c_args: CFLAGS )
Msrc/simple-go.c
@@ -27,6 +27,8 @@ game_state* create_game(go_coordinate size, float komi)
2727 game->board = create_board(size);
2828 game->black_turn = true;
2929 game->komi = komi;
30+ game->white_captured = 0;
31+ game->black_captured = 0;
3032
3133 return game;
3234 }
@@ -45,7 +47,7 @@ bool check_bounds(const go_board* board, go_coordinate y, go_coordinate x)
4547 return false;
4648 }
4749
48-void kill_group(go_board* board, go_board* overlay)
50+void kill_group(go_board* board, const go_board* overlay)
4951 {
5052 for(go_coordinate y = 0; y < board->size; y++)
5153 {
@@ -57,7 +59,7 @@ void kill_group(go_board* board, go_board* overlay)
5759 }
5860 }
5961
60-void print_board(go_board* board)
62+void print_board(const go_board* board)
6163 {
6264 for(go_coordinate y = 0; y < board->size; y++)
6365 {
@@ -70,7 +72,7 @@ void print_board(go_board* board)
7072 }
7173 }
7274
73-char* board_to_string(go_board* board)
75+char* board_to_string(const go_board* board)
7476 {
7577 size_t str_size = (board->size*2+6)*(board->size+2)+2;
7678 char* ret = calloc(str_size+1,1);
@@ -108,10 +110,7 @@ char* board_to_string(go_board* board)
108110 ret[index++] = '\n';
109111 }
110112
111-
112-
113113 return ret;
114-
115114 }
116115
117116
@@ -238,7 +237,60 @@ void find_group(const go_board* board, go_board* overlay, go_coordinate y, go_co
238237 }
239238 }
240239
241-unsigned long count_liberties(go_board* board, go_board* overlay)
240+go_symbol group_belongs(const go_board* board, const go_board* overlay)
241+{
242+ assert(board->size == overlay->size);
243+
244+ go_symbol belongs = EMPTY;
245+
246+ for(go_coordinate y = 0; y < board->size; y++)
247+ {
248+ for(go_coordinate x = 0; x < board->size; x++)
249+ {
250+ if(get_board_at(overlay, y, x) == GROUP)
251+ {
252+ go_symbol up = get_board_at(board,y-1,x);
253+ go_symbol left = get_board_at(board,y,x-1);
254+ go_symbol down = get_board_at(board,y+1,x);
255+ go_symbol right = get_board_at(board,y,x+1);
256+
257+ if(up == WHITE || up == BLACK)
258+ {
259+ belongs = (belongs == EMPTY) ? up : (up != belongs ? NO_FIELD : up);
260+ }
261+ if(left == WHITE || left == BLACK)
262+ {
263+ belongs = (belongs == EMPTY) ? left : (left != belongs ? NO_FIELD : left);
264+ }
265+ if(down == WHITE || down == BLACK)
266+ {
267+ belongs = (belongs == EMPTY) ? down : (down != belongs ? NO_FIELD : down);
268+ }
269+ if(right == WHITE || right == BLACK)
270+ {
271+ belongs = (belongs == EMPTY) ? right : (right != belongs ? NO_FIELD : right);
272+ }
273+ }
274+ }
275+ }
276+ return belongs;
277+}
278+
279+unsigned long group_size(go_board* group)
280+{
281+ unsigned long sum = 0;
282+ for(go_coordinate y = 0; y < group->size; y++)
283+ {
284+ for(go_coordinate x = 0; x < group->size; x++)
285+ {
286+ if(get_board_at(group, y, x) == GROUP)
287+ ++sum;
288+ }
289+ }
290+ return sum;
291+}
292+
293+unsigned long count_liberties(const go_board* board, const go_board* overlay)
242294 {
243295 assert(board->size == overlay->size);
244296
@@ -283,4 +335,70 @@ unsigned long count_liberties(go_board* board, go_board* overlay)
283335 return liberties;
284336 }
285337
338+go_score* score_game(const game_state* game)
339+{
340+ go_score* ret = malloc(sizeof(*ret));
341+
342+ ret->white_groups = new_vector();
343+ ret->black_groups = new_vector();
344+ ret->white_points = game->white_captured;
345+ ret->black_points = game->black_captured;
346+
347+ go_board* board = game->board;
348+ go_board* current;
349+ go_symbol belongs;
350+
351+ for(go_coordinate y = 0; y < board->size; y++)
352+ {
353+ for(go_coordinate x = 0; x < board->size; x++)
354+ {
355+ //if field is empty
356+ if(get_board_at(board, y, x) == EMPTY)
357+ {
358+ //check if field is already counted
359+ for(go_coordinate i = 0; i < ret->white_groups->length; i++)
360+ {
361+ current = vector_at(ret->white_groups, i);
362+ if(get_board_at(current, y, x) == GROUP)
363+ continue;
364+ }
365+ for(go_coordinate i = 0; i < ret->black_groups->length; i++)
366+ {
367+ current = vector_at(ret->black_groups, i);
368+ if(get_board_at(current, y, x) == GROUP)
369+ continue;
370+ }
371+ go_board* overlay = create_board(board->size);
372+ find_group(board, overlay, y, x);
373+
374+ //check if field belongs to a group
375+ if((belongs = group_belongs(board, overlay)) == WHITE)
376+ {
377+ vector_push(ret->white_groups, overlay);
378+ ret->white_points += group_size(overlay);
379+ } else if(belongs == BLACK) {
380+ vector_push(ret->black_groups, overlay);
381+ ret->black_points += group_size(overlay);
382+ } else {
383+ delete_board(overlay);
384+ }
385+ }
386+ }
387+ }
388+
389+ return ret;
390+}
391+
392+void delete_board_wrapper(void* board)
393+{
394+ delete_board(board);
395+}
396+
397+void delete_score(go_score* score)
398+{
399+ delete_vector(score->white_groups, delete_board_wrapper);
400+ delete_vector(score->black_groups, delete_board_wrapper);
401+ free(score);
402+}
403+
286404
Asrc/simple-gtp-func.c
@@ -0,0 +1,170 @@
1+#include <simple-go/simple-gtp-func.h>
2+
3+const char* const known_commands_string = "protocol_version\nname\nversion\nknown_command\nlist_commands\nquit\nboardsize\nclear_board\nkomi\nplay\ngenmove\nshowboard";
4+const char* known_commands_array[] = {"protocol_version","name","version","known_command","list_commands","quit","boardsize","clear_board","komi","play","genmove","showboard", NULL};
5+
6+static 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+
23+static 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+
40+char* protocol_version_func(const Vector* arguments, const char* id, game_state* game)
41+{
42+ return cmd_success("2", id);
43+}
44+
45+char* name_func(const Vector* arguments, const char* id, game_state* game)
46+{
47+ return cmd_success("simple-go", id);
48+}
49+
50+char* version_func(const Vector* arguments, const char* id, game_state* game)
51+{
52+ return cmd_success("0.1", id);
53+}
54+
55+char* known_command_func(const Vector* arguments, const char* id, game_state* game)
56+{
57+ for(size_t i = 0; known_commands_array[i]; i++)
58+ {
59+ if(arguments->length > 0 && strcmp(vector_at(arguments, 0), known_commands_array[i]) == 0)
60+ {
61+ return cmd_success("false", id);
62+ }
63+ }
64+ return cmd_success("false", id);
65+}
66+
67+char* list_commands_func(const Vector* arguments, const char* id, game_state* game)
68+{
69+ return cmd_success(known_commands_string, id);
70+}
71+
72+char* boardsize_func(const Vector* arguments, const char* id, game_state* game)
73+{
74+ unsigned int size;
75+ if(arguments->length == 1 && sscanf(vector_at(arguments,0), "%u", &size) > 0 && 0 < size && size < 26)
76+ {
77+ delete_board(game->board);
78+ game->board = create_board(size);
79+ return cmd_success(NULL, id);
80+ } else {
81+ return cmd_error("unacceptable size", id);
82+ }
83+}
84+
85+char* komi_func(const Vector* arguments, const char* id, game_state* game)
86+{
87+ float komi;
88+ if(arguments->length == 1 && sscanf(vector_at(arguments,0), "%f", &komi))
89+ {
90+ game->komi = komi;
91+ return cmd_success(NULL, id);
92+ } else {
93+ return cmd_error("komi not a float", id);
94+ }
95+}
96+
97+char* clear_board_func(const Vector* arguments, const char* id, game_state* game)
98+{
99+ unsigned int size = game->board->size;
100+ delete_board(game->board);
101+ game->board = create_board(size);
102+ return cmd_success(NULL, id);
103+}
104+
105+char* play_func(const Vector* arguments, const char* id, game_state* game)
106+{
107+ char* color = malloc(6);
108+ char x;
109+ int y;
110+ if((arguments->length == 2 || arguments->length == 3) && //either its "a 10" or "a10"
111+ (snprintf(color, 6, "%s", (char*)vector_at(arguments,0)) > 0) && //"white" and "black" are only 6 chars
112+ (strcmp(color, "white") == 0 || strcmp(color, "black") == 0 ||
113+ strcmp(color, "w") == 0 || strcmp(color, "b") == 0) && // check color
114+ (sscanf(vector_at(arguments,1), "%c", &x) > 0) && // get horizontal coordinate
115+ ((unsigned char)(tolower(x) - 'a') < game->board->size) && // check range
116+ ((sscanf((char*)vector_at(arguments,1)+1, "%d", &y) > 0) || // get vertical coordinate if no space between
117+ ((arguments->length == 3) && (sscanf((char*)vector_at(arguments,2), "%d", &y) > 0))) && // get vertical coordinate if space between
118+ ((unsigned int)y <= game->board->size) && y > 0) // check range
119+ {
120+
121+ if(play_at(game, game->board->size-(unsigned int)y, (unsigned char)(x-'a'), (strcmp(color, "white") == 0 || strcmp(color, "w") == 0) ? WHITE : BLACK))
122+ {
123+ free(color);
124+ return cmd_success(NULL, id);
125+ } else {
126+ free(color);
127+ return cmd_error("illegal move", id);
128+ }
129+ } else {
130+ free(color);
131+ return cmd_error("invalid color or coordinate", id);
132+ }
133+
134+}
135+
136+char* genmove_func(const Vector* arguments, const char* id, game_state* game)
137+{
138+ char* color = malloc(6);
139+ if(arguments->length == 1 &&
140+ (snprintf(color, 6, "%s", (char*)vector_at(arguments,0)) > 0) &&
141+ (strcmp(color, "white") == 0 || strcmp(color, "black") == 0 ||
142+ strcmp(color, "w") == 0 || strcmp(color, "b") == 0 ))
143+ {
144+ go_coordinate y;
145+ go_coordinate x;
146+ do
147+ {
148+ y = (go_coordinate)rand() % game->board->size;
149+ x = (go_coordinate)rand() % game->board->size;
150+ } while(!play_at(game, y, x, (strcmp(color, "white") == 0 || strcmp(color, "w") == 0) ? WHITE : BLACK));
151+ free(color);
152+ return cmd_success(NULL, id);
153+ } else {
154+ free(color);
155+ return cmd_error("invalid color or coordinate", id);
156+ }
157+}
158+
159+char* show_board_func(const Vector* arguments, const char* id, game_state* game)
160+{
161+ char* board = board_to_string(game->board);
162+ char* tmp = cmd_success(board, id);
163+ free(board);
164+ return tmp;
165+}
166+
167+char* final_score_func(const Vector* arguments, const char* id, game_state* game)
168+{
169+ return NULL;
170+}
Msrc/simple-gtp.c
@@ -1,4 +1,5 @@
11 #include <simple-go/simple-gtp.h>
2+#include <simple-go/simple-gtp-func.h>
23
34 typedef struct msg_formatted
45 {
@@ -7,39 +8,6 @@ typedef struct msg_formatted
78 char* id;
89 } msg_formatted;
910
10-char* cmd_error(const char* msg, char* id)
11-{
12- char* ret = malloc(strlen("? ") + strlen(msg) + (id ? strlen(id) : 0) + 3);
13- strcpy(ret, "?");
14- if(id)
15- {
16- strcat(ret, id);
17- free(id);
18- }
19- strcat(ret, " ");
20- strcat(ret, msg);
21- strcat(ret, "\n\n");
22- return ret;
23-}
24-
25-char* cmd_success(const char* msg, char* id)
26-{
27- char* ret = malloc(strlen("= ") + strlen(msg) + (id ? strlen(id) : 0) + 3);
28- strcpy(ret, "=");
29- if(id)
30- {
31- strcat(ret, id);
32- free(id);
33- }
34- strcat(ret, " ");
35- strcat(ret, msg);
36- strcat(ret, "\n\n");
37- return ret;
38-}
39-
40-const char* const known_commands_string = "protocol_version\nname\nversion\nknown_command\nlist_commands\nquit\nboardsize\nclear_board\nkomi\nplay\ngenmove\nshowboard";
41-const char* known_commands_array[] = {"protocol_version","name","version","known_command","list_commands","quit","boardsize","clear_board","komi","play","genmove","showboard"};
42-int cmd_count = sizeof(known_commands_array)/sizeof(known_commands_array[0]);
4311
4412 static msg_formatted format_msg(const char* msg)
4513 {
@@ -85,6 +53,27 @@ static msg_formatted format_msg(const char* msg)
8553 return formatted;
8654 }
8755
56+static char* sanitize(const char* msg)
57+{
58+ char* ret = calloc(strlen(msg)+1, 1);
59+
60+ for(size_t i = 0, reti = 0; i < strlen(msg); i++)
61+ {
62+ if(msg[i] == '\t')
63+ {
64+ ret[reti++] = ' ';
65+ } else if(iscntrl(msg[i])){
66+ ++reti;
67+ } else if(msg[i] == '#'){
68+ break;
69+ } else {
70+ ret[reti++] = msg[i];
71+ }
72+ }
73+
74+ return ret;
75+}
76+
8877 char* handle_gtp_cmd(const char* msg, game_state* game)
8978 {
9079 if(!msg || !strlen(msg))
@@ -92,116 +81,47 @@ char* handle_gtp_cmd(const char* msg, game_state* game)
9281 char* ret = calloc(1,1);
9382 return ret;
9483 }
84+ char* msg_san = sanitize(msg);
9585
96- msg_formatted formatted = format_msg(msg);
86+ msg_formatted formatted = format_msg(msg_san);
9787 char* command = formatted.command;
9888 Vector* arguments = formatted.arguments;
9989 char* id = formatted.id;
10090
101- char* (*func_ptr)(const char*, char* id) = cmd_error;
102- const char* func_args = "unknown command";
91+ char* ret;
92+ char* (*func_ptr)(const Vector*, const char*, game_state*);
10393
10494 if(strcmp(command, "protocol_version") == 0)
10595 {
106- func_ptr = cmd_success;
107- func_args = "2";
96+ func_ptr = protocol_version_func;
10897 } else if(strcmp(command, "name") == 0) {
109- func_ptr = cmd_success;
110- func_args = "simple-go";
98+ func_ptr = name_func;
11199 } else if(strcmp(command, "version") == 0) {
112- func_ptr = cmd_success;
113- func_args = "0.1";
100+ func_ptr = version_func;
114101 } else if(strcmp(command, "known_command") == 0) {
115- func_ptr = cmd_success;
116- func_args = "false";
117- for(int i = 0; i < cmd_count; i++)
118- {
119- if(arguments->length > 0 && strcmp(vector_at(arguments, 0), known_commands_array[i]) == 0)
120- {
121- func_args = "true";
122- break;
123- }
124- }
102+ func_ptr = known_command_func;
125103 } else if(strcmp(command, "list_commands") == 0) {
126- func_ptr = cmd_success;
127- func_args = known_commands_string;
104+ func_ptr = list_commands_func;
128105 } else if(strcmp(command, "boardsize") == 0) {
129- unsigned int size;
130- if(arguments->length == 1 && sscanf(vector_at(arguments,0), "%u", &size) > 0 && 0 < size && size < 26)
131- {
132- func_ptr = cmd_success;
133- func_args = "";
134- delete_board(game->board);
135- game->board = create_board(size);
136- } else {
137- func_ptr = cmd_error;
138- func_args = "unacceptable size";
139- }
106+ func_ptr = boardsize_func;
140107 } else if(strcmp(command, "komi") == 0) {
141- float komi;
142- if(arguments->length == 1 && sscanf(vector_at(arguments,0), "%f", &komi))
143- {
144- func_ptr = cmd_success;
145- func_args = "";
146- game->komi = komi;
147- } else {
148- func_ptr = cmd_error;
149- func_args = "komi not a float";
150- }
108+ func_ptr = komi_func;
151109 } else if(strcmp(command, "clear_board") == 0) {
152- func_ptr = cmd_success;
153- func_args = "";
154- unsigned int size = game->board->size;
155- delete_board(game->board);
156- game->board = create_board(size);
110+ func_ptr = clear_board_func;
157111 } else if(strcmp(command, "play") == 0) {
158- char* color = malloc(6);
159- char x;
160- int y;
161- if((arguments->length == 2 || arguments->length == 3) && //either its "a 10" or "a10"
162- (snprintf(color, 6, "%s", (char*)vector_at(arguments,0)) > 0) && //"white" and "black" are only 6 chars
163- (strcmp(color, "white") == 0 || strcmp(color, "black") == 0) && // check color
164- (sscanf(vector_at(arguments,1), "%c", &x) > 0) && // get horizontal coordinate
165- ((unsigned char)(tolower(x) - 'a') < game->board->size) && // check range
166- ((sscanf((char*)vector_at(arguments,1)+1, "%d", &y) > 0) || // get vertical coordinate if no space between
167- ((arguments->length == 3) && (sscanf((char*)vector_at(arguments,2), "%d", &y) > 0))) && // get vertical coordinate if space between
168- ((unsigned int)y <= game->board->size) && y > 0) // check range
169- {
170- if(play_at(game, game->board->size-(unsigned int)y, (unsigned char)(x-'a'), strcmp(color, "white") == 0 ? WHITE : BLACK))
171- {
172- func_ptr = cmd_success;
173- func_args = "";
174- } else {
175- func_ptr = cmd_error;
176- func_args = "illegal move";
177- }
178- } else {
179- func_ptr = cmd_error;
180- func_args = "invalid color or coordinate";
181- }
182- free(color);
112+ func_ptr = play_func;
183113 } else if(strcmp(command, "genmove") == 0) {
184- func_ptr = cmd_success;
185- func_args = "";
186- go_coordinate y;
187- go_coordinate x;
188- do
189- {
190- y = (go_coordinate)rand() % game->board->size;
191- x = (go_coordinate)rand() % game->board->size;
192- } while(!play_at(game, y, x, NO_FIELD));
114+ func_ptr = genmove_func;
193115 } else if(strcmp(command, "showboard") == 0) {
194- char* board = board_to_string(game->board);
195-
196- free(command);
197- delete_vector(arguments, free);
198- char* tmp = cmd_success(board, id);
199- free(board);
200- return tmp;
116+ func_ptr = show_board_func;
201117 }
202118
119+ ret = func_ptr(arguments, id, game);
120+
203121 free(command);
122+ free(msg_san);
123+ free(id);
204124 delete_vector(arguments, free);
205125
206- return func_ptr(func_args, id);
126+ return ret;
207127 }
Msrc/test.c
@@ -138,20 +138,46 @@ void test4(void)
138138 puts("test4 finished");
139139 }
140140
141+void test5(void)
142+{
143+ puts("test5 running");
144+ game_state* game = create_game(19,0);
145+ set_board_at(game->board, 2, 3, WHITE);
146+ set_board_at(game->board, 2, 5, WHITE);
147+ set_board_at(game->board, 1, 4, WHITE);
148+ set_board_at(game->board, 3, 4, WHITE);
149+
150+ set_board_at(game->board, 5, 6, WHITE);
151+ set_board_at(game->board, 5, 8, WHITE);
152+ set_board_at(game->board, 4, 7, WHITE);
153+ set_board_at(game->board, 6, 7, BLACK);
154+
155+ set_board_at(game->board, 5, 2, BLACK);
156+ set_board_at(game->board, 5, 4, BLACK);
157+ set_board_at(game->board, 4, 3, BLACK);
158+ set_board_at(game->board, 6, 3, BLACK);
159+
160+ go_score* score = score_game(game);
161+ print_board(game->board);
162+ printf("White groups: %ld\n", score->white_groups->length);
163+ printf("White points: %ld\n", score->white_points);
164+ printf("Black groups: %ld\n", score->black_groups->length);
165+ printf("Black points: %ld\n", score->black_points);
166+
167+
168+ delete_score(score);
169+ delete_game(game);
170+ puts("test5 finished");
171+}
172+
141173
142174 int main(int argc, char** argv)
143175 {
144- game_state* game = create_game(19, 0);
176+
145177 test1();
146178 test2();
147179 test3();
148180 test4();
149- set_board_at(game->board, 2, 3, WHITE);
150- char* ret = handle_gtp_cmd("showboard", game);
151- printf("%s", ret);
152-
153-
154- free(ret);
155- delete_game(game);
181+ test5();
156182
157183 }