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