-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathtablebase.h
206 lines (182 loc) · 5.86 KB
/
tablebase.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/*-
* Copyright (c) 2016--2017 Robert Clausecker. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef TABLEBASE_H
#define TABLEBASE_H
/*
* This header contains functionality to generate and probe the
* comprehensive tablebase. This header contains a generic interface
* that isn't specific to a particular tablebase implementation, so
* the implementation can be swapped with a more suitable one as needed.
*/
#include <stdio.h>
#include "rules.h"
/*
* A tablebase entry. The number has the following meaning:
* - a positive number indicates a winning position with the number
* itself being the distance to ascension/lion capture in double
* moves. If ascension/lion capture is possible in this move, the
* number is 1.
* - zero indicates a draw.
* - a negative number indicates a lost position with the number
* itself being the distance to ascension/lion capture in double
* moves. If the opponent can capture your lion or ascend in his
* next move regardless of what you do, the number is 1.
*/
typedef int tb_entry;
/*
* The tablebase itself. This structure is opaque.
*/
struct tablebase;
/*
* This structure is used by analyze_position() to store the analysis
* of the moves from a position. entry indicates what the value of the
* current position would have been if move was the best move, value
* indicates the move value as seen by the engine at the selected
* strength. 0 <= value < 1 holds.
*/
struct analysis {
struct move move;
tb_entry entry;
double value;
};
/*
* This structure is used to seed the random number generator for the
* ai. Internally, the POSIX rand48 random number generator is used
* with this structure forming a thin wrapper over it.
*/
struct seed {
unsigned short xsubi[3];
};
enum {
/*
* The maximum number of threads allowed for generate_tablebase.
* This limit is arbitrary and can be increased if desired. The
* intent is to avoid crashing people's computers if they
* accidentally try to run gentb with 1000 threads.
*/
#ifdef NO_ATOMICS
GENTB_MAX_THREADS = 1,
#else
GENTB_MAX_THREADS = 64,
#endif
/*
* The last parameter to ai_move() indicates the ai strength,
* which should be an integer between 0 and MAX_STRENGTH. This
* limit has been set with some safety margin such that no
* floating point overflow happens during computation.
*/
MAX_STRENGTH = 700,
};
/* tablebase functionality */
extern struct tablebase *generate_tablebase(int);
extern struct tablebase *read_tablebase(FILE*);
extern tb_entry lookup_position(const struct tablebase*, const struct position*);
extern int write_tablebase(FILE*, const struct tablebase*);
extern int validate_tablebase(const struct tablebase*);
extern void free_tablebase(struct tablebase*);
/* ai functionality */
extern void ai_seed(struct seed*);
extern struct move ai_move(const struct tablebase*, const struct position*,
struct seed*, double);
extern size_t analyze_position(struct analysis[MAX_MOVES],
const struct tablebase*, const struct position*, double);
/* auxillary functionality */
static inline int is_win(tb_entry);
static inline int is_draw(tb_entry);
static inline int is_loss(tb_entry);
static inline int get_dtm(tb_entry);
static inline tb_entry next_dtm(tb_entry);
static inline tb_entry prev_dtm(tb_entry);
static inline int wdl_compare(tb_entry, tb_entry);
/* implementations of inline functions */
static inline int
is_win(tb_entry e)
{
return (e > 0);
}
static inline int
is_draw(tb_entry e)
{
return (e == 0);
}
static inline int
is_loss(tb_entry e)
{
return (e < 0);
}
/*
* Return the distance to mate in half moves. If e is a draw, the
* result is unspecified.
*/
static inline int
get_dtm(tb_entry e)
{
if (is_win(e))
return (2 * e - 1);
else
return (- 2 * e);
}
/*
* Return the tb_entry that results when playing the best move from a
* position with value e. If e indicates an immediate win, the result
* is undefined.
*/
static inline tb_entry
next_dtm(tb_entry e)
{
if (e > 0)
return (1 - e);
else /* e <= 0 */
return (-e);
}
/*
* Return the tb_entry from which we came when the best move led to this
* position.
*/
static inline
tb_entry
prev_dtm(tb_entry e)
{
if (e < 0)
return (1 - e);
else /* e >= 0 */
return (-e);
}
/*
* Order e and f by how good they are. Return a negative, zero, or
* positive value if e indicates a worse, equal, or better position than
* f.
*/
static inline int
wdl_compare(tb_entry e, tb_entry f)
{
if (is_loss(f))
return (is_loss(e) ? f - e : 1);
else if (is_draw(f))
return (e);
else /* is_win(f) */
return (is_win(e) ? f - e : -1);
}
#endif /* TABLEBASE_H */