1 /*
2  * eval.h
3  *
4  * by Gary Wong <gary@cs.arizona.edu>, 1998-2001.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of version 3 or later of the GNU General Public License as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  * $Id: eval.h,v 1.198 2018/06/16 14:58:42 plm Exp $
20  */
21 
22 #ifndef EVAL_H
23 #define EVAL_H
24 
25 #include "dice.h"
26 #include "bearoff.h"
27 #include "neuralnet.h"
28 #include "cache.h"
29 
30 #define EXP_LOCK_FUN(ret, name, ...) \
31 	typedef ret (*f_##name)( __VA_ARGS__); \
32 	extern f_##name name; \
33 	extern ret name##NoLocking( __VA_ARGS__); \
34 	extern ret name##WithLocking( __VA_ARGS__)
35 
36 #define WEIGHTS_VERSION "1.00"
37 #define WEIGHTS_VERSION_BINARY 1.00f
38 #define WEIGHTS_MAGIC_BINARY 472.3782f
39 
40 #define NUM_OUTPUTS 5
41 #define NUM_CUBEFUL_OUTPUTS 4
42 #define NUM_ROLLOUT_OUTPUTS 7
43 
44 #define BETA_HIDDEN 0.1f
45 #define BETA_OUTPUT 1.0f
46 
47 #define OUTPUT_WIN 0
48 #define OUTPUT_WINGAMMON 1
49 #define OUTPUT_WINBACKGAMMON 2
50 #define OUTPUT_LOSEGAMMON 3
51 #define OUTPUT_LOSEBACKGAMMON 4
52 
53 #define OUTPUT_EQUITY 5         /* NB: neural nets do not output equity, only
54                                  * rollouts do. */
55 #define OUTPUT_CUBEFUL_EQUITY 6
56 
57 /* Cubeful evalutions */
58 typedef enum {
59     OUTPUT_OPTIMAL = 0,
60     OUTPUT_NODOUBLE,
61     OUTPUT_TAKE,
62     OUTPUT_DROP
63 } CubefulOutputs;
64 
65 /* A trivial upper bound on the number of (complete or incomplete)
66  * legal moves of a single roll: if all 15 chequers are spread out,
67  * then there are 18 C 4 + 17 C 3 + 16 C 2 + 15 C 1 = 3875
68  * combinations in which a roll of 11 could be played (up to 4 choices from
69  * 15 chequers, and a chequer may be chosen more than once).  The true
70  * bound will be lower than this (because there are only 26 points,
71  * some plays of 15 chequers must "overlap" and map to the same
72  * resulting position), but that would be more difficult to
73  * compute. */
74 #define MAX_INCOMPLETE_MOVES 3875
75 #define MAX_MOVES 3060
76 
77 typedef struct movefilter_s {
78     int Accept;                 /* always allow this many moves. 0 means don't use this */
79     /* level, since at least 1 is needed when used. */
80     int Extra;                  /* and add up to this many more... */
81     float Threshold;            /* ...if they are within this equity difference */
82 } movefilter;
83 
84 /* we'll have filters for 1..4 ply evaluation */
85 #define MAX_FILTER_PLIES	4
86 extern movefilter defaultFilters[MAX_FILTER_PLIES][MAX_FILTER_PLIES];
87 
88 typedef struct {
89     /* FIXME expand this... e.g. different settings for different position
90      * classes */
91     unsigned int fCubeful:1;    /* cubeful evaluation */
92     unsigned int nPlies:4;
93     unsigned int fUsePrune:1;
94     unsigned int fDeterministic:1;
95     unsigned int :25;		/* padding */
96     float rNoise;               /* standard deviation */
97 } evalcontext;
98 
99 /* identifies the format of evaluation info in .sgf files
100  * early (pre extending rollouts) had no version numbers
101  * extendable rollouts have a version number of 1
102  * with pruning nets, we have two possibilities - reduction could still
103  * be enabled (version = 2) or, given the speedup and performance
104  * improvements, I assume we will drop reduction entirely. (ver = 3 or more)
105  * When presented with an .sgf file, gnubg will attempt to work out what
106  * data is present in the file based on the version number
107  */
108 
109 #define SGF_FORMAT_VER 3
110 
111 typedef struct {
112     evalcontext aecCube[2], aecChequer[2];      /* evaluation parameters */
113     evalcontext aecCubeLate[2], aecChequerLate[2];      /* ... for later moves */
114     evalcontext aecCubeTrunc, aecChequerTrunc;  /* ... at truncation point */
115     movefilter aaamfChequer[2][MAX_FILTER_PLIES][MAX_FILTER_PLIES];
116     movefilter aaamfLate[2][MAX_FILTER_PLIES][MAX_FILTER_PLIES];
117 
118     unsigned int fCubeful:1;    /* Cubeful rollout */
119     unsigned int fVarRedn:1;    /* variance reduction */
120     unsigned int fInitial:1;    /* roll out as opening position */
121     unsigned int fRotate:1;     /* quasi-random dice */
122     unsigned int fTruncBearoff2:1;      /* cubeless rollout: trunc at BEAROFF2 */
123     unsigned int fTruncBearoffOS:1;     /* cubeless rollout: trunc at BEAROFF_OS */
124     unsigned int fLateEvals:1;  /* enable different evals for later moves */
125     unsigned int fDoTruncate:1; /* enable truncated rollouts */
126     unsigned int fStopOnSTD:1;  /* stop when std's are small enough */
127     unsigned int fStopOnJsd:1;
128     unsigned int fStopMoveOnJsd:1;      /* stop multi-line rollout when jsd
129                                          * is small enough */
130     unsigned short nTruncate;   /* truncation */
131     unsigned int nTrials;       /* number of rollouts */
132     unsigned short nLate;       /* switch evaluations on move nLate of game */
133     rng rngRollout;
134     unsigned long nSeed;
135     unsigned int nMinimumGames; /* always do at least this many */
136     float rStdLimit;            /* stop when std < this */
137     unsigned int nMinimumJsdGames;
138     float rJsdLimit;
139     unsigned int nGamesDone;
140     float rStoppedOnJSD;
141     int nSkip;
142 } rolloutcontext;
143 
144 typedef struct {
145     float rEquity;
146     float rJSD;
147     int nOrder;
148     int nRank;
149 } jsdinfo;
150 
151 typedef enum {
152     EVAL_NONE, EVAL_EVAL, EVAL_ROLLOUT
153 } evaltype;
154 
155 /* enumeration of variations of backgammon
156  * (starting position and/or special rules) */
157 
158 extern bgvariation bgvDefault;
159 
160 extern int anChequers[NUM_VARIATIONS];
161 extern const char *aszVariations[NUM_VARIATIONS];
162 extern const char *aszVariationCommands[NUM_VARIATIONS];
163 
164 /*
165  * Cubeinfo contains the information necessary for evaluation
166  * of a position.
167  * These structs are placed here so that the move struct can be defined
168  */
169 
170 typedef struct {
171     /*
172      * nCube: the current value of the cube,
173      * fCubeOwner: the owner of the cube,
174      * fMove: the player for which we are
175      *        calculating equity for,
176      * fCrawford, fJacoby, fBeavers: optional rules in effect,
177      * arGammonPrice: the gammon prices;
178      *   [ 0 ] = gammon price for player 0,
179      *   [ 1 ] = gammon price for player 1,
180      *   [ 2 ] = backgammon price for player 0,
181      *   [ 3 ] = backgammon price for player 1.
182      *
183      */
184     int nCube, fCubeOwner, fMove, nMatchTo, anScore[2], fCrawford, fJacoby, fBeavers;
185     float arGammonPrice[4];
186     bgvariation bgv;
187 } cubeinfo;
188 
189 typedef struct {
190     evaltype et;
191     evalcontext ec;
192     rolloutcontext rc;
193 } evalsetup;
194 
195 typedef enum {
196     DOUBLE_TAKE,
197     DOUBLE_PASS,
198     NODOUBLE_TAKE,
199     TOOGOOD_TAKE,
200     TOOGOOD_PASS,
201     DOUBLE_BEAVER,
202     NODOUBLE_BEAVER,
203     REDOUBLE_TAKE,
204     REDOUBLE_PASS,
205     NO_REDOUBLE_TAKE,
206     TOOGOODRE_TAKE,
207     TOOGOODRE_PASS,
208     NO_REDOUBLE_BEAVER,
209     NODOUBLE_DEADCUBE,          /* cube is dead (match play only) */
210     NO_REDOUBLE_DEADCUBE,       /* cube is dead (match play only) */
211     NOT_AVAILABLE,              /* Cube not available */
212     OPTIONAL_DOUBLE_TAKE,
213     OPTIONAL_REDOUBLE_TAKE,
214     OPTIONAL_DOUBLE_BEAVER,
215     OPTIONAL_DOUBLE_PASS,
216     OPTIONAL_REDOUBLE_PASS
217 } cubedecision;
218 
219 typedef enum {
220     DT_NORMAL,
221     DT_BEAVER,
222     DT_RACCOON,
223     NUM_DOUBLE_TYPES
224 } doubletype;
225 
226 /*
227  * TT_NA can happen if a single position was loaded from a sgf file.
228  * To check for beavers, use "> TT_NORMAL", not "!= TT_NORMAL".
229  */
230 typedef enum {
231     TT_NA,
232     TT_NORMAL,
233     TT_BEAVER
234 } taketype;
235 
236 extern const char *aszDoubleTypes[NUM_DOUBLE_TYPES];
237 
238 /*
239  * prefined settings
240  */
241 
242 #define NUM_SETTINGS            9
243 #define SETTINGS_4PLY           8
244 #define SETTINGS_GRANDMASTER    7
245 #define SETTINGS_SUPREMO        6
246 #define SETTINGS_WORLDCLASS     5
247 #define SETTINGS_EXPERT         4
248 #define SETTINGS_ADVANCED       3
249 #define SETTINGS_INTERMEDIATE   2
250 #define SETTINGS_NOVICE         1
251 #define SETTINGS_BEGINNER       0
252 
253 extern evalcontext aecSettings[NUM_SETTINGS];
254 extern evalcontext ecBasic;
255 extern int aiSettingsMoveFilter[NUM_SETTINGS];
256 extern const char *aszSettings[NUM_SETTINGS];
257 
258 #define NUM_MOVEFILTER_SETTINGS 5
259 
260 extern const char *aszMoveFilterSettings[NUM_MOVEFILTER_SETTINGS];
261 extern movefilter aaamfMoveFilterSettings[NUM_MOVEFILTER_SETTINGS][MAX_FILTER_PLIES][MAX_FILTER_PLIES];
262 
263 typedef enum {
264     CMARK_NONE,
265     CMARK_ROLLOUT
266 } CMark;
267 
268 typedef struct {
269     int anMove[8];
270     positionkey key;
271     unsigned int cMoves, cPips;
272     /* scores for this move */
273     float rScore, rScore2;
274     /* evaluation for this move */
275     float arEvalMove[NUM_ROLLOUT_OUTPUTS];
276     float arEvalStdDev[NUM_ROLLOUT_OUTPUTS];
277     evalsetup esMove;
278     CMark cmark;
279 } move;
280 
281 extern int fInterrupt;
282 extern cubeinfo ciCubeless;
283 extern const char *aszEvalType[(int) EVAL_ROLLOUT + 1];
284 
285 extern bearoffcontext *pbc1;
286 extern bearoffcontext *pbc2;
287 extern bearoffcontext *pbcOS;
288 extern bearoffcontext *pbcTS;
289 extern bearoffcontext *apbcHyper[3];
290 
291 typedef struct {
292     unsigned int cMoves;        /* and current move when building list */
293     unsigned int cMaxMoves, cMaxPips;
294     int iMoveBest;
295     float rBestScore;
296     move *amMoves;
297 } movelist;
298 
299 /* cube efficiencies */
300 
301 extern float rOSCubeX;
302 extern float rRaceFactorX;
303 extern float rRaceCoefficientX;
304 extern float rRaceMax;
305 extern float rRaceMin;
306 extern float rCrashedX;
307 extern float rContactX;
308 
309 /* position classes */
310 
311 typedef enum {
312     CLASS_OVER = 0,             /* Game already finished */
313     CLASS_HYPERGAMMON1,         /* hypergammon with 1 chequers */
314     CLASS_HYPERGAMMON2,         /* hypergammon with 2 chequers */
315     CLASS_HYPERGAMMON3,         /* hypergammon with 3 chequers */
316     CLASS_BEAROFF2,             /* Two-sided bearoff database (in memory) */
317     CLASS_BEAROFF_TS,           /* Two-sided bearoff database (on disk) */
318     CLASS_BEAROFF1,             /* One-sided bearoff database (in memory) */
319     CLASS_BEAROFF_OS,           /* One-sided bearoff database /on disk) */
320     CLASS_RACE,                 /* Race neural network */
321     CLASS_CRASHED,              /* Contact, one side has less than 7 active checkers */
322     CLASS_CONTACT               /* Contact neural network */
323 } positionclass;
324 
325 #define N_CLASSES (CLASS_CONTACT + 1)
326 
327 #define CLASS_PERFECT CLASS_BEAROFF_TS
328 #define CLASS_GOOD CLASS_BEAROFF_OS   /* Good enough to not need SanityCheck */
329 
330 typedef int (*classevalfunc) (const TanBoard anBoard, float arOutput[], const bgvariation bgv, NNState * nnStates);
331 
332 extern classevalfunc acef[N_CLASSES];
333 
334 /* Evaluation cache size is 2^SIZE entries */
335 #define CACHE_SIZE_DEFAULT 19
336 #define CACHE_SIZE_GUIMAX 23
337 
338 #define CFMONEY(arEquity,pci) \
339    ( ( (pci)->fCubeOwner == -1 ) ? arEquity[ 2 ] : \
340    ( ( (pci)->fCubeOwner == (pci)->fMove ) ? arEquity[ 1 ] : arEquity[ 3 ] ) )
341 
342 #define CFHYPER(arEquity,pci) \
343    ( ( (pci)->fCubeOwner == -1 ) ? \
344      ( ( (pci)->fJacoby ) ? arEquity[ 2 ] : arEquity[ 1 ] ) : \
345      ( ( (pci)->fCubeOwner == (pci)->fMove ) ? arEquity[ 0 ] : arEquity[ 3 ] ) )
346 
347 extern void EvalInitialise(char *szWeights, char *szWeightsBinary, int fNoBearoff, void (*pfProgress) (unsigned int));
348 
349 extern int EvalShutdown(void);
350 
351 extern void EvalStatus(char *szOutput);
352 
353 extern int EvalNewWeights(int nSize);
354 
355 extern int EvalSave(const char *szWeights);
356 
357 
358 EXP_LOCK_FUN(int, EvaluatePosition, NNState * nnStates, const TanBoard anBoard, float arOutput[],
359              cubeinfo * const pci, const evalcontext * pec);
360 
361 extern void
362  InvertEvaluationR(float ar[NUM_ROLLOUT_OUTPUTS], const cubeinfo * pci);
363 
364 extern void
365  InvertEvaluation(float ar[NUM_OUTPUTS]);
366 
367 EXP_LOCK_FUN(int, FindBestMove, int anMove[8], int nDice0, int nDice1,
368              TanBoard anBoard, const cubeinfo * pci, evalcontext * pec, movefilter aamf[MAX_FILTER_PLIES][MAX_FILTER_PLIES]);
369 
370 EXP_LOCK_FUN(int, FindnSaveBestMoves, movelist * pml,
371              int nDice0, int nDice1, const TanBoard anBoard,
372              positionkey * keyMove, const float rThr,
373              const cubeinfo * pci, const evalcontext * pec, movefilter aamf[MAX_FILTER_PLIES][MAX_FILTER_PLIES]);
374 
375 extern void
376  PipCount(const TanBoard anBoard, unsigned int anPips[2]);
377 
378 extern int
379  ThorpCount(const TanBoard anBoard, int *pnLeader, float *adjusted, int *pnTrailer);
380 
381 extern int
382  KeithCount(const TanBoard anBoard, int pn[2]);
383 
384 extern int
385  IsightCount(const TanBoard anBoard, int pn[2]);
386 
387 extern int
388  DumpPosition(const TanBoard anBoard, char *szOutput,
389              const evalcontext * pec, cubeinfo * pci, int fOutputMWC,
390              int fOutputWinPC, int fOutputInvert, const char *szMatchID);
391 
392 extern void
393  SwapSides(TanBoard anBoard);
394 
395 extern int
396  GameStatus(const TanBoard anBoard, const bgvariation bgv);
397 
398 extern void EvalCacheFlush(void);
399 extern int EvalCacheResize(unsigned int cNew);
400 extern int EvalCacheStats(unsigned int *pcUsed, unsigned int *pcLookup, unsigned int *pcHit);
401 extern double GetEvalCacheSize(void);
402 void SetEvalCacheSize(unsigned int size);
403 extern unsigned int GetEvalCacheEntries(void);
404 extern int GetCacheMB(int size);
405 
406 extern evalCache cEval;
407 extern evalCache cpEval;
408 extern unsigned int cCache;
409 
410 extern int
411  GenerateMoves(movelist * pml, const TanBoard anBoard, int n0, int n1, int fPartial);
412 
413 extern int ApplySubMove(TanBoard anBoard, const int iSrc, const int nRoll, const int fCheckLegal);
414 
415 extern int ApplyMove(TanBoard anBoard, const int anMove[8], const int fCheckLegal);
416 
417 extern positionclass ClassifyPosition(const TanBoard anBoard, const bgvariation bgv);
418 
419 /* internal use only */
420 extern void EvalRaceBG(const TanBoard anBoard, float arOutput[], const bgvariation bgv);
421 
422 extern float
423  Utility(float ar[NUM_OUTPUTS], const cubeinfo * pci);
424 
425 extern float
426  UtilityME(float ar[NUM_OUTPUTS], const cubeinfo * pci);
427 
428 extern int
429  SetCubeInfoMoney(cubeinfo * pci, const int nCube, const int fCubeOwner,
430                  const int fMove, const int fJacoby, const int fBeavers, const bgvariation bgv);
431 
432 extern int
433  SetCubeInfo(cubeinfo * pci, const int nCube, const int fCubeOwner,
434             const int fMove, const int nMatchTo, const int anScore[2],
435             const int fCrawford, const int fJacoby, const int fBeavers, const bgvariation bgv);
436 
437 extern void
438  swap_us(unsigned int *p0, unsigned int *p1);
439 
440 extern void
441  swap(int *p0, int *p1);
442 
443 extern void
444  SanityCheck(const TanBoard anBoard, float arOutput[]);
445 
446 extern int
447  EvalOver(const TanBoard anBoard, float arOutput[], const bgvariation bgv, NNState * nnStates);
448 
449 extern float
450  KleinmanCount(int nPipOnRoll, int nPipNotOnRoll);
451 
452 extern int
453  GetDPEq(int *pfCube, float *prDPEq, const cubeinfo * pci);
454 
455 extern float
456  mwc2eq(const float rMwc, const cubeinfo * pci);
457 
458 extern float
459  eq2mwc(const float rEq, const cubeinfo * pci);
460 
461 extern float
462  se_mwc2eq(const float rMwc, const cubeinfo * pci);
463 
464 extern float
465  se_eq2mwc(const float rEq, const cubeinfo * pci);
466 
467 extern char
468 *FormatEval(char *sz, evalsetup * pes);
469 
470 extern cubedecision FindCubeDecision(float arDouble[], float aarOutput[][NUM_ROLLOUT_OUTPUTS], const cubeinfo * pci);
471 
472 EXP_LOCK_FUN(int, GeneralCubeDecisionE, float aarOutput[2][NUM_ROLLOUT_OUTPUTS],
473              const TanBoard anBoard, cubeinfo * const pci, const evalcontext * pec, const evalsetup * pes);
474 
475 EXP_LOCK_FUN(int, GeneralEvaluationE, float arOutput[NUM_ROLLOUT_OUTPUTS],
476              const TanBoard anBoard, cubeinfo * const pci, const evalcontext * pec);
477 
478 extern int
479  cmp_evalsetup(const evalsetup * pes1, const evalsetup * pes2);
480 
481 extern int
482  cmp_evalcontext(const evalcontext * pec1, const evalcontext * pec2);
483 
484 extern char
485 *GetCubeRecommendation(const cubedecision cd);
486 
487 extern cubedecision
488 FindBestCubeDecision(float arDouble[], float aarOutput[2][NUM_ROLLOUT_OUTPUTS], const cubeinfo * pci);
489 
490 extern int
491  getCurrentGammonRates(float aarRates[2][2],
492                       float arOutput[], const TanBoard anBoard, cubeinfo * pci, const evalcontext * pec);
493 
494 extern void
495  getMoneyPoints(float aaarPoints[2][7][2], const int fJacoby, const int fBeavers, float aarRates[2][2]);
496 
497 extern void
498  getMatchPoints(float aaarPoints[2][4][2],
499                int afAutoRedouble[2], int afDead[2], const cubeinfo * pci, float aarRates[2][2]);
500 
501 extern void
502  getCubeDecisionOrdering(int aiOrder[3],
503                         float arDouble[4], float aarOutput[2][NUM_ROLLOUT_OUTPUTS], const cubeinfo * pci);
504 
505 extern float
506  getPercent(const cubedecision cd, const float arDouble[]);
507 
508 extern void
509  RefreshMoveList(movelist * pml, int *ai);
510 
511 EXP_LOCK_FUN(int, ScoreMove, NNState * nnStates, move * pm, const cubeinfo * pci, const evalcontext * pec, int nPlies);
512 
513 extern void
514  CopyMoveList(movelist * pmlDest, const movelist * pmlSrc);
515 
516 extern int
517  isCloseCubedecision(const float arDouble[]);
518 
519 extern int
520  isMissedDouble(float arDouble[], float aarOutput[2][NUM_ROLLOUT_OUTPUTS], const int fDouble, const cubeinfo * pci);
521 
522 extern unsigned int
523  locateMove(const TanBoard anBoard, const int anMove[8], const movelist * pml);
524 
525 extern int
526  equal_movefilter(const int i, const movefilter amf1[MAX_FILTER_PLIES], const movefilter amf2[MAX_FILTER_PLIES]);
527 
528 extern int
529  equal_movefilters(movefilter aamf1[MAX_FILTER_PLIES][MAX_FILTER_PLIES],
530                    movefilter aamf2[MAX_FILTER_PLIES][MAX_FILTER_PLIES]);
531 
532 extern doubletype DoubleType(const int fDoubled, const int fMove, const int fTurn);
533 
534 extern int
535  PerfectCubeful(bearoffcontext * pbc, const TanBoard anBoard, float arEquity[]);
536 
537 extern void
538  baseInputs(const TanBoard anBoard, float arInput[]);
539 
540 extern int CompareMoves(const move * pm0, const move * pm1);
541 extern float EvalEfficiency(const TanBoard anBoard, positionclass pc);
542 extern float Cl2CfMoney(float arOutput[NUM_OUTPUTS], cubeinfo * pci, float rCubeX);
543 extern float Cl2CfMatch(float arOutput[NUM_OUTPUTS], cubeinfo * pci, float rCubeX);
544 extern float Noise(const evalcontext * pec, const TanBoard anBoard, int iOutput);
545 extern int EvalKey(const evalcontext * pec, const int nPlies, const cubeinfo * pci, int fCubefulEquity);
546 extern void MakeCubePos(const cubeinfo aciCubePos[], const int cci, const int fTop, cubeinfo aci[], const int fInvert);
547 extern void GetECF3(float arCubeful[], int cci, float arCf[], cubeinfo aci[]);
548 extern int EvaluatePerfectCubeful(const TanBoard anBoard, float arEquity[], const bgvariation bgv);
549 
550 extern neuralnet nnContact, nnRace, nnCrashed;
551 extern neuralnet nnpContact, nnpRace, nnpCrashed;
552 
553 #endif
554