static void TextPrintCubeAnalysisTable(GString * gsz, float aarOutput[2][NUM_ROLLOUT_OUTPUTS], float aarStdDev[2][NUM_ROLLOUT_OUTPUTS], int UNUSED(fPlayer), const evalsetup * pes, const cubeinfo * pci, int fDouble, int fTake, skilltype stDouble, skilltype stTake) { int fActual, fClose, fMissed; int fDisplay; float arDouble[4]; /* check if cube analysis should be printed */ if (pes->et == EVAL_NONE) return; /* no evaluation */ FindCubeDecision(arDouble, aarOutput, pci); fActual = fDouble; fClose = isCloseCubedecision(arDouble); fMissed = isMissedDouble(arDouble, aarOutput, fDouble, pci); fDisplay = (fActual && exsExport.afCubeDisplay[EXPORT_CUBE_ACTUAL]) || (fClose && exsExport.afCubeDisplay[EXPORT_CUBE_CLOSE]) || (fMissed && exsExport.afCubeDisplay[EXPORT_CUBE_MISSED]) || (exsExport.afCubeDisplay[stDouble]) || (exsExport.afCubeDisplay[stTake]); if (!fDisplay) return; g_string_append(gsz, OutputCubeAnalysisFull(aarOutput, aarStdDev, pes, pci, fDouble, fTake, stDouble, stTake)); }
extern char * OutputCubeAnalysis(float aarOutput[2][NUM_ROLLOUT_OUTPUTS], float aarStdDev[2][NUM_ROLLOUT_OUTPUTS], const evalsetup * pes, const cubeinfo * pci) { static char sz[4096]; int i; float arDouble[4]; const char *aszCube[] = { NULL, N_("No double"), N_("Double, take"), N_("Double, pass") }; int ai[3]; cubedecision cd; float r; FindCubeDecision(arDouble, aarOutput, pci); /* header */ sprintf(sz, "\n%s\n", _("Cube analysis")); /* ply & cubeless equity */ switch (pes->et) { case EVAL_NONE: strcat(sz, _("n/a")); break; case EVAL_EVAL: sprintf(strchr(sz, 0), "%u-%s", pes->ec.nPlies, _("ply")); break; case EVAL_ROLLOUT: strcat(sz, _("Rollout")); break; } if (pci->nMatchTo) sprintf(strchr(sz, 0), " %s %s (%s: %s)\n", (!pci->nMatchTo || (pci->nMatchTo && !fOutputMWC)) ? _("cubeless equity") : _("cubeless MWC"), OutputEquity(aarOutput[0][OUTPUT_EQUITY], pci, TRUE), _("Money"), OutputMoneyEquity(aarOutput[0], TRUE)); else sprintf(strchr(sz, 0), " %s %s\n", _("cubeless equity"), OutputMoneyEquity(aarOutput[0], TRUE)); /* Output percentags for evaluations */ if (exsExport.fCubeDetailProb && pes->et == EVAL_EVAL) { strcat(sz, " "); strcat(sz, OutputPercents(aarOutput[0], TRUE)); } strcat(sz, "\n"); /* equities */ strcat(sz, _("Cubeful equities")); strcat(sz, ":\n"); if (pes->et == EVAL_EVAL && exsExport.afCubeParameters[0]) { strcat(sz, " "); strcat(sz, OutputEvalContext(&pes->ec, FALSE)); strcat(sz, "\n"); } getCubeDecisionOrdering(ai, arDouble, aarOutput, pci); for (i = 0; i < 3; i++) { sprintf(strchr(sz, 0), "%d. %-20s", i + 1, gettext(aszCube[ai[i]])); strcat(sz, OutputEquity(arDouble[ai[i]], pci, TRUE)); if (i) sprintf(strchr(sz, 0), " (%s)", OutputEquityDiff(arDouble[ai[i]], arDouble[OUTPUT_OPTIMAL], pci)); strcat(sz, "\n"); } /* cube decision */ cd = FindBestCubeDecision(arDouble, aarOutput, pci); sprintf(strchr(sz, 0), "%s: %s", _("Proper cube action"), GetCubeRecommendation(cd)); if ((r = getPercent(cd, arDouble)) >= 0.0) sprintf(strchr(sz, 0), " (%.1f%%)", 100.0f * r); strcat(sz, "\n"); /* dump rollout */ if (pes->et == EVAL_ROLLOUT && exsExport.fCubeDetailProb) { char asz[2][1024]; cubeinfo aci[2]; for (i = 0; i < 2; i++) { memcpy(&aci[i], pci, sizeof(cubeinfo)); if (i) { aci[i].fCubeOwner = !pci->fMove; aci[i].nCube *= 2; } FormatCubePosition(asz[i], &aci[i]); } sprintf(strchr(sz, 0), "\n%s:\n", _("Rollout details")); strcat(strchr(sz, 0), OutputRolloutResult(NULL, asz, aarOutput, aarStdDev, aci, 0, 2, pes->rc.fCubeful)); } if (pes->et == EVAL_ROLLOUT && exsExport.afCubeParameters[1]) strcat(strchr(sz, 0), OutputRolloutContext(NULL, &pes->rc)); return sz; }
extern char * OutputCubeAnalysisFull(float aarOutput[2][NUM_ROLLOUT_OUTPUTS], float aarStdDev[2][NUM_ROLLOUT_OUTPUTS], const evalsetup * pes, const cubeinfo * pci, int fDouble, int fTake, skilltype stDouble, skilltype stTake) { float r; int fMissed; int fAnno = FALSE; float arDouble[4]; static char sz[4096]; char *pc; strcpy(sz, ""); /* check if cube analysis should be printed */ if (pes->et == EVAL_NONE) return NULL; /* no evaluation */ FindCubeDecision(arDouble, aarOutput, pci); /* print alerts */ fMissed = fDouble > -1 && isMissedDouble(arDouble, aarOutput, fDouble, pci); /* print alerts */ if (fMissed) { fAnno = TRUE; /* missed double */ sprintf(pc = strchr(sz, 0), "%s (%s)!\n", _("Alert: missed double"), OutputEquityDiff(arDouble[OUTPUT_NODOUBLE], (arDouble[OUTPUT_TAKE] > arDouble[OUTPUT_DROP]) ? arDouble[OUTPUT_DROP] : arDouble[OUTPUT_TAKE], pci)); if (badSkill(stDouble)) sprintf(pc = strchr(sz, 0), " [%s]", gettext(aszSkillType[stDouble])); } r = arDouble[OUTPUT_TAKE] - arDouble[OUTPUT_DROP]; if (fTake > 0 && r > 0.0f) { fAnno = TRUE; /* wrong take */ sprintf(pc = strchr(sz, 0), "%s (%s)!\n", _("Alert: wrong take"), OutputEquityDiff(arDouble[OUTPUT_DROP], arDouble[OUTPUT_TAKE], pci)); if (badSkill(stTake)) sprintf(pc = strchr(sz, 0), " [%s]", gettext(aszSkillType[stTake])); } r = arDouble[OUTPUT_DROP] - arDouble[OUTPUT_TAKE]; if (fDouble > 0 && !fTake && r > 0.0f) { fAnno = TRUE; /* wrong pass */ sprintf(pc = strchr(sz, 0), "%s (%s)!\n", _("Alert: wrong pass"), OutputEquityDiff(arDouble[OUTPUT_TAKE], arDouble[OUTPUT_DROP], pci)); if (badSkill(stTake)) sprintf(pc = strchr(sz, 0), " [%s]", gettext(aszSkillType[stTake])); } if (arDouble[OUTPUT_TAKE] > arDouble[OUTPUT_DROP]) r = arDouble[OUTPUT_NODOUBLE] - arDouble[OUTPUT_DROP]; else r = arDouble[OUTPUT_NODOUBLE] - arDouble[OUTPUT_TAKE]; if (fDouble > 0 && fTake < 0 && r > 0.0f) { fAnno = TRUE; /* wrong double */ sprintf(pc = strchr(sz, 0), "%s (%s)!\n", _("Alert: wrong double"), OutputEquityDiff((arDouble[OUTPUT_TAKE] > arDouble[OUTPUT_DROP]) ? arDouble[OUTPUT_DROP] : arDouble[OUTPUT_TAKE], arDouble[OUTPUT_NODOUBLE], pci)); if (badSkill(stDouble)) sprintf(pc = strchr(sz, 0), " [%s]", gettext(aszSkillType[stDouble])); } if ((badSkill(stDouble) || badSkill(stTake)) && !fAnno) { if (badSkill(stDouble)) { sprintf(pc = strchr(sz, 0), _("Alert: double decision marked %s"), gettext(aszSkillType[stDouble])); strcat(sz, "\n"); } if (badSkill(stTake)) { sprintf(pc = strchr(sz, 0), _("Alert: take decision marked %s"), gettext(aszSkillType[stTake])); strcat(sz, "\n"); } } strcat(sz, OutputCubeAnalysis(aarOutput, aarStdDev, pes, pci)); return sz; }
static char * ExtFIBSBoard(scancontext * pec) { ProcessedFIBSBoard processedBoard; TanBoard anBoardOrig; int anScore[2], anMove[8], fTurn; float arDouble[NUM_CUBEFUL_OUTPUTS], aarOutput[2][NUM_ROLLOUT_OUTPUTS], aarStdDev[2][NUM_ROLLOUT_OUTPUTS]; rolloutstat aarsStatistics[2][2]; cubeinfo ci; char *szResponse; if (ProcessFIBSBoardInfo(&pec->bi, &processedBoard)) { szResponse = g_strdup_printf("Error: badly formed board\n"); } else { anScore[0] = processedBoard.nScoreOpp; anScore[1] = processedBoard.nScore; /* If the session isn't using Crawford rule, set crawford flag to false */ processedBoard.fCrawford = pec->fCrawfordRule ? processedBoard.fCrawford : FALSE; /* Set the Jacoby flag appropriately from the external interface settings */ processedBoard.fJacoby = pec->fJacobyRule; /* printf ("Crawford Setting: %d\n", fCrawford); */ /* printf ("Jacoby Setting: %d\n", fJacoby); */ fTurn = 1; SetCubeInfo(&ci, processedBoard.nCube, processedBoard.fCubeOwner, fTurn, processedBoard.nMatchTo, anScore, processedBoard.fCrawford, processedBoard.fJacoby, nBeavers, bgvDefault); memcpy(anBoardOrig, processedBoard.anBoard, sizeof(processedBoard.anBoard)); if (processedBoard.fDoubled) { /* take decision */ if (GeneralCubeDecision(aarOutput, aarStdDev, aarsStatistics, (ConstTanBoard) processedBoard.anBoard, &ci, GetEvalCube(), NULL, NULL) < 0) return NULL; switch (FindCubeDecision(arDouble, aarOutput, &ci)) { case DOUBLE_PASS: case TOOGOOD_PASS: case REDOUBLE_PASS: case TOOGOODRE_PASS: szResponse = g_strdup("drop\n"); break; case NODOUBLE_BEAVER: case DOUBLE_BEAVER: case NO_REDOUBLE_BEAVER: szResponse = g_strdup("beaver\n"); break; default: szResponse = g_strdup("take\n"); } } else if (pec->nResignation) { /* if opp wants to resign (extension to FIBS board) */ float arOutput[NUM_ROLLOUT_OUTPUTS]; float rEqBefore, rEqAfter; const float epsilon = 1.0e-6f; getResignation(arOutput, processedBoard.anBoard, &ci, &esEvalCube); getResignEquities(arOutput, &ci, pec->nResignation, &rEqBefore, &rEqAfter); /* if opponent gives up equity by resigning */ if ((rEqAfter - epsilon) < rEqBefore) szResponse = g_strdup("accept\n"); else szResponse = g_strdup("reject\n"); } else if (processedBoard.anDice[0]) { /* move */ char szMove[64]; if (FindBestMove(anMove, processedBoard.anDice[0], processedBoard.anDice[1], processedBoard.anBoard, &ci, &GetEvalChequer()->ec, *GetEvalMoveFilter()) < 0) return NULL; FormatMovePlain(szMove, anBoardOrig, anMove); szResponse = g_strconcat(szMove, "\n", NULL); } else { /* double decision */ if (GeneralCubeDecision(aarOutput, aarStdDev, aarsStatistics, (ConstTanBoard) processedBoard.anBoard, &ci, GetEvalCube(), NULL, NULL) < 0) return NULL; switch (FindCubeDecision(arDouble, aarOutput, &ci)) { case DOUBLE_TAKE: case DOUBLE_PASS: case DOUBLE_BEAVER: case REDOUBLE_TAKE: case REDOUBLE_PASS: szResponse = g_strdup("double\n"); break; default: szResponse = g_strdup("roll\n"); } } } return szResponse; }
static char * ExtFIBSBoard( extcmd *pec ) { char szName[ MAX_NAME_LEN ], szOpp[ MAX_NAME_LEN ]; int nMatchTo, anScore[ 2 ], anDice[ 2 ], nCube, fCubeOwner, fDoubled, fCrawford, fJacoby, anMove[ 8 ], fTurn; TanBoard anBoard, anBoardOrig; float arDouble[ NUM_CUBEFUL_OUTPUTS ], aarOutput[ 2 ][ NUM_ROLLOUT_OUTPUTS ], aarStdDev[ 2 ][ NUM_ROLLOUT_OUTPUTS ]; rolloutstat aarsStatistics[ 2 ][ 2 ]; cubeinfo ci; int nScore, nScoreOpponent; char *szResponse; if( ParseFIBSBoard( pec->szFIBSBoard, anBoard, szName, szOpp, &nMatchTo, &nScore, &nScoreOpponent, anDice, &nCube, &fCubeOwner, &fDoubled, &fCrawford ) ) { outputl( _("Warning: badly formed board from external controller.") ); szResponse = g_strdup_printf( "Error: badly formed board ('%s')\n", pec->szFIBSBoard ); } else { anScore[ 0 ] = nScoreOpponent; anScore[ 1 ] = nScore; /* If the session isn't using Crawford rule, set crawford flag to false */ fCrawford = pec->fCrawfordRule ? fCrawford : FALSE; /* Set the Jacoby flag appropriately from the external interface settings */ fJacoby = pec->fJacobyRule; /* printf ("Crawford Setting: %d\n", fCrawford); */ /* printf ("Jacoby Setting: %d\n", fJacoby); */ fTurn = 1; SetCubeInfo ( &ci, nCube, fCubeOwner, fTurn, nMatchTo, anScore, fCrawford, fJacoby, nBeavers, bgvDefault ); #if 0 { char *asz[ 7 ] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; char szBoard[ 10000 ]; outputl( DrawBoard( szBoard, anBoard, 1, asz, "no matchid", 15 ) ); printf( "score %d-%d to %d ", anScore[ 0 ], anScore[ 1 ], nMatchTo ); printf( "dice %d %d ", anDice[ 0 ], anDice[ 1 ] ); printf( "cubeowner %d cube %d turn %d crawford %d doubled %d\n", fCubeOwner, nCube, fTurn, fCrawford, fDoubled ); } #endif memcpy( anBoardOrig, anBoard, sizeof( anBoard ) ); if ( fDoubled ) { /* take decision */ if( GeneralCubeDecision( aarOutput, aarStdDev, aarsStatistics, (ConstTanBoard)anBoard, &ci, GetEvalCube(), NULL, NULL ) < 0 ) return NULL; switch( FindCubeDecision( arDouble, aarOutput, &ci )) { case DOUBLE_PASS: case TOOGOOD_PASS: case REDOUBLE_PASS: case TOOGOODRE_PASS: szResponse = g_strdup( "drop\n" ); break; case NODOUBLE_BEAVER: case DOUBLE_BEAVER: case NO_REDOUBLE_BEAVER: szResponse = g_strdup( "beaver\n" ); break; default: szResponse = g_strdup( "take\n" ); } #if 0 /* this code is broken as the sign of fDoubled indicates who doubled */ } else if ( fDoubled < 0 ) { /* if opp wants to resign (extension to FIBS board) */ float arOutput[ NUM_ROLLOUT_OUTPUTS ]; float rEqBefore, rEqAfter; const float epsilon = 1.0e-6; getResignation( arOutput, anBoard, &ci, &esEvalCube ); getResignEquities ( arOutput, &ci, -fDoubled, &rEqBefore, &rEqAfter ); /* if opponent gives up equity by resigning */ if( ( rEqAfter - epsilon ) < rEqBefore ) szResponse = g_strdup( "accept\n" ); else szResponse = g_strdup( "reject\n" ); #endif /* broken */ } else if( anDice[ 0 ] ) { /* move */ char szMove[ 64 ]; if( FindBestMove( anMove, anDice[ 0 ], anDice[ 1 ], anBoard, &ci, &GetEvalChequer()->ec, *GetEvalMoveFilter() ) < 0 ) return NULL; FormatMovePlain( szMove, anBoardOrig, anMove ); szResponse = g_strconcat( szMove, "\n", NULL ); } else { /* double decision */ if( GeneralCubeDecision( aarOutput, aarStdDev, aarsStatistics, (ConstTanBoard)anBoard, &ci, GetEvalCube(), NULL, NULL ) < 0 ) return NULL; switch( FindCubeDecision( arDouble, aarOutput, &ci )) { case DOUBLE_TAKE: case DOUBLE_PASS: case DOUBLE_BEAVER: case REDOUBLE_TAKE: case REDOUBLE_PASS: szResponse = g_strdup( "double\n" ); break; default: szResponse = g_strdup( "roll\n" ); } } } return szResponse; }