extern int check_resigns(cubeinfo * pci) { float rEqBefore, rEqAfter; const float max_cost = 0.05f; const float max_gain = 1e-6f; decisionData dd; cubeinfo ci; int resigned = 1; if (pci == NULL) { GetMatchStateCubeInfo(&ci, &ms); pci = &ci; } get_eq_before_resign(pci, &dd); do { getResignEquities(dd.aarOutput[0], pci, resigned, &rEqBefore, &rEqAfter); if (rEqBefore - rEqAfter > max_cost) { resigned = 4; break; } else if (rEqAfter - rEqBefore < max_gain) break; } while (resigned++ <= 3); return resigned == 4 ? -1 : resigned; }
static GtkTreeModel * create_model(const int n, evalcontext * pec, const matchstate * pms) { GtkTreeStore *model; TanBoard anBoard; cubeinfo ci; float arOutput[NUM_ROLLOUT_OUTPUTS]; int i, j; memcpy(anBoard, pms->anBoard, sizeof(anBoard)); /* create tree store */ model = gtk_tree_store_new(3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); GetMatchStateCubeInfo(&ci, pms); for (i = 0, j = 1; i < n; ++i, j *= 21); ProgressStartValue(_("Calculating equities"), j); add_level(model, NULL, n - 1, (ConstTanBoard) anBoard, pec, &ci, TRUE, arOutput); ProgressEnd(); if (!fInterrupt) { gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(model), 2, sort_func, NULL, NULL); gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(model), 2, GTK_SORT_DESCENDING); return GTK_TREE_MODEL(model); } else return NULL; }
static void EvalMoves(hintdata * phd, evalcontext * pec) { GList *pl; cubeinfo ci; int *ai; GList *plSelList = MoveListGetSelectionList(phd); if (!plSelList) return; GetMatchStateCubeInfo(&ci, &ms); for (pl = plSelList; pl; pl = pl->next) { scoreData sd; sd.pm = MoveListGetMove(phd, pl); sd.pci = &ci; sd.pec = pec; if (RunAsyncProcess((AsyncFun) asyncScoreMove, &sd, _("Evaluating positions...")) != 0) { MoveListFreeSelectionList(plSelList); return; } /* Calling RefreshMoveList here requires some extra work, as * it may reorder moves */ MoveListUpdate(phd); } MoveListFreeSelectionList(plSelList); MoveListClearSelection(0, 0, phd); ai = (int *) malloc(phd->pml->cMoves * sizeof(int)); RefreshMoveList(phd->pml, ai); if (phd->piHighlight && phd->pml->cMoves) *phd->piHighlight = ai[*phd->piHighlight]; free(ai); find_skills(phd->pmr, &ms, -1, -1); MoveListUpdate(phd); if (phd->hist) { SetAnnotation(pmrCurAnn); ChangeGame(NULL); } }
static void TextPrintMoveAnalysis(GString * gsz, const matchstate * pms, moverecord * pmr) { char szBuf[1024]; char sz[64]; unsigned int i; cubeinfo ci; GetMatchStateCubeInfo(&ci, pms); /* check if move should be printed */ if (!exsExport.afMovesDisplay[pmr->n.stMove]) return; /* print alerts */ if (badSkill(pmr->n.stMove)) { /* blunder or error */ g_string_append_printf(gsz, _("Alert: %s move"), gettext(aszSkillType[pmr->n.stMove])); if (!pms->nMatchTo || (pms->nMatchTo && !fOutputMWC)) g_string_append_printf(gsz, " (%+7.3f)\n", pmr->ml.amMoves[pmr->n.iMove].rScore - pmr->ml.amMoves[0].rScore); else g_string_append_printf(gsz, " (%+6.3f%%)\n", 100.0f * eq2mwc(pmr->ml.amMoves[pmr->n.iMove].rScore, &ci) - 100.0f * eq2mwc(pmr->ml.amMoves[0].rScore, &ci)); } if (pmr->lt != LUCK_NONE) { /* joker */ g_string_append_printf(gsz, _("Alert: %s roll!"), gettext(aszLuckType[pmr->lt])); if (!pms->nMatchTo || (pms->nMatchTo && !fOutputMWC)) g_string_append_printf(gsz, " (%+7.3f)\n", pmr->rLuck); else g_string_append_printf(gsz, " (%+6.3f%%)\n", 100.0f * eq2mwc(pmr->rLuck, &ci) - 100.0f * eq2mwc(0.0f, &ci)); } g_string_append(gsz, "\n"); g_string_append_printf(gsz, _("Rolled %d%d"), pmr->anDice[0], pmr->anDice[1]); if (pmr->rLuck != ERR_VAL) g_string_append_printf(gsz, " (%s):\n", GetLuckAnalysis(pms, pmr->rLuck)); else g_string_append_printf(gsz, ":\n"); if (pmr->ml.cMoves) { for (i = 0; i < pmr->ml.cMoves; i++) { if (i >= exsExport.nMoves && i != pmr->n.iMove) continue; g_string_append(gsz, i == pmr->n.iMove ? "*" : " "); g_string_append(gsz, FormatMoveHint(szBuf, pms, &pmr->ml, i, i != pmr->n.iMove || i != pmr->ml.cMoves - 1 || pmr->ml.cMoves == 1 || i < exsExport.nMoves, exsExport.fMovesDetailProb, exsExport.afMovesParameters[pmr->ml.amMoves[i].esMove.et - 1])); } } else { if (pmr->n.anMove[0] >= 0) /* no movelist saved */ g_string_append_printf(gsz, "* %s\n", FormatMove(sz, pms->anBoard, pmr->n.anMove)); else /* no legal moves */ /* FIXME: output equity?? */ g_string_append_printf(gsz, "* %s\n", _("Cannot move")); } g_string_append(gsz, "\n\n"); return; }
static void TextPrintCubeAnalysis(GString * gsz, const matchstate * pms, moverecord * pmr) { cubeinfo ci; /* we need to remember the double type to be able to do the right * thing for beavers and racoons */ static doubletype dt = DT_NORMAL; GetMatchStateCubeInfo(&ci, pms); switch (pmr->mt) { case MOVE_NORMAL: /* cube analysis from move */ TextPrintCubeAnalysisTable(gsz, pmr->CubeDecPtr->aarOutput, pmr->CubeDecPtr->aarStdDev, pmr->fPlayer, &pmr->CubeDecPtr->esDouble, &ci, FALSE, -1, pmr->stCube, SKILL_NONE); dt = DT_NORMAL; break; case MOVE_DOUBLE: dt = DoubleType(pms->fDoubled, pms->fMove, pms->fTurn); if (dt != DT_NORMAL) { g_string_append(gsz, _("Cannot analyse beaver nor raccoons!\n")); break; } TextPrintCubeAnalysisTable(gsz, pmr->CubeDecPtr->aarOutput, pmr->CubeDecPtr->aarStdDev, pmr->fPlayer, &pmr->CubeDecPtr->esDouble, &ci, TRUE, -1, pmr->stCube, SKILL_NONE); break; case MOVE_TAKE: case MOVE_DROP: /* cube analysis from double, {take, drop, beaver} */ if (dt != DT_NORMAL) { dt = DT_NORMAL; g_string_append(gsz, _("Cannot analyse beaver nor raccoons!\n")); break; } TextPrintCubeAnalysisTable(gsz, pmr->CubeDecPtr->aarOutput, pmr->CubeDecPtr->aarStdDev, pmr->fPlayer, &pmr->CubeDecPtr->esDouble, &ci, TRUE, pmr->mt == MOVE_TAKE, SKILL_NONE, /* FIXME: skill from prev. cube */ pmr->stCube); break; default: g_assert_not_reached(); } return; }
/* * 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); } }
static void MoveListRolloutClicked(GtkWidget * pw, hintdata * phd) { cubeinfo ci; int i, c, res; move *m; int *ai; void *p; GList *pl, *plSelList = MoveListGetSelectionList(phd); if (!plSelList) return; GetMatchStateCubeInfo(&ci, &ms); c = g_list_length(plSelList); /* setup rollout dialog */ { move **ppm = (move **) malloc(c * sizeof(move *)); cubeinfo **ppci = (cubeinfo **) malloc(c * sizeof(cubeinfo *)); char (*asz)[40] = (char (*)[40]) malloc(40 * c); for (i = 0, pl = plSelList; i < c; pl = pl->next, i++) { m = ppm[i] = MoveListGetMove(phd, pl); ppci[i] = &ci; FormatMove(asz[i], msBoard(), m->anMove); } MoveListFreeSelectionList(plSelList); GTKSetCurrentParent(pw); RolloutProgressStart(&ci, c, NULL, &rcRollout, asz, FALSE, &p); res = ScoreMoveRollout(ppm, (const cubeinfo **) ppci, c, RolloutProgress, p); RolloutProgressEnd(&p, FALSE); free(asz); free(ppm); free(ppci); if (res < 0) return; /* If the source widget parent has been destroyed do not attempt * to update the hint window */ if (!GDK_IS_WINDOW(gtk_widget_get_parent_window(pw))) return; /* Calling RefreshMoveList here requires some extra work, as * it may reorder moves */ MoveListUpdate(phd); } MoveListClearSelection(0, 0, phd); ai = (int *) malloc(phd->pml->cMoves * sizeof(int)); RefreshMoveList(phd->pml, ai); if (phd->piHighlight && phd->pml->cMoves) *phd->piHighlight = ai[*phd->piHighlight]; free(ai); find_skills(phd->pmr, &ms, -1, -1); MoveListUpdate(phd); if (phd->hist) { SetAnnotation(pmrCurAnn); ChangeGame(NULL); } }