Prototype for gtp protocol

AuthorKonata <konata@posteo.jp>
Date
Commit79363be9a8d45bb54e5e9319c56ecc82d990af6a
Parentf60dc8c
8 files changed, 235 insertions(+), 42 deletions(-)
M.gitignore
@@ -1,6 +1,13 @@
11 # Binaries
22 test
33
4+#cutils files
5+cutils.h
6+cutils_endian.h
7+dyn_string.h
8+libcutils.so
9+vector.h
10+
411 # Prerequisites
512 *.d
613
@@ -52,4 +59,4 @@ test
5259 modules.order
5360 Module.symvers
5461 Mkfile.old
55-dkms.conf
62+dkms.conf
MMakefile
@@ -1,4 +1,3 @@
11 all:
2- gcc -Og -g test.c simple-go.c -o test -std=c11 \
3- -Wall -Wextra -Wpedantic -Wnull-dereference -Wshadow -Wconversion -Wstrict-prototypes -Wmissing-prototypes -Wcast-qual -Wstrict-overflow=5 -Wunreachable-code -Wno-unused-parameter \
4- -fsanitize=undefined
2+ gcc -L./ -lcutils -O0 -g test.c simple-go.c simple-gtp.c -o test -std=c11 \
3+ -Wall -Wextra -Wpedantic -Wnull-dereference -Wshadow -Wconversion -Wstrict-prototypes -Wmissing-prototypes -Wcast-qual -Wstrict-overflow=5 -Wunreachable-code -Wno-unused-parameter -Wno-missing-prototypes \
Arun.sh
@@ -0,0 +1,2 @@
1+#!/bin/bash
2+LD_LIBRARY_PATH=. ./test
Msimple-go.c
@@ -1,12 +1,12 @@
11 #include "simple-go.h"
22
3-go_board* create_board(size_t size)
3+go_board* create_board(unsigned int size)
44 {
55 go_board* board = malloc(sizeof(*board));
66 assert(board);
77 board->field_array = malloc(size*size*sizeof(*board->field_array));
88 assert(board->field_array);
9- for(size_t i = 0; i < size*size; i++)
9+ for(unsigned int i = 0; i < size*size; i++)
1010 {
1111 board->field_array[i] = EMPTY;
1212 }
@@ -21,11 +21,12 @@ void delete_board(go_board* board)
2121 free(board);
2222 }
2323
24-game_state* create_game(size_t size)
24+game_state* create_game(unsigned int size, float komi)
2525 {
2626 game_state* game = malloc(sizeof(*game));
2727 game->board = create_board(size);
2828 game->black_turn = true;
29+ game->komi = komi;
2930
3031 return game;
3132 }
@@ -36,7 +37,7 @@ void delete_game(game_state* game)
3637 free(game);
3738 }
3839
39-bool check_bounds(go_board* board, size_t y, size_t x)
40+bool check_bounds(go_board* board, unsigned int y, unsigned int x)
4041 {
4142 if(y < board->size && x < board->size)
4243 return true;
@@ -46,9 +47,9 @@ bool check_bounds(go_board* board, size_t y, size_t x)
4647
4748 void kill_group(go_board* board, go_board* overlay)
4849 {
49- for(size_t y = 0; y < board->size; y++)
50+ for(unsigned int y = 0; y < board->size; y++)
5051 {
51- for(size_t x = 0; x < board->size; x++)
52+ for(unsigned int x = 0; x < board->size; x++)
5253 {
5354 if(get_board_at(overlay, y, x) == GROUP)
5455 set_board_at(board, y, x, EMPTY);
@@ -58,9 +59,9 @@ void kill_group(go_board* board, go_board* overlay)
5859
5960 void print_board(go_board* board)
6061 {
61- for(size_t y = 0; y < board->size; y++)
62+ for(unsigned int y = 0; y < board->size; y++)
6263 {
63- for(size_t x = 0; x < board->size; x++)
64+ for(unsigned int x = 0; x < board->size; x++)
6465 {
6566 putchar(get_board_at(board,y,x));
6667 putchar(' ');
@@ -69,7 +70,7 @@ void print_board(go_board* board)
6970 }
7071 }
7172
72-bool play_at(game_state* game, size_t y, size_t x)
73+bool play_at(game_state* game, unsigned int y, unsigned int x)
7374 {
7475 //check out-of-bounds
7576 if(!check_bounds(game->board, y, x))
@@ -116,6 +117,7 @@ bool play_at(game_state* game, size_t y, size_t x)
116117 kill_group(game->board, enemy_group);
117118 can_place = true;
118119 }
120+ delete_board(enemy_group);
119121 } else if(left == EMPTY) {
120122 can_place = true;
121123 } else {
@@ -135,6 +137,7 @@ bool play_at(game_state* game, size_t y, size_t x)
135137 kill_group(game->board, enemy_group);
136138 can_place = true;
137139 }
140+ delete_board(enemy_group);
138141 } else if(down == EMPTY) {
139142 can_place = true;
140143 } else {
@@ -154,6 +157,7 @@ bool play_at(game_state* game, size_t y, size_t x)
154157 kill_group(game->board, enemy_group);
155158 can_place = true;
156159 }
160+ delete_board(enemy_group);
157161 } else if(right == EMPTY) {
158162 can_place = true;
159163 } else {
@@ -172,7 +176,7 @@ bool play_at(game_state* game, size_t y, size_t x)
172176 return true;
173177 }
174178
175-char get_board_at(go_board* board, size_t y, size_t x)
179+char get_board_at(go_board* board, unsigned int y, unsigned int x)
176180 {
177181 if(check_bounds(board, y, x))
178182 return board->field_array[y*board->size+x];
@@ -180,45 +184,46 @@ char get_board_at(go_board* board, size_t y, size_t x)
180184 return INVALID_FIELD;
181185 }
182186
183-void set_board_at(go_board* board, size_t y, size_t x, char item)
187+void set_board_at(go_board* board, unsigned int y, unsigned int x, char item)
184188 {
185189 if(check_bounds(board,y,x))
186190 board->field_array[y*board->size+x] = item;
187191 }
188192
189-void find_group(go_board* board, go_board* overlay, size_t y, size_t x)
193+void find_group(go_board* board, go_board* overlay, unsigned int y, unsigned int x)
190194 {
191195 assert(board->size == overlay->size);
192- assert(check_bounds(board, y, x));
193-
194- set_board_at(overlay, y, x, GROUP);
195- char field = get_board_at(board,y,x);
196+ if(check_bounds(board, y, x))
197+ {
198+ set_board_at(overlay, y, x, GROUP);
199+ char field = get_board_at(board,y,x);
196200
197- if(get_board_at(board,y-1,x) == field && get_board_at(overlay,y-1,x) == EMPTY)
198- find_group(board, overlay, y-1, x);
201+ if(get_board_at(board,y-1,x) == field && get_board_at(overlay,y-1,x) == EMPTY)
202+ find_group(board, overlay, y-1, x);
199203
200- if(get_board_at(board,y,x-1) == field && get_board_at(overlay,y,x-1) == EMPTY)
201- find_group(board, overlay, y, x-1);
204+ if(get_board_at(board,y,x-1) == field && get_board_at(overlay,y,x-1) == EMPTY)
205+ find_group(board, overlay, y, x-1);
202206
203- if(get_board_at(board,y+1,x) == field && get_board_at(overlay,y+1,x) == EMPTY)
204- find_group(board, overlay, y+1, x);
207+ if(get_board_at(board,y+1,x) == field && get_board_at(overlay,y+1,x) == EMPTY)
208+ find_group(board, overlay, y+1, x);
205209
206- if(get_board_at(board,y,x+1) == field && get_board_at(overlay,y,x+1) == EMPTY)
207- find_group(board, overlay, y, x+1);
210+ if(get_board_at(board,y,x+1) == field && get_board_at(overlay,y,x+1) == EMPTY)
211+ find_group(board, overlay, y, x+1);
212+ }
208213 }
209214
210-size_t count_liberties(go_board* board, go_board* overlay)
215+unsigned long count_liberties(go_board* board, go_board* overlay)
211216 {
212217 assert(board->size == overlay->size);
213218
214219 go_board* tmpoverlay = create_board(board->size);
215220 memcpy(tmpoverlay->field_array, overlay->field_array, board->size*board->size);
216221
217- size_t liberties = 0;
222+ unsigned long liberties = 0;
218223
219- for(size_t y = 0; y < board->size; y++)
224+ for(unsigned int y = 0; y < board->size; y++)
220225 {
221- for(size_t x = 0; x < board->size; x++)
226+ for(unsigned int x = 0; x < board->size; x++)
222227 {
223228 if(get_board_at(overlay, y, x) == GROUP)
224229 {
Msimple-go.h
@@ -17,31 +17,32 @@
1717 typedef struct go_board
1818 {
1919 char* field_array;
20- size_t size;
20+ unsigned int size;
2121 } go_board;
2222
2323 typedef struct game_state
2424 {
2525 go_board* board;
26+ float komi;
2627 bool black_turn;
2728 } game_state;
2829
2930
30-go_board* create_board(size_t size);
31+go_board* create_board(unsigned int size);
3132 void delete_board(go_board* board);
32-game_state* create_game(size_t size);
33+game_state* create_game(unsigned int size, float komi);
3334 void delete_game(game_state* game);
3435
35-bool check_bounds(go_board* board, size_t y, size_t x);
36-char get_board_at(go_board* board, size_t y, size_t x);
37-void set_board_at(go_board* board, size_t y, size_t x, char item);
36+bool check_bounds(go_board* board, unsigned int y, unsigned int x);
37+char get_board_at(go_board* board, unsigned int y, unsigned int x);
38+void set_board_at(go_board* board, unsigned int y, unsigned int x, char item);
3839
3940 void kill_group(go_board* board, go_board* overlay);
40-bool play_at(game_state* game, size_t y, size_t x);
41+bool play_at(game_state* game, unsigned int y, unsigned int x);
4142
4243 void print_board(go_board* board);
43-void find_group(go_board* board, go_board* overlay, size_t y, size_t x);
44-size_t count_liberties(go_board* board, go_board* overlay);
44+void find_group(go_board* board, go_board* overlay, unsigned int y, unsigned int x);
45+unsigned long count_liberties(go_board* board, go_board* overlay);
4546
4647
4748
Asimple-gtp.c
@@ -0,0 +1,147 @@
1+#include "simple-gtp.h"
2+
3+char* cmd_error(const char* msg)
4+{
5+ char* ret = malloc(strlen("? ") + strlen(msg) + 1);
6+ strcpy(ret, "? ");
7+ strcat(ret, msg);
8+ return ret;
9+}
10+
11+char* cmd_success(const char* msg)
12+{
13+ char* ret = malloc(strlen("= ") + strlen(msg) + 2);
14+ strcpy(ret, "= ");
15+ strcat(ret, msg);
16+ return ret;
17+}
18+
19+const char* const known_commands_string = "protocol_version\nname\nversion\nknown_command\nlist_commands\nquit\nboardsize\nclear_board\nkomi\nplay\ngenmove\nshowboard";
20+const char* known_commands_array[] = {"protocol_version","name","version","known_command","list_commands","quit","boardsize","clear_board","komi","play","genmove","showboard"};
21+int cmd_count = sizeof(known_commands_array)/sizeof(known_commands_array[0]);
22+
23+char* handle_gtp_cmd(const char* msg, game_state* game)
24+{
25+ if(!msg || !strlen(msg))
26+ {
27+ char* ret = calloc(1,1);
28+ return ret;
29+ }
30+
31+ char* command = malloc(strlen(msg) + 1);
32+ sscanf(msg, "%s", command);
33+
34+ Vector* arguments = new_vector();
35+
36+ char* tmp_msg = malloc(strlen(msg)+1);
37+ strcpy(tmp_msg, msg);
38+
39+
40+ char* current = strtok(tmp_msg, " ");
41+ char* tmp_arg;
42+
43+ while(current)
44+ {
45+ tmp_arg = malloc(strlen(current)+1);
46+ strcpy(tmp_arg, current);
47+ vector_push(arguments, tmp_arg);
48+ current = strtok(NULL, " ");
49+ }
50+
51+ char* (*func_ptr)(const char*) = cmd_error;
52+ const char* func_args = "unknown command";
53+
54+ if(strcmp(command, "protocol_version") == 0)
55+ {
56+ func_ptr = cmd_success;
57+ func_args = "2";
58+ } else if(strcmp(command, "name") == 0) {
59+ func_ptr = cmd_success;
60+ func_args = "simple-go";
61+ } else if(strcmp(command, "version") == 0) {
62+ func_ptr = cmd_success;
63+ func_args = "0.1";
64+ } else if(strcmp(command, "known_command") == 0) {
65+ func_ptr = cmd_success;
66+ func_args = "false";
67+ for(int i = 0; i < cmd_count; i++)
68+ {
69+ if(arguments->length > 0 && strcmp(vector_at(arguments, 0), known_commands_array[i]) == 0)
70+ {
71+ func_args = "true";
72+ break;
73+ }
74+ }
75+ } else if(strcmp(command, "list_commands") == 0) {
76+ func_ptr = cmd_success;
77+ func_args = known_commands_string;
78+ } else if(strcmp(command, "boardsize") == 0) {
79+ unsigned int size;
80+ if(arguments->length == 1 && sscanf(vector_at(arguments,0), "%u", &size) > 0 && 0 < size && size < 26)
81+ {
82+ func_ptr = cmd_success;
83+ func_args = "";
84+ delete_board(game->board);
85+ game->board = create_board(size);
86+ } else {
87+ func_ptr = cmd_error;
88+ func_args = "unacceptable size";
89+ }
90+ } else if(strcmp(command, "komi") == 0) {
91+ float komi;
92+ if(arguments->length == 1 && sscanf(vector_at(arguments,0), "%f", &komi))
93+ {
94+ func_ptr = cmd_success;
95+ func_args = "";
96+ game->komi = komi;
97+ } else {
98+ func_ptr = cmd_error;
99+ func_args = "komi not a float";
100+ }
101+ } else if(strcmp(command, "clear_board") == 0) {
102+ unsigned int size = game->board->size;
103+ delete_board(game->board);
104+ game->board = create_board(size);
105+ } else if(strcmp(command, "play") == 0) {
106+ char* color = malloc(6);
107+ char y;
108+ int x;
109+ if((arguments->length == 2 || arguments->length == 3) &&
110+ (snprintf(color, 6, "%s", (char*)vector_at(arguments,0)) > 0) &&
111+ (strcmp(color, "white") == 0 || strcmp(color, "black") == 0) &&
112+ (sscanf(vector_at(arguments,1), "%c", &y) > 0) &&
113+ ((unsigned char)(tolower(y) - 'a') < game->board->size) &&
114+ (sscanf((char*)vector_at(arguments,1)+1, "%d", &x) > 0) &&
115+ ((unsigned int)x <= game->board->size) && (unsigned int)x > 0)
116+ {
117+ if(play_at(game, (unsigned char)(y-'a'), (unsigned int)x-1))
118+ {
119+ func_ptr = cmd_success;
120+ func_args = "";
121+ } else {
122+ func_ptr = cmd_error;
123+ func_args = "illegal move";
124+ }
125+ } else {
126+ func_ptr = cmd_error;
127+ func_args = "invalid color or coordinate";
128+ }
129+ free(color);
130+ } else if(strcmp(command, "genmove") == 0) {
131+ unsigned int y;
132+ unsigned int x;
133+ do
134+ {
135+ y = (unsigned int)rand() % game->board->size;
136+ x = (unsigned int)rand() % game->board->size;
137+ } while(!play_at(game, y, x));
138+
139+ }
140+
141+ free(command);
142+ delete_vector(arguments, NULL);
143+ free(arguments);
144+ free(tmp_msg);
145+
146+ return func_ptr(func_args);
147+}
Asimple-gtp.h
@@ -0,0 +1,13 @@
1+#ifndef SIMPLE_GTP_H
2+#define SIMPLE_GTP_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.h"
9+#include "cutils.h"
10+
11+char* handle_gtp_cmd(const char* msg, game_state* game);
12+
13+#endif //SIMPLE_GTP_H
Mtest.c
@@ -1,4 +1,5 @@
11 #include "simple-go.h"
2+#include "simple-gtp.h"
23
34 void test1(void)
45 {
@@ -35,12 +36,13 @@ void test1(void)
3536 void test2(void)
3637 {
3738 puts("test2 running");
38- game_state* test_game = create_game(5);
39+ game_state* test_game = create_game(5, 0);
3940 go_board* test_board = test_game->board;
4041 set_board_at(test_board, 2, 3, WHITE);
4142 set_board_at(test_board, 3, 2, WHITE);
4243 set_board_at(test_board, 1, 2, WHITE);
4344 set_board_at(test_board, 2, 1, WHITE);
45+ set_board_at(test_board, 1, 1, BLACK);
4446
4547 play_at(test_game, 2, 2);
4648 print_board(test_game->board);
@@ -58,10 +60,27 @@ void test2(void)
5860 puts("test2 finished");
5961 }
6062
63+void test3(void)
64+{
65+ puts("test2 running");
66+
67+ game_state* test_game = create_game(11, 0);
68+
69+ char* ret =handle_gtp_cmd("play white a9", test_game);
70+ printf("%s\n", ret);
71+ print_board(test_game->board);
72+
73+ free(ret);
74+ delete_game(test_game);
75+
76+ puts("test2 finished");
77+}
78+
6179
6280 int main(int argc, char** argv)
6381 {
6482 test1();
6583 test2();
84+ test3();
6685
6786 }