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 @@
# Binaries
test
#cutils files
cutils.h
cutils_endian.h
dyn_string.h
libcutils.so
vector.h
#build directories
subprojects/cutils
build/
include/cutils
# Prerequisites
*.d
DMakefile-3
@@ -1,3 +0,0 @@
all:
gcc -L./ -lcutils -O0 -g test.c simple-go.c simple-gtp.c -o test -std=c11 \
-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 @@
#define WHITE 'w'
#define EMPTY '.'
#define GROUP '#'
#define INVALID_FIELD '\0'
#define NO_FIELD '\0'
#define COUNTED '+'
typedef unsigned int go_coordinate;
@@ -43,9 +43,10 @@ void set_board_at(go_board* board, go_coordinate y, go_coordinate x, char item);
void kill_group(go_board* board, go_board* overlay);
bool group_killable(game_state* game, go_coordinate y, go_coordinate x);
bool group_attachable(const game_state* game, go_coordinate y, go_coordinate x);
bool play_at(game_state* game, go_coordinate y, go_coordinate x);
bool play_at(game_state* game, go_coordinate y, go_coordinate x, go_symbol color);
void print_board(go_board* board);
char* board_to_string(go_board* board);
void find_group(const go_board* board, go_board* overlay, go_coordinate y, go_coordinate x);
unsigned long count_liberties(go_board* board, go_board* overlay);
Rinclude/simple-go/simple-gtp.h← simple-gtp.h
@@ -5,8 +5,8 @@
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "simple-go.h"
#include "cutils.h"
#include <simple-go/simple-go.h>
#include <cutils/cutils.h>
char* handle_gtp_cmd(const char* msg, game_state* game);
Ameson.build
@@ -0,0 +1,10 @@
project('simple-go', 'c')
CFLAGS = ['-std=c11', '-fstrict-aliasing', '-Wall', '-Wpedantic', '-Wextra']
cutils_sp = subproject('cutils')
dep = cutils_sp.get_variable('cutils_dep')
subdir('include')
subdir('src')
Drun.sh-2
@@ -1,2 +0,0 @@
#!/bin/bash
LD_LIBRARY_PATH=. ./test
Asrc/meson.build
@@ -0,0 +1,6 @@
cutils_sp = subproject('cutils')
dep = cutils_sp.get_variable('cutils_dep')
src = ['simple-go.c', 'simple-gtp.c']
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 @@
#include "simple-go.h"
#include <simple-go/simple-go.h>
go_board* create_board(go_coordinate size)
{
@@ -70,6 +70,49 @@ void print_board(go_board* board)
}
}
char* board_to_string(go_board* board)
{
size_t str_size = (board->size*2+6)*(board->size+2)+2;
char* ret = calloc(str_size+1,1);
unsigned int index = 0;
unsigned int board_index = 0;
ret[index++] = '\n';
for(unsigned int i = 0; i < board->size+2; i++)
{
if(i == 0 || i == board->size+1)
{
ret[index++] = ' ';
ret[index++] = ' ';
ret[index++] = ' ';
char current_char = 'A';
for(unsigned int j = 0; j < board->size; j++)
{
ret[index++] = (char)(current_char == 'I' ? current_char++, current_char++ : current_char++);
ret[index++] = ' ';
}
ret[index++] = ' ';
ret[index++] = ' ';
} else {
index += (unsigned int)sprintf(ret+index, "%2u", (unsigned int)(board->size+1-i));
ret[index++] = ' ';
for(unsigned int j = 0; j < board->size; j++)
{
ret[index++] = board->field_array[board_index++];
ret[index++] = ' ';
}
index += (unsigned int)sprintf(ret+index, "%-2u", (unsigned int)(board->size+1-i));
}
ret[index++] = '\n';
}
return ret;
}
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)
}
}
bool play_at(game_state* game, go_coordinate y, go_coordinate x)
bool play_at(game_state* game, go_coordinate y, go_coordinate x, go_symbol color)
{
//check out-of-bounds
if(!check_bounds(game->board, y, x))
@@ -113,13 +156,13 @@ bool play_at(game_state* game, go_coordinate y, go_coordinate x)
bool can_place = false;
go_symbol enemy = game->black_turn ? WHITE : BLACK;
go_symbol friendly = game->black_turn ? BLACK : WHITE;
go_symbol enemy = color == NO_FIELD ? (game->black_turn ? WHITE : BLACK) : (color == BLACK ? WHITE : BLACK);
go_symbol friendly = color == NO_FIELD ? (game->black_turn ? BLACK : WHITE) : (color == BLACK ? BLACK : WHITE);
go_symbol up = y == 0 ? INVALID_FIELD : get_board_at(game->board, y-1, x);
go_symbol left = x == 0 ? INVALID_FIELD : get_board_at(game->board, y, x-1);
go_symbol down = y == game->board->size-1 ? INVALID_FIELD : get_board_at(game->board, y+1, x);
go_symbol right = x == game->board->size-1 ? INVALID_FIELD : get_board_at(game->board, y, x+1);
go_symbol up = y == 0 ? NO_FIELD : get_board_at(game->board, y-1, x);
go_symbol left = x == 0 ? NO_FIELD : get_board_at(game->board, y, x-1);
go_symbol down = y == game->board->size-1 ? NO_FIELD : get_board_at(game->board, y+1, x);
go_symbol right = x == game->board->size-1 ? NO_FIELD : get_board_at(game->board, y, x+1);
//first check for group to kill, then for empty field, and last for group with liberties
@@ -154,7 +197,7 @@ bool play_at(game_state* game, go_coordinate y, go_coordinate x)
if(!can_place)
return false;
set_board_at(game->board, y, x, game->black_turn ? BLACK : WHITE);
set_board_at(game->board, y, x, friendly);
game->black_turn = !game->black_turn;
return true;
}
@@ -164,7 +207,7 @@ go_symbol get_board_at(const go_board* board, go_coordinate y, go_coordinate x)
if(check_bounds(board, y, x))
return board->field_array[y*board->size+x];
else
return INVALID_FIELD;
return NO_FIELD;
}
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 @@
#include "simple-gtp.h"
#include <simple-go/simple-gtp.h>
typedef struct msg_formatted
{
@@ -156,18 +156,18 @@ char* handle_gtp_cmd(const char* msg, game_state* game)
game->board = create_board(size);
} else if(strcmp(command, "play") == 0) {
char* color = malloc(6);
char y;
int x;
char x;
int y;
if((arguments->length == 2 || arguments->length == 3) && //either its "a 10" or "a10"
(snprintf(color, 6, "%s", (char*)vector_at(arguments,0)) > 0) && //"white" and "black" are only 6 chars
(strcmp(color, "white") == 0 || strcmp(color, "black") == 0) && // check color
(sscanf(vector_at(arguments,1), "%c", &y) > 0) && //get vertical coordinate
((unsigned char)(tolower(y) - 'a') < game->board->size) && // check range
((sscanf((char*)vector_at(arguments,1)+1, "%d", &x) > 0) || // get horizontal coordinate if no space between
((arguments->length == 3) && (sscanf((char*)vector_at(arguments,2), "%d", &x) > 0))) && // get horizontal coordinate if space between
((unsigned int)x <= game->board->size) && ((unsigned int)x > 0)) // check range
(sscanf(vector_at(arguments,1), "%c", &x) > 0) && // get horizontal coordinate
((unsigned char)(tolower(x) - 'a') < game->board->size) && // check range
((sscanf((char*)vector_at(arguments,1)+1, "%d", &y) > 0) || // get vertical coordinate if no space between
((arguments->length == 3) && (sscanf((char*)vector_at(arguments,2), "%d", &y) > 0))) && // get vertical coordinate if space between
((unsigned int)y <= game->board->size) && y > 0) // check range
{
if(play_at(game, (unsigned char)(y-'a'), (unsigned int)x-1))
if(play_at(game, game->board->size-(unsigned int)y, (unsigned char)(x-'a'), strcmp(color, "white") == 0 ? WHITE : BLACK))
{
func_ptr = cmd_success;
func_args = "";
@@ -183,14 +183,21 @@ char* handle_gtp_cmd(const char* msg, game_state* game)
} else if(strcmp(command, "genmove") == 0) {
func_ptr = cmd_success;
func_args = "";
unsigned int y;
unsigned int x;
go_coordinate y;
go_coordinate x;
do
{
y = (unsigned int)rand() % game->board->size;
x = (unsigned int)rand() % game->board->size;
} while(!play_at(game, y, x));
y = (go_coordinate)rand() % game->board->size;
x = (go_coordinate)rand() % game->board->size;
} while(!play_at(game, y, x, NO_FIELD));
} else if(strcmp(command, "showboard") == 0) {
char* board = board_to_string(game->board);
free(command);
delete_vector(arguments, free);
char* tmp = cmd_success(board, id);
free(board);
return tmp;
}
free(command);
Rsrc/test.c← test.c
@@ -1,5 +1,5 @@
#include "simple-go.h"
#include "simple-gtp.h"
#include <simple-go/simple-go.h>
#include <simple-go/simple-gtp.h>
void test1(void)
{
@@ -44,16 +44,16 @@ void test2(void)
set_board_at(test_board, 2, 1, WHITE);
set_board_at(test_board, 1, 1, BLACK);
play_at(test_game, 2, 2);
play_at(test_game, 2, 2, NO_FIELD);
print_board(test_game->board);
set_board_at(test_board, 2, 1, EMPTY);
play_at(test_game, 2, 2);
play_at(test_game, 2, 2, NO_FIELD);
print_board(test_game->board);
play_at(test_game, 2, 1);
play_at(test_game, 2, 1, NO_FIELD);
print_board(test_game->board);
delete_game(test_game);
@@ -66,11 +66,15 @@ void test3(void)
game_state* test_game = create_game(11, 0);
char* ret =handle_gtp_cmd("play white a 10", test_game);
char* ret =handle_gtp_cmd("play white a 11", test_game);
printf("%s\n", ret);
free(ret);
print_board(test_game->board);
ret =handle_gtp_cmd("showboard", test_game);
printf("%s\n", ret);
free(ret);
ret =handle_gtp_cmd("version", test_game);
printf("%s\n", ret);
free(ret);
@@ -126,7 +130,7 @@ void test4(void)
set_board_at(test_board, 2, 5, WHITE);
set_board_at(test_board, 1, 4, WHITE);
set_board_at(test_board, 3, 4, BLACK);
play_at(test_game, 2,4);
play_at(test_game, 2,4, NO_FIELD);
print_board(test_game->board);
@@ -137,9 +141,17 @@ void test4(void)
int main(int argc, char** argv)
{
game_state* game = create_game(19, 0);
test1();
test2();
test3();
test4();
set_board_at(game->board, 2, 3, WHITE);
char* ret = handle_gtp_cmd("showboard", game);
printf("%s", ret);
free(ret);
delete_game(game);
}