Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Organization

The code is organized in a shared codebase that consists of this folder plus
mcts/, with header files in inc/. A number of entry points complement this for
their respective purposes. Each entry point has it's own folder (main, ob_gen,
etc. All file I/O is made from the data/ directory by default.
All "public" (read: non C static) functions have a short header description too.

The project consists of several executable files:

matilda - the main program, used for playing and analyzing Go. If you are
unsure, use this program. It can also be used to benchmark the system.

test - use for running unitary tests; often with a debug compilation or
profiling activated.

generate_ob - used for creating Fuego-style opening books from collections of
game records in SGF format.

learn_best_plays - used to evaluate and save the best play to a number of
positions extracted from collections of game records. These can be used to as a
replacement to opening books, or for brute forcing.

learn_pat_weights - used to learn the weights to be associated with 3x3
patterns.

gen_zobrist_table - used to generate a vector of values suitable to be used as a
codification table for Zobrist hashing.

twogtp - used to pit one GTP-speaking program against another, for testing, benchmarking, etc.



Configuration

Most things can be either set via command line flags, GTP commands or C
preprocessor definitions. The most common symbols that are defined in
preprocessor definitions are found in the file inc/config.h

The file inc/config.h is special. It must not include anything and should be
included prior to everything else for the potential to enable or disable
assertions and other debugging checks.



Project conventions/guidelines

1.  All code must be strict C99 code, with a preference for ANSI C
    compatibility.
2.  All code must compile both in GCC and clang.
3.  There can be as many lines in between the code as necessary for clarity.
4.  The scope of everything should be as limited as possible (types, functions);
    each piece of code should import and be dependent on the rest as little as
    possible.
5.  There shouldn't be a "God import", where a single file imports all header
    files. Note this is not the case of inc/config.h because it doesn't import.
6.  The structure of a C file is (in order): short description of its function,
    config.h include, C library includes, 3rd party includes, project includes,
    public symbol declaration, extern symbol declaration, static symbol
    declaration and finally function declarations. Static symbol declarations
    may also be kept close to functions that will use them for clarity.
7.  The size of a function should not be cut short just for brevity. It is
    clearer to read a long function than ten small ones spread around. Having
    said that, functions that are not performance critical should attempt to be
    small and delegate responsabilities.
8.  Avoid recursion except if it would make the code very obfuscated otherwise.
9.  Prefer statically allocated resources in initialization time; instead of
    using mallocs. Do not allow a single memory leak -- no byte left behind.
10. All public functions must have their declaration complemented with a
    commentary that exlains its purpose, parameters and returned values.
11. Anything out of the ordinary should be asserted/tested in either runtime or
    through unitary testing.
12. All code should be as small and functional as possible.
13. All code should be maintained; if one software piece is no longer useful it
    should be removed. This may mean moving it to the old/ folder if it may be
    useful for future reference.
14. Symbol naming convention: all symbols should be named lower case with
    underscore separators. Symbols that aren't meant to be used should start
    with two underscores and end in one. Symbols that are static and variations
    of other (public) symbols, should start with one underscore.
15. Preprocessor: names should be upper case. Private names must start with two
    underscores and end in one. Preprocessor instructions are never indented.
16. Avoid asserts unless for critical, unfathomable, exceptions. Not finding a
    file in the file system or running out of memory are not unfathomable.
    Expected problems should be tested and dealt with programmatically. Also do
    not use asserts specifically for the functions 'close' and 'fclose'.
17. Pointer dereferencing and primitive operations can receive unnecessary
    parenthesis if it makes their meaning clearer.
18. If the program may fail on user error, it should fail with a bang. This
    means logging the situation and closing. Silent failing only makes it harder
    to understand how to fix the issue.
19. Use const and restrict keywords where appropriate. Things should be very
    strongly static typed and array passed as parameters should not be
    referenced.
20. Don't use volatile keyword, enumerables or unions if avoidable.
21. Text in the program text interface can be adjusted to a terminal assumed to
    contain 80 character lines.
22. Coding style is 1TBS with 4-space indentation. Line length is not
    restricted but please be reasonable. Pointers are typed appart from symbols.
    Function declarations should have parameter lists NT kernel style, except if
    they have no parameters. An if that follows an else can omit the braces and
    indentation. Comments always use /* */ instead of //. The case keywords of
    switch statements is aligned with the switch keyword.
    Following are several examples.

#define IMPORTANT_STUFF 1
#define IMPORTANT_STUFF_ALIGNED  3
#define IMPORTANT_STUFF_ALIGNED2 4
#define __DONT_LOOK_ 2

static void long_method_definition(
    int v2,
    char var1,
    char var2,
    char * pt1,
    char * pt2,
    char * argv1[static 10] /* the last comma is optional */
);

static void _main() {
    /* example of function without parameters */
    fprintf(stderr, "Example of string literal that is very long. Notice how
the string is not cut short but the next parameters are aligned in the next line.",
        BOARD_SIZ);
}

int main(
    int argc,
    char * argv[]
) {
    /* I am an ANSI comment */
    char * s = do_something(argc > 1 ? argv[0] : NULL);
    if (s == NULL) {
        return -1;
    }

    if (strcmp(s, "test") == 0) {
        printf("goodbye world\n");
#if IMPORTANT_STUFF
        printf("cruel world\n");
#endif
        return 1;
    } else if (1) {
        printf("hello world\n");
        _main();
        return 2;
    }
}