added typedefs for possible future changes, refactored play_at()(added helper functions), fixed some possible overflow

AuthorKonata <konata@posteo.jp>
Date
Commit647a5678b910eaeeffb48bc79a7501ecd31b66b8
Parent79363be
4 files changed, 91 insertions(+), 100 deletions(-)
Msimple-go.c
@@ -1,12 +1,12 @@
11 #include "simple-go.h"
22
3-go_board* create_board(unsigned int size)
3+go_board* create_board(go_coordinate 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(unsigned int i = 0; i < size*size; i++)
9+ for(go_coordinate i = 0; i < size*size; i++)
1010 {
1111 board->field_array[i] = EMPTY;
1212 }
@@ -21,7 +21,7 @@ void delete_board(go_board* board)
2121 free(board);
2222 }
2323
24-game_state* create_game(unsigned int size, float komi)
24+game_state* create_game(go_coordinate size, float komi)
2525 {
2626 game_state* game = malloc(sizeof(*game));
2727 game->board = create_board(size);
@@ -37,7 +37,7 @@ void delete_game(game_state* game)
3737 free(game);
3838 }
3939
40-bool check_bounds(go_board* board, unsigned int y, unsigned int x)
40+bool check_bounds(const go_board* board, go_coordinate y, go_coordinate x)
4141 {
4242 if(y < board->size && x < board->size)
4343 return true;
@@ -47,9 +47,9 @@ bool check_bounds(go_board* board, unsigned int y, unsigned int x)
4747
4848 void kill_group(go_board* board, go_board* overlay)
4949 {
50- for(unsigned int y = 0; y < board->size; y++)
50+ for(go_coordinate y = 0; y < board->size; y++)
5151 {
52- for(unsigned int x = 0; x < board->size; x++)
52+ for(go_coordinate x = 0; x < board->size; x++)
5353 {
5454 if(get_board_at(overlay, y, x) == GROUP)
5555 set_board_at(board, y, x, EMPTY);
@@ -59,9 +59,9 @@ void kill_group(go_board* board, go_board* overlay)
5959
6060 void print_board(go_board* board)
6161 {
62- for(unsigned int y = 0; y < board->size; y++)
62+ for(go_coordinate y = 0; y < board->size; y++)
6363 {
64- for(unsigned int x = 0; x < board->size; x++)
64+ for(go_coordinate x = 0; x < board->size; x++)
6565 {
6666 putchar(get_board_at(board,y,x));
6767 putchar(' ');
@@ -70,7 +70,38 @@ void print_board(go_board* board)
7070 }
7171 }
7272
73-bool play_at(game_state* game, unsigned int y, unsigned int x)
73+
74+
75+bool group_attachable(const game_state* game, go_coordinate y, go_coordinate x)
76+{
77+ go_board* friendly_group = create_board(game->board->size);
78+ find_group(game->board, friendly_group, y, x);
79+ if(count_liberties(game->board, friendly_group) > 1)
80+ {
81+ delete_board(friendly_group);
82+ return true;
83+ } else {
84+ delete_board(friendly_group);
85+ return false;
86+ }
87+}
88+
89+bool group_killable(game_state* game, go_coordinate y, go_coordinate x)
90+{
91+ go_board* enemy_group = create_board(game->board->size);
92+ find_group(game->board, enemy_group, y, x);
93+ if(count_liberties(game->board, enemy_group) <= 1)
94+ {
95+ kill_group(game->board, enemy_group);
96+ delete_board(enemy_group);
97+ return true;
98+ } else {
99+ delete_board(enemy_group);
100+ return false;
101+ }
102+}
103+
104+bool play_at(game_state* game, go_coordinate y, go_coordinate x)
74105 {
75106 //check out-of-bounds
76107 if(!check_bounds(game->board, y, x))
@@ -82,91 +113,43 @@ bool play_at(game_state* game, unsigned int y, unsigned int x)
82113
83114 bool can_place = false;
84115
85- char up = get_board_at(game->board, y-1, x);
86- char left = get_board_at(game->board, y, x-1);
87- char down = get_board_at(game->board, y+1, x);
88- char right = get_board_at(game->board, y, x+1);
116+ go_symbol enemy = game->black_turn ? WHITE : BLACK;
117+ go_symbol friendly = game->black_turn ? BLACK : WHITE;
89118
90- //first check for group to kill, then for empty field, and last for group woth liberties
91- if(up == (game->black_turn ? WHITE : BLACK))
92- {
93- go_board* enemy_group = create_board(game->board->size);
94- find_group(game->board, enemy_group, y-1, x);
95- if(count_liberties(game->board, enemy_group) <= 1)
96- {
97- kill_group(game->board, enemy_group);
98- can_place = true;
99- }
100- delete_board(enemy_group);
101- } else if(up == EMPTY) {
119+ go_symbol up = y == 0 ? INVALID_FIELD : get_board_at(game->board, y-1, x);
120+ go_symbol left = x == 0 ? INVALID_FIELD : get_board_at(game->board, y, x-1);
121+ go_symbol down = y == game->board->size-1 ? INVALID_FIELD : get_board_at(game->board, y+1, x);
122+ go_symbol right = x == game->board->size-1 ? INVALID_FIELD : get_board_at(game->board, y, x+1);
123+
124+ //first check for group to kill, then for empty field, and last for group with liberties
125+
126+ if(up == enemy && group_killable(game, y-1, x))
127+ can_place = true;
128+ else if(up == EMPTY)
129+ can_place = true;
130+ else if(up == friendly && group_attachable(game, y-1, x))
102131 can_place = true;
103- } else {
104- go_board* friendly_group = create_board(game->board->size);
105- find_group(game->board, friendly_group, y-1, x);
106- if(count_liberties(game->board, friendly_group) > 1)
107- can_place = true;
108- delete_board(friendly_group);
109- }
110132
111- if(left == (game->black_turn ? WHITE : BLACK))
112- {
113- go_board* enemy_group = create_board(game->board->size);
114- find_group(game->board, enemy_group, y, x-1);
115- if(count_liberties(game->board, enemy_group) <= 1)
116- {
117- kill_group(game->board, enemy_group);
118- can_place = true;
119- }
120- delete_board(enemy_group);
121- } else if(left == EMPTY) {
133+ if(left == enemy && group_killable(game, y, x-1))
134+ can_place = true;
135+ else if(left == EMPTY)
136+ can_place = true;
137+ else if(up == friendly && group_attachable(game, y, x-1))
122138 can_place = true;
123- } else {
124- go_board* friendly_group = create_board(game->board->size);
125- find_group(game->board, friendly_group, y, x-1);
126- if(count_liberties(game->board, friendly_group) > 1)
127- can_place = true;
128- delete_board(friendly_group);
129- }
130139
131- if(down == (game->black_turn ? WHITE : BLACK))
132- {
133- go_board* enemy_group = create_board(game->board->size);
134- find_group(game->board, enemy_group, y+1, x);
135- if(count_liberties(game->board, enemy_group) <= 1)
136- {
137- kill_group(game->board, enemy_group);
138- can_place = true;
139- }
140- delete_board(enemy_group);
141- } else if(down == EMPTY) {
140+ if(down == enemy && group_killable(game, y+1, x))
141+ can_place = true;
142+ else if(down == EMPTY)
143+ can_place = true;
144+ else if(up == friendly && group_attachable(game, y+1, x))
142145 can_place = true;
143- } else {
144- go_board* friendly_group = create_board(game->board->size);
145- find_group(game->board, friendly_group, y+1, x);
146- if(count_liberties(game->board, friendly_group) > 1)
147- can_place = true;
148- delete_board(friendly_group);
149- }
150146
151- if(right == (game->black_turn ? WHITE : BLACK))
152- {
153- go_board* enemy_group = create_board(game->board->size);
154- find_group(game->board, enemy_group, y, x+1);
155- if(count_liberties(game->board, enemy_group) <= 1)
156- {
157- kill_group(game->board, enemy_group);
158- can_place = true;
159- }
160- delete_board(enemy_group);
161- } else if(right == EMPTY) {
147+ if(right == enemy && group_killable(game, y, x+1))
148+ can_place = true;
149+ else if(right == EMPTY)
150+ can_place = true;
151+ else if(up == friendly && group_attachable(game, y, x+1))
162152 can_place = true;
163- } else {
164- go_board* friendly_group = create_board(game->board->size);
165- find_group(game->board, friendly_group, y, x+1);
166- if(count_liberties(game->board, friendly_group) > 1)
167- can_place = true;
168- delete_board(friendly_group);
169- }
170153
171154 if(!can_place)
172155 return false;
@@ -176,7 +159,7 @@ bool play_at(game_state* game, unsigned int y, unsigned int x)
176159 return true;
177160 }
178161
179-char get_board_at(go_board* board, unsigned int y, unsigned int x)
162+go_symbol get_board_at(const go_board* board, go_coordinate y, go_coordinate x)
180163 {
181164 if(check_bounds(board, y, x))
182165 return board->field_array[y*board->size+x];
@@ -184,19 +167,19 @@ char get_board_at(go_board* board, unsigned int y, unsigned int x)
184167 return INVALID_FIELD;
185168 }
186169
187-void set_board_at(go_board* board, unsigned int y, unsigned int x, char item)
170+void set_board_at(go_board* board, go_coordinate y, go_coordinate x, go_symbol item)
188171 {
189172 if(check_bounds(board,y,x))
190173 board->field_array[y*board->size+x] = item;
191174 }
192175
193-void find_group(go_board* board, go_board* overlay, unsigned int y, unsigned int x)
176+void find_group(const go_board* board, go_board* overlay, go_coordinate y, go_coordinate x)
194177 {
195178 assert(board->size == overlay->size);
196179 if(check_bounds(board, y, x))
197180 {
198181 set_board_at(overlay, y, x, GROUP);
199- char field = get_board_at(board,y,x);
182+ go_symbol field = get_board_at(board,y,x);
200183
201184 if(get_board_at(board,y-1,x) == field && get_board_at(overlay,y-1,x) == EMPTY)
202185 find_group(board, overlay, y-1, x);
@@ -221,9 +204,9 @@ unsigned long count_liberties(go_board* board, go_board* overlay)
221204
222205 unsigned long liberties = 0;
223206
224- for(unsigned int y = 0; y < board->size; y++)
207+ for(go_coordinate y = 0; y < board->size; y++)
225208 {
226- for(unsigned int x = 0; x < board->size; x++)
209+ for(go_coordinate x = 0; x < board->size; x++)
227210 {
228211 if(get_board_at(overlay, y, x) == GROUP)
229212 {
Msimple-go.h
@@ -14,10 +14,13 @@
1414 #define INVALID_FIELD '\0'
1515 #define COUNTED '+'
1616
17+typedef unsigned int go_coordinate;
18+typedef char go_symbol;
19+
1720 typedef struct go_board
1821 {
19- char* field_array;
20- unsigned int size;
22+ go_symbol* field_array;
23+ go_coordinate size;
2124 } go_board;
2225
2326 typedef struct game_state
@@ -33,15 +36,17 @@ void delete_board(go_board* board);
3336 game_state* create_game(unsigned int size, float komi);
3437 void delete_game(game_state* game);
3538
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);
39+bool check_bounds(const go_board* board, unsigned int y, unsigned int x);
40+char get_board_at(const go_board* board, unsigned int y, unsigned int x);
3841 void set_board_at(go_board* board, unsigned int y, unsigned int x, char item);
3942
4043 void kill_group(go_board* board, go_board* overlay);
44+bool group_killable(game_state* game, unsigned int y, unsigned int x);
45+bool group_attachable(const game_state* game, unsigned int y, unsigned int x);
4146 bool play_at(game_state* game, unsigned int y, unsigned int x);
4247
4348 void print_board(go_board* board);
44-void find_group(go_board* board, go_board* overlay, unsigned int y, unsigned int x);
49+void find_group(const go_board* board, go_board* overlay, unsigned int y, unsigned int x);
4550 unsigned long count_liberties(go_board* board, go_board* overlay);
4651
4752
Msimple-gtp.c
@@ -48,6 +48,9 @@ char* handle_gtp_cmd(const char* msg, game_state* game)
4848 current = strtok(NULL, " ");
4949 }
5050
51+ if(arguments->length > 1)
52+ vector_remove(arguments,0,free);
53+
5154 char* (*func_ptr)(const char*) = cmd_error;
5255 const char* func_args = "unknown command";
5356
@@ -139,8 +142,7 @@ char* handle_gtp_cmd(const char* msg, game_state* game)
139142 }
140143
141144 free(command);
142- delete_vector(arguments, NULL);
143- free(arguments);
145+ delete_vector(arguments, free);
144146 free(tmp_msg);
145147
146148 return func_ptr(func_args);
Mtest.c
@@ -68,9 +68,10 @@ void test3(void)
6868
6969 char* ret =handle_gtp_cmd("play white a9", test_game);
7070 printf("%s\n", ret);
71+ free(ret);
7172 print_board(test_game->board);
7273
73- free(ret);
74+
7475 delete_game(test_game);
7576
7677 puts("test2 finished");