aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortslil <tslil@posteo.de>2021-01-08 17:37:13 -0500
committertslil <tslil@posteo.de>2026-08-28 19:37:41 +0100
commit84d17dd73a8ef43ef9e284c4455f79f67f7bd98d (patch)
tree157ad18698970d888e91b588ea5c1a8aae77ba71
parente8315ed893157a87c8f2c3935667ffcc97b2c95e (diff)
Fixed a small bug in PTN parsing, other stuff
-rwxr-xr-xextract.sh61
-rw-r--r--include/tak.c15
-rw-r--r--src/ctaklm.c69
-rw-r--r--src/pptdb.c65
4 files changed, 144 insertions, 66 deletions
diff --git a/extract.sh b/extract.sh
index a48e5ab..77c0ddc 100755
--- a/extract.sh
+++ b/extract.sh
@@ -3,48 +3,47 @@
db_file=games_anon.db
query() {
- echo "SELECT $1 FROM games WHERE (size == $2) \
-and ((result == 'R-0') or (result == '0-R'));"
-# and (result != '1-0') and (result != '0-1') and (result != '0-0')\
-# and (result != '1/2-1/2');"
+ query="(size == $1) and (result != '1-0') and (result != '0-1') and (result != '0-0')"
+ selct=""
+ # for player in rabbitboy84 fwwwwibib archvenison Simmon AaaarghBot; do
+ for player in; do
+ selct="$selct(player_black == '$player') or (player_white == '$player') or "
+ done;
+ if [ -n "$selct" ]; then
+ query="$query and (${selct:0:-4})"
+ fi
+ echo "SELECT $2 FROM games WHERE $query;"
}
extract() {
+ size="$1"
+ things="$2"
if [ ! -f "data/$db_file" ]; then
wget "https://www.playtak.com/games_anon.db" -O "data/$db_file"
fi
- for size in 5; do
- echo Extracing games of size "$size"...
- sqlite3 "data/$db_file" "$(query $1 $size)" | shuf > "data/playtak-$size"
- done
+ echo Extracing games of size "$size"...
+ sqlite3 "data/$db_file" "$(query $size $things)" | shuf > "data/playtak-$size"
}
process() {
- num_games=$1
- echo -e "Beginning to process data\n"
- for i in 5; do
- echo "Size $i..."
- ./pptdb "$i" "data/playtak-$i" > "data/check-$i"
- tail -n21 "data/check-$i"
- echo -e "\tStripping overflows and illegal games..."
- grep -Fvxf "data/check-$i" "data/playtak-$i" > "data/good-playtak-$i"
- echo -e "\tChoosing $num_games from what remains ..."
- shuf -n $num_games "data/good-playtak-$i" > "data/smalltak-$i"
- echo -en "\tGenerating training data... "
- ./pptdb "$i" "data/smalltak-$i" generate
- echo -e "\tWrote $(wc -l data/training-$i.csv | cut -d\ -f1) samples. Shuffling these..."
- tail -n+2 "data/training-$i.csv" | shuf > "data/shuf-$i.csv"
- head -n 1 "data/training-$i.csv" | cat "data/shuf-$i.csv" > "data/smalltrain-$i.csv"
- rm "data/shuf-$i.csv"
- mv "data/smalltrain-5.csv" "data/training-5.csv "
- echo -e "\n\tDone! Sample training data in data/training-$i.csv"
- done
+ size=$1
+ num_games=$2
+ ./pptdb "$size" "data/playtak-$size" > "data/check-$size"
+ tail -n22 "data/check-$size"
+ echo -e "\tStripping overflows and illegal games..."
+ grep -Fvxf "data/check-$size" "data/playtak-$size" > "data/good-playtak-$size"
+ echo -e "\tChoosing $num_games from what remains ..."
+ shuf -n $num_games "data/good-playtak-$size" > "data/smalltak-$size"
+ echo -en "\tGenerating training data... "
+ ./pptdb "$size" "data/smalltak-$size" generate
+ echo -e "\n\tDone! Wrote $(wc -l data/training-$size.csv | cut -d\ -f1) samples to data/training-$size.csv."
}
-if [ ! -f "data/playtak-5" ]; then
- extract notation,result
-fi
make pptdb
-process 20000
+for size in 5 6; do
+ extract $size notation,result
+ process $size 20000
+ echo
+done
diff --git a/include/tak.c b/include/tak.c
index 1d29694..bb06a16 100644
--- a/include/tak.c
+++ b/include/tak.c
@@ -319,10 +319,11 @@ check_win(void) {
} else {
return WIN_ROAD_BLACK;
}
- } else {
+ } else if (rw == WIN_ROAD_WHITE) {
return rw;
}
+ // Do we do a flat count?
int8_t total = 0, board_full = 1;
for (uint8_t k = 0; k < NUM_SQUARES; k++) {
if (COUNT_AT(k) == 0) {
@@ -331,14 +332,14 @@ check_win(void) {
total += ((colours[k] & 1) == C_BLACK) ? +1 : -1 ;
}
}
-
- // Do we do a flat count?
if (black_count == 0 || white_count == 0 || board_full) {
// Decide based on count
if (total > 0) return WIN_FLAT_BLACK;
else if (total < 0) return WIN_FLAT_WHITE;
else return WIN_DRAW;
}
+
+ return 0xFF;
}
// ===================================================================
// PTN place parser
@@ -424,7 +425,7 @@ parse_move(const uint8_t board_size, char *ptn,
// assume n = 1
ptn++;
if (*ptn == 0) {
- *out_steps = picked_up;
+ *out_steps = 1;
out_drops[0] = picked_up;
return PTN_VALID;
}
@@ -556,7 +557,11 @@ do_ptn(char *ptn) {
// more conservative here :)
if (ply >= board_size) {
won = check_win();
- if (won < 0xFF) return GAME_END;
+ if (won < 0xFF) {
+ // Winning move, but no need to update current colour
+ ply++;
+ return GAME_END;
+ }
}
// Only step if the game isn't over yet
next_ply();
diff --git a/src/ctaklm.c b/src/ctaklm.c
index 9d369f8..3d4310c 100644
--- a/src/ctaklm.c
+++ b/src/ctaklm.c
@@ -190,16 +190,17 @@ end_game(char *line, char *win) {
putchar('\n');
}
-static void
+static int
handle_turn(char *line) {
// Track win state
uint8_t new_win = (won == 0xFF);
switch (do_ptn(line)) {
// Errors
- case PTN_INVALID: { puts("Invalid PTN."); break; }
- case ACT_ILLEGAL: { puts("Illegal action."); break; }
+ case PTN_INVALID: { puts("Invalid PTN."); return -1; break; }
+ case ACT_ILLEGAL: { puts("Illegal action."); return -1; break; }
case ACT_OVERFLOW: {
puts("Move would cause internal overflow, select another.");
+ return -1;
break;
}
// Game has ended
@@ -216,6 +217,7 @@ handle_turn(char *line) {
}
}
puts("Game over, enter `new' to play again.");
+ if (! new_win) return -1;
break;
}
// Valid, append to game log
@@ -227,6 +229,8 @@ handle_turn(char *line) {
break;
}
}
+
+ return 0;
}
static void
@@ -238,6 +242,59 @@ new_game(uint8_t size) {
gamelog[0] = 0;
}
+static int
+load_ptn(const char* fn) {
+ FILE *fh = NULL;
+
+ fh = fopen(fn, "r");
+ if (fh == NULL) return EXIT_FAILURE;
+
+ int space1, space2;
+ enum E_RESULT r;
+
+ ssize_t read;
+ size_t alloc_size;
+ char *line = NULL;
+ while ((read = getline(&line, &alloc_size, fh)) != -1) {
+ if (read && line[0] <= '9' && line[0] >= '0') {
+ // Trim trailing \n
+ line[read-1] = 0;
+ // Find first separator
+ space1 = 0;
+ while (space1 < read && line[space1++] != ' ');
+ // If still on line
+ if (space1 < read) {
+ // Find next separator or end of line, either way mark the split
+ space2 = space1;
+ while (space2 < read && line[space2] != ' ') space2++;
+ line[space2] = 0;
+ // Try the first piece we found
+ r = handle_turn(line+space1);
+ if (r) {
+ printf("Error on: %s\n", line+space1);
+ break;
+ }
+ // If there's a second piece, try it
+ if (space2 + 1 < read) {
+ r = handle_turn(line+space2+1);
+ if (r) {
+ printf("Error on: %s", line+space2+1);
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ }
+ }
+
+ if (line) free(line);
+ fclose(fh);
+
+
+ return EXIT_SUCCESS;
+}
+
int
main(int argc, char **argv) {
(void)(argc);
@@ -255,6 +312,12 @@ main(int argc, char **argv) {
print_info();
} else if (!strncmp(line,"log",3)) {
puts(gamelog);
+ } else if (!strncmp(line,"load",4)) {
+ if (strnlen(line,6) >= 6) {
+ load_ptn(line+5);
+ } else {
+ puts("Usage: load <file.ptn>.");
+ }
} else if (!strncmp(line,"auto",4)) {
if (!strncmp(line,"auto board",10)) {
auto_board = ~auto_board;
diff --git a/src/pptdb.c b/src/pptdb.c
index 92155b5..7179ab0 100644
--- a/src/pptdb.c
+++ b/src/pptdb.c
@@ -17,11 +17,11 @@ write_input(void) {
/* fprintf(training_fh,"%d,",current_colour == C_BLACK); */
// Two numbers for flats remaining
- /* fprintf(training_fh,"%.6f,%.6f,", */
- /* (float)(white_count & 127)/max_flats, */
- /* (float)(black_count & 127)/max_flats); */
- // Two data points for each square
- /* float t; uint16_t mask; */
+ /*
+ * fprintf(training_fh,"%.6f,%.6f,",
+ * (float)(white_count & 127)/max_flats,
+ * (float)(black_count & 127)/max_flats);
+ */
float val;
uint16_t mask = 1;
@@ -48,21 +48,22 @@ write_input(void) {
mask <<= 1;
}
+
/*
- float t;
- for (int k = 0; k < board_size * board_size; k++) {
- // stacks encoded as balanced ternary
- const int h = COUNT_AT(k);
- t = 0;
- mask = 1<<h;
- for (int j = 1; j < h; j++) {
- t += (colours[k] & mask) ? +1 : -1;
- t /= 3.0;
- mask >>=1;
- }
- fprintf(training_fh,"%.8f,",2*t);
- }
- */
+ * float t;
+ * for (int k = 0; k < board_size * board_size; k++) {
+ * // stacks encoded as balanced ternary
+ * const int h = COUNT_AT(k);
+ * t = 0;
+ * mask = 1<<h;
+ * for (int j = 1; j < h; j++) {
+ * t += (colours[k] & mask) ? +1 : -1;
+ * t /= 3.0;
+ * mask >>=1;
+ * }
+ * fprintf(training_fh,"%.8f,",2*t);
+ * }
+ */
}
@@ -141,7 +142,8 @@ main(int argc, char **argv) {
enum E_RESULT r;
enum WIN_TYPE win;
uint32_t games = 0, overflow=0, illegal = 0;
- uint32_t road_wins=0, flat_wins=0, road_turns=0, flat_turns=0;
+ uint32_t road_wins=0, flat_wins=0, road_turns=0, flat_turns=0,
+ white_wins = 0, black_wins = 0;
for (int k = 0; k < 16; k++) heights[k] = 0;
@@ -171,10 +173,10 @@ main(int argc, char **argv) {
}
/*
- for (int k = 0; k < size*size; k++) {
- fprintf(training_fh,"\"BT %d\",",k);
- }
- */
+ * for (int k = 0; k < size*size; k++) {
+ * fprintf(training_fh,"\"BT %d\",",k);
+ * }
+ */
fputs("\"White win\",\"Black win\"\n",training_fh);
} else generate=0;
@@ -206,6 +208,10 @@ main(int argc, char **argv) {
road_wins++;
road_turns += ply/2+1;
}
+ if (win == WIN_FLAT_BLACK || win == WIN_ROAD_BLACK)
+ black_wins++;
+ else if (win == WIN_FLAT_WHITE || win == WIN_ROAD_WHITE)
+ white_wins++;
}
}
games++;
@@ -219,9 +225,14 @@ main(int argc, char **argv) {
printf("Read %d games\n",games);
if (generate==0) {
- printf("Illegals: %d\nOverflows: %d\nRoad wins: %d\nFlat wins: %d\n\
-Average turns to road win: %.3f\nAverage turns to flat win: %f\n",
- illegal,overflow, road_wins, flat_wins,
+ printf("Illegals: %d\nOverflows: %d\n\
+Black wins: %.3f%%\n\
+Road wins: %d\nFlat wins: %d\n\
+Average turns to road win: %.3f\n\
+Average turns to flat win: %f\n",
+ illegal, overflow,
+ (double)black_wins / (double)(black_wins+white_wins) * 100,
+ road_wins, flat_wins,
(double)(road_turns)/(double)(road_wins),
(double)(flat_turns)/(double)(flat_wins));
for (int k = 2; k < 16; k++) {