/*
 
  Copyright (c) 2011-2013 Ronald de Man
 
*/
 
 
 
#ifndef RTB_CORE_HPP_
 
#define RTB_CORE_HPP_
 
 
 
#ifndef _WIN32
 
#define SEP_CHAR ':'
 
#define FD int
 
#define FD_ERR -1
 
#else
 
#include <windows.h>
 
#define SEP_CHAR ';'
 
#define FD HANDLE
 
#define FD_ERR INVALID_HANDLE_VALUE
 
#endif
 
 
 
#include <stdint.h>
 
 
 
#define WDLSUFFIX ".rtbw"
 
#define DTZSUFFIX ".rtbz"
 
#define TBPIECES 6
 
 
 
#define WDL_MAGIC 0x5d23e871
 
#define DTZ_MAGIC 0xa50c66d7
 
 
 
#define TBHASHBITS 11
 
 
 
using ubyte = unsigned char;
 
using ushort = unsigned short;
 
 
 
struct TBHashEntry;
 
 
 
using base_t = uint64_t;
 
 
 
struct PairsData {
 
    char *indextable;
 
    ushort *sizetable;
 
    ubyte *data;
 
    ushort *offset;
 
    ubyte *symlen;
 
    ubyte *sympat;
 
    int blocksize;
 
    int idxbits;
 
    int min_len;
 
    base_t base[1]; // C++ complains about base[]...
 
};
 
 
 
struct TBEntry {
 
    char *data;
 
    uint64_t key;
 
    uint64_t mapping;
 
    std::atomic<ubyte> ready;
 
    ubyte num;
 
    ubyte symmetric;
 
    ubyte has_pawns;
 
}
 
#ifndef _MSC_VER
 
__attribute__((__may_alias__)) // Pierre-Marie Baty -- this is not supported by MSVC
 
#endif // !_MSC_VER
 
;
 
 
 
struct TBEntry_piece {
 
    char *data;
 
    uint64_t key;
 
    uint64_t mapping;
 
    std::atomic<ubyte> ready;
 
    ubyte num;
 
    ubyte symmetric;
 
    ubyte has_pawns;
 
    ubyte enc_type;
 
    struct PairsData *precomp[2];
 
    int factor[2][TBPIECES];
 
    ubyte pieces[2][TBPIECES];
 
    ubyte norm[2][TBPIECES];
 
};
 
 
 
struct TBEntry_pawn {
 
    char *data;
 
    uint64_t key;
 
    uint64_t mapping;
 
    std::atomic<ubyte> ready;
 
    ubyte num;
 
    ubyte symmetric;
 
    ubyte has_pawns;
 
    ubyte pawns[2];
 
    struct {
 
        struct PairsData *precomp[2];
 
        int factor[2][TBPIECES];
 
        ubyte pieces[2][TBPIECES];
 
        ubyte norm[2][TBPIECES];
 
    } file[4];
 
};
 
 
 
struct DTZEntry_piece {
 
    char *data;
 
    uint64_t key;
 
    uint64_t mapping;
 
    std::atomic<ubyte> ready;
 
    ubyte num;
 
    ubyte symmetric;
 
    ubyte has_pawns;
 
    ubyte enc_type;
 
    struct PairsData *precomp;
 
    int factor[TBPIECES];
 
    ubyte pieces[TBPIECES];
 
    ubyte norm[TBPIECES];
 
    ubyte flags; // accurate, mapped, side
 
    ushort map_idx[4];
 
    ubyte *map;
 
};
 
 
 
struct DTZEntry_pawn {
 
    char *data;
 
    uint64_t key;
 
    uint64_t mapping;
 
    std::atomic<ubyte> ready;
 
    ubyte num;
 
    ubyte symmetric;
 
    ubyte has_pawns;
 
    ubyte pawns[2];
 
    struct {
 
        struct PairsData *precomp;
 
        int factor[TBPIECES];
 
        ubyte pieces[TBPIECES];
 
        ubyte norm[TBPIECES];
 
    } file[4];
 
    ubyte flags[4];
 
    ushort map_idx[4][4];
 
    ubyte *map;
 
};
 
 
 
struct TBHashEntry {
 
    uint64_t key;
 
    struct TBEntry *ptr;
 
};
 
 
 
struct DTZTableEntry {
 
    uint64_t key1;
 
    uint64_t key2;
 
    std::atomic<TBEntry*> entry;
 
};
 
 
 
#endif