extern int DumpPosition(const TanBoard anBoard, char *szOutput, const evalcontext * pec, cubeinfo * pci, int fOutputMWC, int UNUSED(fOutputWinPC), int fOutputInvert, const char *szMatchID) { float aarOutput[2][NUM_ROLLOUT_OUTPUTS]; positionclass pc = ClassifyPosition(anBoard, pci->bgv); int i, nPlies; int j; evalcontext ec; static const char *aszEvaluator[] = { N_("Over"), N_("Hypergammon-1"), N_("Hypergammon-2"), N_("Hypergammon-3"), N_("Bearoff2"), N_("Bearoff-TS"), N_("Bearoff1"), N_("Bearoff-OS"), N_("Race"), N_("Crashed"), N_("Contact") }; strcpy(szOutput, ""); sprintf(strchr(szOutput, 0), "%s:\t", _("Position ID")); strcat(szOutput, PositionID(anBoard)); strcat(szOutput, "\n"); if (szMatchID) { sprintf(strchr(szOutput, 0), "%s:\t", _("Match ID")); strcat(szOutput, szMatchID); strcat(szOutput, "\n"); } strcat(szOutput, "\n"); sprintf(strchr(szOutput, 0), "%s: \t", _("Evaluator")); strcat(szOutput, gettext(aszEvaluator[pc])); strcat(szOutput, "\n\n"); acdf[pc] (anBoard, strchr(szOutput, 0), pci->bgv); szOutput = strchr(szOutput, 0); sprintf(strchr(szOutput, 0), "\n" " %-7s %-7s %-7s %-7s %-7s %-9s %-9s\n", _("Win"), _("W(g)"), _("W(bg)"), _("L(g)"), _("L(bg)"), (!pci->nMatchTo || (pci->nMatchTo && !fOutputMWC)) ? _("Equity") : _("MWC"), _("Cubeful")); nPlies = pec->nPlies > 9 ? 9 : pec->nPlies; memcpy(&ec, pec, sizeof(evalcontext)); for (i = 0; i <= nPlies; i++) { szOutput = strchr(szOutput, 0); ec.nPlies = i; if (GeneralCubeDecisionE(aarOutput, anBoard, pci, &ec, 0) < 0) return -1; if (!i) strcpy(szOutput, _("static")); else sprintf(szOutput, "%2d %s", i, _("ply")); szOutput = strchr(szOutput, 0); if (fOutputInvert) { InvertEvaluationR(aarOutput[0], pci); InvertEvaluationR(aarOutput[1], pci); pci->fMove = !pci->fMove; } /* Print %'s and equities */ strcat(szOutput, ": "); for (j = 0; j < 5; ++j) { sprintf(strchr(szOutput, 0), "%-7s ", OutputPercent(aarOutput[0][j])); } if (pci->nMatchTo) sprintf(strchr(szOutput, 0), "%-9s ", OutputEquity(Utility(aarOutput[0], pci), pci, TRUE)); else sprintf(strchr(szOutput, 0), "%-9s ", OutputMoneyEquity(aarOutput[0], TRUE)); sprintf(strchr(szOutput, 0), "%-9s ", OutputMWC(aarOutput[0][6], pci, TRUE)); strcat(szOutput, "\n"); if (fOutputInvert) { pci->fMove = !pci->fMove; } } /* if cube is available, output cube action */ if (GetDPEq(NULL, NULL, pci)) { evalsetup es; es.et = EVAL_EVAL; es.ec = *pec; strcat(szOutput, "\n\n"); strcat(szOutput, OutputCubeAnalysis(aarOutput, NULL, &es, pci)); } return 0; }
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; }
/* * Call UpdateMostList to update the movelist in the GTK hint window. * For example, after new evaluations, rollouts or toggle of MWC/Equity. * */ extern void MoveListUpdate ( const hintdata *phd ) { unsigned int i, j, colNum; char sz[ 32 ]; cubeinfo ci; movelist *pml = phd->pml; int col = phd->fDetails ? 8 : 2; int showWLTree = showMoveListDetail && !phd->fDetails; int offset = (phd->fDetails) ? 0 : MIN_COLUMN_COUNT - DETAIL_COLUMN_COUNT; GtkTreeIter iter; GtkListStore *store; store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(phd->pwMoves))); gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); if (!psHighlight) { /* Get highlight style first time in */ GtkStyle *psTemp; GtkStyle *psMoves = gtk_widget_get_style(phd->pwMoves); GetStyleFromRCFile(&psHighlight, "move-done", psMoves); /* Use correct background colour when selected */ memcpy(&psHighlight->bg[GTK_STATE_SELECTED], &psMoves->bg[GTK_STATE_SELECTED], sizeof(GdkColor)); /* Also get colour to use for w/l stats in detail view */ GetStyleFromRCFile(&psTemp, "move-winlossfg", psMoves); memcpy(&wlCol, &psTemp->fg[GTK_STATE_NORMAL], sizeof(GdkColor)); g_object_unref(psTemp); } /* This function should only be called when the game state matches the move list. */ g_assert( ms.fMove == 0 || ms.fMove == 1 ); GetMatchStateCubeInfo( &ci, &ms ); rBest = pml->amMoves[ 0 ].rScore; if (!showWLTree) gtk_tree_view_column_set_title(gtk_tree_view_get_column(GTK_TREE_VIEW(phd->pwMoves), col), (fOutputMWC && ms.nMatchTo) ? _("MWC") : _("Equity")); for( i = 0; i < pml->cMoves; i++ ) { float *ar = pml->amMoves[ i ].arEvalMove; int rankKnown; char *highlight_sz; if (showWLTree) gtk_list_store_set(store, &iter, 0, pml->amMoves + i, -1); else gtk_list_store_set(store, &iter, ML_COL_DATA + offset, pml->amMoves + i, -1); rankKnown = 1; if( i && i == pml->cMoves - 1 && phd->piHighlight && i == *phd->piHighlight ) /* The move made is the last on the list. Some moves might have been deleted to fit this one in */ { /* Lets count how many moves are possible to see if this is the last move */ movelist ml; int dice[2]; memcpy(dice, ms.anDice, sizeof(dice)); if (!dice[0]) { /* If the dice have got lost, try to find them */ moverecord* pmr = (moverecord*)plLastMove->plNext->p; if (pmr) { dice[0] = pmr->anDice[0]; dice[1] = pmr->anDice[1]; } } GenerateMoves(&ml, msBoard(), dice[0], dice[1], FALSE); if (i < ml.cMoves - 1) rankKnown = 0; } highlight_sz = (phd->piHighlight && *phd->piHighlight == i) ? "*" : ""; if (rankKnown) sprintf( sz, "%s%s%d", pml->amMoves[i].cmark ? "+" : "", highlight_sz, i + 1 ); else sprintf( sz, "%s%s??", pml->amMoves[i].cmark ? "+" : "", highlight_sz ); if (showWLTree) { gtk_list_store_set(store, &iter, 1, rankKnown ? (int)i + 1 : -1, -1); goto skipoldcode; } else gtk_list_store_set(store, &iter, ML_COL_RANK, sz, -1); FormatEval( sz, &pml->amMoves[ i ].esMove ); gtk_list_store_set(store, &iter, ML_COL_TYPE, sz, -1); /* gwc */ if ( phd->fDetails ) { colNum = ML_COL_WIN; for( j = 0; j < 5; j++ ) { if (j == 3) { gtk_list_store_set(store, &iter, colNum, OutputPercent(1.0f - ar[ OUTPUT_WIN ] ), -1); colNum++; } gtk_list_store_set(store, &iter, colNum, OutputPercent(ar[j]), -1); colNum++; } } /* cubeless equity */ gtk_list_store_set(store, &iter, ML_COL_EQUITY + offset, OutputEquity( pml->amMoves[ i ].rScore, &ci, TRUE ), -1); if (i != 0) { gtk_list_store_set(store, &iter, ML_COL_DIFF + offset, OutputEquityDiff( pml->amMoves[ i ].rScore, rBest, &ci ), -1); } gtk_list_store_set(store, &iter, ML_COL_MOVE + offset, FormatMove( sz, msBoard(), pml->amMoves[ i ].anMove ), -1); /* highlight row */ if (phd->piHighlight && *phd->piHighlight == i) { char buf[20]; sprintf(buf, "#%02x%02x%02x", psHighlight->fg[GTK_STATE_SELECTED].red / 256, psHighlight->fg[GTK_STATE_SELECTED].green / 256, psHighlight->fg[GTK_STATE_SELECTED].blue / 256); gtk_list_store_set(store, &iter, ML_COL_FGCOL + offset, buf, -1); } else gtk_list_store_set(store, &iter, ML_COL_FGCOL + offset, NULL, -1); skipoldcode: /* Messy as 3 copies of code at moment... */ gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter); } }