switched to meson build system, fixed function signatures, fixed play_at() bug for testing wrong directions, added ids for gtp return strings, refactored handel_gtp_command(), added protocol tests. Note to self: never switch build systems AND to a huge commit together again
M.gitignore
| @@ -1,12 +1,8 @@ | |||
|---|---|---|---|
| 1 | - | # Binaries | |
| 2 | - | test | |
| 3 | - | ||
| 4 | - | #cutils files | |
| 5 | - | cutils.h | |
| 6 | - | cutils_endian.h | |
| 7 | - | dyn_string.h | |
| 8 | - | libcutils.so | |
| 9 | - | vector.h | |
| 1 | + | #build directories | |
| 2 | + | subprojects/cutils | |
| 3 | + | build/ | |
| 4 | + | include/cutils | |
| 5 | + | ||
| 10 | 6 | ||
| 11 | 7 | # Prerequisites | |
| 12 | 8 | *.d | |
DMakefile-3
| @@ -1,3 +0,0 @@ | |||
|---|---|---|---|
| 1 | - | all: | |
| 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 \ | |
Rinclude/simple-go/simple-go.h← simple-go.h
| @@ -11,7 +11,7 @@ | |||
|---|---|---|---|
| 11 | 11 | #define WHITE 'w' | |
| 12 | 12 | #define EMPTY '.' | |
| 13 | 13 | #define GROUP '#' | |
| 14 | - | #define INVALID_FIELD '\0' | |
| 14 | + | #define NO_FIELD '\0' | |
| 15 | 15 | #define COUNTED '+' | |
| 16 | 16 | ||
| 17 | 17 | typedef unsigned int go_coordinate; | |
| @@ -43,9 +43,10 @@ void set_board_at(go_board* board, go_coordinate y, go_coordinate x, char item); | |||
|---|---|---|---|
| 43 | 43 | void kill_group(go_board* board, go_board* overlay); | |
| 44 | 44 | bool group_killable(game_state* game, go_coordinate y, go_coordinate x); | |
| 45 | 45 | bool group_attachable(const game_state* game, go_coordinate y, go_coordinate x); | |
| 46 | - | bool play_at(game_state* game, go_coordinate y, go_coordinate x); | |
| 46 | + | bool play_at(game_state* game, go_coordinate y, go_coordinate x, go_symbol color); | |
| 47 | 47 | ||
| 48 | 48 | void print_board(go_board* board); | |
| 49 | + | char* board_to_string(go_board* board); | |
| 49 | 50 | void find_group(const go_board* board, go_board* overlay, go_coordinate y, go_coordinate x); | |
| 50 | 51 | unsigned long count_liberties(go_board* board, go_board* overlay); | |
| 51 | 52 | ||
Rinclude/simple-go/simple-gtp.h← simple-gtp.h
| @@ -5,8 +5,8 @@ | |||
|---|---|---|---|
| 5 | 5 | #include <stdio.h> | |
| 6 | 6 | #include <string.h> | |
| 7 | 7 | #include <ctype.h> | |
| 8 | - | #include "simple-go.h" | |
| 9 | - | #include "cutils.h" | |
| 8 | + | #include <simple-go/simple-go.h> | |
| 9 | + | #include <cutils/cutils.h> | |
| 10 | 10 | ||
| 11 | 11 | char* handle_gtp_cmd(const char* msg, game_state* game); | |
| 12 | 12 | ||
Ameson.build
| @@ -0,0 +1,10 @@ | |||
|---|---|---|---|
| 1 | + | project('simple-go', 'c') | |
| 2 | + | ||
| 3 | + | CFLAGS = ['-std=c11', '-fstrict-aliasing', '-Wall', '-Wpedantic', '-Wextra'] | |
| 4 | + | ||
| 5 | + | cutils_sp = subproject('cutils') | |
| 6 | + | dep = cutils_sp.get_variable('cutils_dep') | |
| 7 | + | ||
| 8 | + | subdir('include') | |
| 9 | + | subdir('src') | |
| 10 | + | ||
Drun.sh-2
| @@ -1,2 +0,0 @@ | |||
|---|---|---|---|
| 1 | - | #!/bin/bash | |
| 2 | - | LD_LIBRARY_PATH=. ./test | |
Asrc/meson.build
| @@ -0,0 +1,6 @@ | |||
|---|---|---|---|
| 1 | + | cutils_sp = subproject('cutils') | |
| 2 | + | dep = cutils_sp.get_variable('cutils_dep') | |
| 3 | + | ||
| 4 | + | src = ['simple-go.c', 'simple-gtp.c'] | |
| 5 | + | ||
| 6 | + | executable('test_go', src + ['test.c'], include_directories : inc, dependencies : dep, c_args: CFLAGS ) | |
Rsrc/simple-go.c← simple-go.c
| @@ -1,4 +1,4 @@ | |||
|---|---|---|---|
| 1 | - | #include "simple-go.h" | |
| 1 | + | #include <simple-go/simple-go.h> | |
| 2 | 2 | ||
| 3 | 3 | go_board* create_board(go_coordinate size) | |
| 4 | 4 | { | |
| @@ -70,6 +70,49 @@ void print_board(go_board* board) | |||
|---|---|---|---|
| 70 | 70 | } | |
| 71 | 71 | } | |
| 72 | 72 | ||
| 73 | + | char* board_to_string(go_board* board) | |
| 74 | + | { | |
| 75 | + | size_t str_size = (board->size*2+6)*(board->size+2)+2; | |
| 76 | + | char* ret = calloc(str_size+1,1); | |
| 77 | + | unsigned int index = 0; | |
| 78 | + | unsigned int board_index = 0; | |
| 79 | + | ret[index++] = '\n'; | |
| 80 | + | ||
| 81 | + | for(unsigned int i = 0; i < board->size+2; i++) | |
| 82 | + | { | |
| 83 | + | if(i == 0 || i == board->size+1) | |
| 84 | + | { | |
| 85 | + | ret[index++] = ' '; | |
| 86 | + | ret[index++] = ' '; | |
| 87 | + | ret[index++] = ' '; | |
| 88 | + | ||
| 89 | + | char current_char = 'A'; | |
| 90 | + | for(unsigned int j = 0; j < board->size; j++) | |
| 91 | + | { | |
| 92 | + | ret[index++] = (char)(current_char == 'I' ? current_char++, current_char++ : current_char++); | |
| 93 | + | ret[index++] = ' '; | |
| 94 | + | } | |
| 95 | + | ||
| 96 | + | ret[index++] = ' '; | |
| 97 | + | ret[index++] = ' '; | |
| 98 | + | } else { | |
| 99 | + | index += (unsigned int)sprintf(ret+index, "%2u", (unsigned int)(board->size+1-i)); | |
| 100 | + | ret[index++] = ' '; | |
| 101 | + | for(unsigned int j = 0; j < board->size; j++) | |
| 102 | + | { | |
| 103 | + | ret[index++] = board->field_array[board_index++]; | |
| 104 | + | ret[index++] = ' '; | |
| 105 | + | } | |
| 106 | + | index += (unsigned int)sprintf(ret+index, "%-2u", (unsigned int)(board->size+1-i)); | |
| 107 | + | } | |
| 108 | + | ret[index++] = '\n'; | |
| 109 | + | } | |
| 110 | + | ||
| 111 | + | ||
| 112 | + | ||
| 113 | + | return ret; | |
| 114 | + | ||
| 115 | + | } | |
| 73 | 116 | ||
| 74 | 117 | ||
| 75 | 118 | bool group_attachable(const game_state* game, go_coordinate y, go_coordinate x) | |
| @@ -101,7 +144,7 @@ bool group_killable(game_state* game, go_coordinate y, go_coordinate x) | |||
|---|---|---|---|
| 101 | 144 | } | |
| 102 | 145 | } | |
| 103 | 146 | ||
| 104 | - | bool play_at(game_state* game, go_coordinate y, go_coordinate x) | |
| 147 | + | bool play_at(game_state* game, go_coordinate y, go_coordinate x, go_symbol color) | |
| 105 | 148 | { | |
| 106 | 149 | //check out-of-bounds | |
| 107 | 150 | if(!check_bounds(game->board, y, x)) | |
| @@ -113,13 +156,13 @@ bool play_at(game_state* game, go_coordinate y, go_coordinate x) | |||
|---|---|---|---|
| 113 | 156 | ||
| 114 | 157 | bool can_place = false; | |
| 115 | 158 | ||
| 116 | - | go_symbol enemy = game->black_turn ? WHITE : BLACK; | |
| 117 | - | go_symbol friendly = game->black_turn ? BLACK : WHITE; | |
| 159 | + | go_symbol enemy = color == NO_FIELD ? (game->black_turn ? WHITE : BLACK) : (color == BLACK ? WHITE : BLACK); | |
| 160 | + | go_symbol friendly = color == NO_FIELD ? (game->black_turn ? BLACK : WHITE) : (color == BLACK ? BLACK : WHITE); | |
| 118 | 161 | ||
| 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); | |
| 162 | + | go_symbol up = y == 0 ? NO_FIELD : get_board_at(game->board, y-1, x); | |
| 163 | + | go_symbol left = x == 0 ? NO_FIELD : get_board_at(game->board, y, x-1); | |
| 164 | + | go_symbol down = y == game->board->size-1 ? NO_FIELD : get_board_at(game->board, y+1, x); | |
| 165 | + | go_symbol right = x == game->board->size-1 ? NO_FIELD : get_board_at(game->board, y, x+1); | |
| 123 | 166 | ||
| 124 | 167 | //first check for group to kill, then for empty field, and last for group with liberties | |
| 125 | 168 | ||
| @@ -154,7 +197,7 @@ bool play_at(game_state* game, go_coordinate y, go_coordinate x) | |||
|---|---|---|---|
| 154 | 197 | if(!can_place) | |
| 155 | 198 | return false; | |
| 156 | 199 | ||
| 157 | - | set_board_at(game->board, y, x, game->black_turn ? BLACK : WHITE); | |
| 200 | + | set_board_at(game->board, y, x, friendly); | |
| 158 | 201 | game->black_turn = !game->black_turn; | |
| 159 | 202 | return true; | |
| 160 | 203 | } | |
| @@ -164,7 +207,7 @@ go_symbol get_board_at(const go_board* board, go_coordinate y, go_coordinate x) | |||
|---|---|---|---|
| 164 | 207 | if(check_bounds(board, y, x)) | |
| 165 | 208 | return board->field_array[y*board->size+x]; | |
| 166 | 209 | else | |
| 167 | - | return INVALID_FIELD; | |
| 210 | + | return NO_FIELD; | |
| 168 | 211 | } | |
| 169 | 212 | ||
| 170 | 213 | void set_board_at(go_board* board, go_coordinate y, go_coordinate x, go_symbol item) | |
Rsrc/simple-gtp.c← simple-gtp.c
| @@ -1,4 +1,4 @@ | |||
|---|---|---|---|
| 1 | - | #include "simple-gtp.h" | |
| 1 | + | #include <simple-go/simple-gtp.h> | |
| 2 | 2 | ||
| 3 | 3 | typedef struct msg_formatted | |
| 4 | 4 | { | |
| @@ -156,18 +156,18 @@ char* handle_gtp_cmd(const char* msg, game_state* game) | |||
|---|---|---|---|
| 156 | 156 | game->board = create_board(size); | |
| 157 | 157 | } else if(strcmp(command, "play") == 0) { | |
| 158 | 158 | char* color = malloc(6); | |
| 159 | - | char y; | |
| 160 | - | int x; | |
| 159 | + | char x; | |
| 160 | + | int y; | |
| 161 | 161 | if((arguments->length == 2 || arguments->length == 3) && //either its "a 10" or "a10" | |
| 162 | 162 | (snprintf(color, 6, "%s", (char*)vector_at(arguments,0)) > 0) && //"white" and "black" are only 6 chars | |
| 163 | 163 | (strcmp(color, "white") == 0 || strcmp(color, "black") == 0) && // check color | |
| 164 | - | (sscanf(vector_at(arguments,1), "%c", &y) > 0) && //get vertical coordinate | |
| 165 | - | ((unsigned char)(tolower(y) - 'a') < game->board->size) && // check range | |
| 166 | - | ((sscanf((char*)vector_at(arguments,1)+1, "%d", &x) > 0) || // get horizontal coordinate if no space between | |
| 167 | - | ((arguments->length == 3) && (sscanf((char*)vector_at(arguments,2), "%d", &x) > 0))) && // get horizontal coordinate if space between | |
| 168 | - | ((unsigned int)x <= game->board->size) && ((unsigned int)x > 0)) // check range | |
| 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 | 169 | { | |
| 170 | - | if(play_at(game, (unsigned char)(y-'a'), (unsigned int)x-1)) | |
| 170 | + | if(play_at(game, game->board->size-(unsigned int)y, (unsigned char)(x-'a'), strcmp(color, "white") == 0 ? WHITE : BLACK)) | |
| 171 | 171 | { | |
| 172 | 172 | func_ptr = cmd_success; | |
| 173 | 173 | func_args = ""; | |
| @@ -183,14 +183,21 @@ char* handle_gtp_cmd(const char* msg, game_state* game) | |||
|---|---|---|---|
| 183 | 183 | } else if(strcmp(command, "genmove") == 0) { | |
| 184 | 184 | func_ptr = cmd_success; | |
| 185 | 185 | func_args = ""; | |
| 186 | - | unsigned int y; | |
| 187 | - | unsigned int x; | |
| 186 | + | go_coordinate y; | |
| 187 | + | go_coordinate x; | |
| 188 | 188 | do | |
| 189 | 189 | { | |
| 190 | - | y = (unsigned int)rand() % game->board->size; | |
| 191 | - | x = (unsigned int)rand() % game->board->size; | |
| 192 | - | } while(!play_at(game, y, x)); | |
| 193 | - | ||
| 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)); | |
| 193 | + | } 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; | |
| 194 | 201 | } | |
| 195 | 202 | ||
| 196 | 203 | free(command); | |
Rsrc/test.c← test.c
| @@ -1,5 +1,5 @@ | |||
|---|---|---|---|
| 1 | - | #include "simple-go.h" | |
| 2 | - | #include "simple-gtp.h" | |
| 1 | + | #include <simple-go/simple-go.h> | |
| 2 | + | #include <simple-go/simple-gtp.h> | |
| 3 | 3 | ||
| 4 | 4 | void test1(void) | |
| 5 | 5 | { | |
| @@ -44,16 +44,16 @@ void test2(void) | |||
|---|---|---|---|
| 44 | 44 | set_board_at(test_board, 2, 1, WHITE); | |
| 45 | 45 | set_board_at(test_board, 1, 1, BLACK); | |
| 46 | 46 | ||
| 47 | - | play_at(test_game, 2, 2); | |
| 47 | + | play_at(test_game, 2, 2, NO_FIELD); | |
| 48 | 48 | print_board(test_game->board); | |
| 49 | 49 | ||
| 50 | 50 | set_board_at(test_board, 2, 1, EMPTY); | |
| 51 | 51 | ||
| 52 | - | play_at(test_game, 2, 2); | |
| 52 | + | play_at(test_game, 2, 2, NO_FIELD); | |
| 53 | 53 | print_board(test_game->board); | |
| 54 | 54 | ||
| 55 | 55 | ||
| 56 | - | play_at(test_game, 2, 1); | |
| 56 | + | play_at(test_game, 2, 1, NO_FIELD); | |
| 57 | 57 | print_board(test_game->board); | |
| 58 | 58 | ||
| 59 | 59 | delete_game(test_game); | |
| @@ -66,11 +66,15 @@ void test3(void) | |||
|---|---|---|---|
| 66 | 66 | ||
| 67 | 67 | game_state* test_game = create_game(11, 0); | |
| 68 | 68 | ||
| 69 | - | char* ret =handle_gtp_cmd("play white a 10", test_game); | |
| 69 | + | char* ret =handle_gtp_cmd("play white a 11", test_game); | |
| 70 | 70 | printf("%s\n", ret); | |
| 71 | 71 | free(ret); | |
| 72 | 72 | print_board(test_game->board); | |
| 73 | 73 | ||
| 74 | + | ret =handle_gtp_cmd("showboard", test_game); | |
| 75 | + | printf("%s\n", ret); | |
| 76 | + | free(ret); | |
| 77 | + | ||
| 74 | 78 | ret =handle_gtp_cmd("version", test_game); | |
| 75 | 79 | printf("%s\n", ret); | |
| 76 | 80 | free(ret); | |
| @@ -126,7 +130,7 @@ void test4(void) | |||
|---|---|---|---|
| 126 | 130 | set_board_at(test_board, 2, 5, WHITE); | |
| 127 | 131 | set_board_at(test_board, 1, 4, WHITE); | |
| 128 | 132 | set_board_at(test_board, 3, 4, BLACK); | |
| 129 | - | play_at(test_game, 2,4); | |
| 133 | + | play_at(test_game, 2,4, NO_FIELD); | |
| 130 | 134 | ||
| 131 | 135 | print_board(test_game->board); | |
| 132 | 136 | ||
| @@ -137,9 +141,17 @@ void test4(void) | |||
|---|---|---|---|
| 137 | 141 | ||
| 138 | 142 | int main(int argc, char** argv) | |
| 139 | 143 | { | |
| 144 | + | game_state* game = create_game(19, 0); | |
| 140 | 145 | test1(); | |
| 141 | 146 | test2(); | |
| 142 | 147 | test3(); | |
| 143 | 148 | 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); | |
| 144 | 156 | ||
| 145 | 157 | } | |