“She knew the true shape of the world. All else was shadow and the sound of distant drums.”
/tei
exposes a minimalistic tei
interface, that can be compiled with make tei
(resulting in the bin /bin/tei
). Supported commands are:
option | arguments | description | aliases |
---|---|---|---|
help |
|||
quit |
quit the io loop | q |
|
print |
[tps\|pretty] |
if tps print the position encoded as a tps string.if pretty or no arguments pretty-print the whole position. |
p |
ninja |
print the formatted ptn.ninja url pointing to the current position | ||
new |
<size> |
set the current position as a new position of size size |
|
tps |
<tps> |
parse the given tps string and into the current position | |
move |
[<move 1> ... <move n>] |
apply a series of ptn-encoded moves at the current position | |
search |
[spread\|placement\|all] |
search legal moves in the current position. no arguments defaults to all |
|
perft |
<depth> |
perft | |
perftd |
<depth> |
divide perft | |
random |
[-n <N>] [-m <N>] [-M <N>] |
generate random non-terminated positions, starting from the current one-n <N> : amount of position to generate-m <N> : min randomization depth-M <N> : max randomization depth |
tei
now replace the old scripts
, as it can be used like
echo "random -n 10" | tei
tei <<< "move a1 b2" <<< "print tps"
xdg-open $(tei <<< "tps 1,1,12,x2/x5/x5/x5/2,x4 1 4" <<< "ninja")
[!NOTE]
here-strings
(<<<
) des not chain in defaultbash
, a shell likezsh
is required insthead.
Everything that is not data
is regarded as log
and printed to a different stream (by default stderr
), so that it can be discarded with 2>/dev/null
.
taklib
, located in /lib
, is meant as a fast (TODO: bench) header-only c
library for handling a tak game, used as a base for the other tools implemented in auri
. Implemented features are:
For more informations regarding the positon encoding and the moves generation strategy see the docs.
taklib
taklib
is a set of header-only c files. If you are confused by this definition, this should help. Altough kinda controversial, this choice makes a lot of things easier, and as a user the only difference is that, before importing, it's necesary to define the TAKLIB_IMPLEMENTATION
macro:
// first we define the macro
#define TAKLIB_IMPLEMENTATION
// then we include the headers we need
#include "tak.h"
#include "ptn.h"
a position
is the representation of a state of the board, like a "screenshot" of a moment in a game where a move has just been made.
// this creates a new, empty, position
tak_position pos = tak_newposition(5);
There are two lookup tables that are required to run most of the functionalities of the library: tak_slt
and tak_zobrist_data
. The first contains all the possible spread configurations and is used to search for spreads, while the second one contains the randomly generated bitstrings needed fot zobrist hashing.
tak_slt slt = tak_slt_load();
tak_zobrist_data zd = tak_zd_load();
A tak move
is handled by taklib
as a combination of anonymous unions and structs that allows to have the same struct (tak_move
) represent both a placement and a spread, and the field tak_move.type
is set to TAK_SPREAD
of TAK_PLACEMENT
to indicate it's type.
Moves can be created manually, although not so convenient, or can be searched for
// create a buffer to store found moves
tak_move buffer[TAK_MAX_MOVES];
// search all legal moves in a given position
int n = tak_search(buffer, &pos, &slt); // returns the amount of
// moves found
Spreads and placements can also be searched individually with tak_search_spreads
and tak_search_placements
.
[!NOTE] By default
taklib
assumes swap opening. If we desire to remove this, we can set theTAKLIB_SWAP
macro to0
(or a different number to modify the number of plies for which the rule apply, default2
) both in code#define TAKLIB_SWAP 0 #include "tak.h" // no swap now
or at compilation time with
-DTAKLIB_SWAP=0
(on GCC).
To apply a move simply
tak_position before = tan_newposition(5);
tak_position after = tak_do(before, a_move, &zd);
and the type-specifics functions are tak_do_spread
and tak_do_placement
. As the tak_do*
functions copy the "before" position insthead of modifying it no tak_undo*
is required. This proved to be faster with optimized GCC builds than passing references and undoing.
tps
stringstps
string are handled using the ptn.h
module. We can parse a string into a position
char tps_string[] = "x3,12,2S/x,22S,22C,11,21/121,212,12,1121C,1212S/21S,1,21,211S,12S/x,21S,2,x2 1 26";
tak_position pos = tps_parse(tps_string, TPS_STD, &zd);
The &zd
parameter is a reference to the zobrist lookup table we made earlier, while TPS_STD
is the standard tps lexicon. A lexicon
, both in tps
and ptn
, is a set of declarations that defines the characters used to represent stuff in the strings.
We can also encode a previously created position as a new tps string
// create a new position, loading it from a tps string
tak_position pos = tps_parse("x3/x3/x3 1 1");
// and encode it into a new string
char tps[TPS_MAX_LENGTH];
int n = tps_encode(tps, pos, TPS_STD); // returns the amout of charachters
// written into `tps, included '\0'
assert(strcmp(tps, "x3/x3/x3 1 1") == 0) // true
[!WARNING] Loading both
tps
andptn
strings does not imply a legality check (yet), so trying to load a faulty string can lead to a variety of side effects, ranging from strangely-formed position to segfaults.
ptn
movesptn
-encoded moves can be handled in a similar manner as tps
strings
// load
tak_move move = ptn_parse("4d2>112*");
// and encode
char ptn[PTN_MAX_MOVE_LENGTH];
int n = ptn_encode(ptn, move, /*the size of the board*/ 5, PTN_STD),
Note that loading a ptn move is unrelated from any position, so before applying a loaded move to a position without assertions may be risky.
There is a utility function that allows to parse a position from a list of ptn moves
char *moves[] = {"a1", "a2", "b1<"};
tak_position p = ptn_apply(tak_newposition(3), moves, 3, PTN_STD, &zd);
// -> p = 21,x/x3/x3 2 2