static void MoveListMove(GtkWidget * pw, hintdata * phd) { move m; move *pm; char szMove[40]; GList *plSelList = MoveListGetSelectionList(phd); if (!plSelList) return; ShowMove(phd, TRUE); pm = MoveListGetMove(phd, plSelList); MoveListFreeSelectionList(plSelList); memcpy(&m, pm, sizeof(move)); if (phd->fDestroyOnMove) /* Destroy widget on exit */ gtk_widget_destroy(gtk_widget_get_toplevel(pw)); FormatMove(szMove, msBoard(), m.anMove); UserCommand(szMove); #if USE_BOARD3D RestrictiveRedraw(); #endif }
extern void TextAnalysis(GString * gsz, const matchstate * pms, moverecord * pmr) { char sz[1024]; switch (pmr->mt) { case MOVE_NORMAL: if (pmr->n.anMove[0] >= 0) g_string_append_printf(gsz, _("* %s moves %s"), ap[pmr->fPlayer].szName, FormatMove(sz, pms->anBoard, pmr->n.anMove)); else if (!pmr->ml.cMoves) g_string_append_printf(gsz, _("* %s cannot move"), ap[pmr->fPlayer].szName); g_string_append(gsz, "\n"); if (exsExport.fIncludeAnalysis) { TextPrintCubeAnalysis(gsz, pms, pmr); TextPrintMoveAnalysis(gsz, pms, pmr); } break; case MOVE_DOUBLE: case MOVE_TAKE: case MOVE_DROP: if (pmr->mt == MOVE_DOUBLE) g_string_append_printf(gsz, "* %s doubles\n\n", ap[pmr->fPlayer].szName); else g_string_append_printf(gsz, "* %s %s\n\n", ap[pmr->fPlayer].szName, (pmr->mt == MOVE_TAKE) ? _("accepts") : _("rejects")); if (exsExport.fIncludeAnalysis) TextPrintCubeAnalysis(gsz, pms, pmr); break; default: break; } }
static void MoveListTempMapClicked(GtkWidget * pw, hintdata * phd) { GList *pl; char szMove[100]; matchstate *ams; int i, c; gchar **asz; GList *plSelList = MoveListGetSelectionList(phd); if (!plSelList) return; c = g_list_length(plSelList); ams = (matchstate *) g_malloc(c * sizeof(matchstate)); asz = (char **) g_malloc(c * sizeof(char *)); for (i = 0, pl = plSelList; pl; pl = pl->next, ++i) { move *m = MoveListGetMove(phd, pl); /* Apply move to get board */ memcpy(&ams[i], &ms, sizeof(matchstate)); FormatMove(szMove, (ConstTanBoard) ams[i].anBoard, m->anMove); ApplyMove(ams[i].anBoard, m->anMove, FALSE); /* Swap sides */ SwapSides(ams[i].anBoard); ams[i].fMove = !ams[i].fMove; ams[i].fTurn = !ams[i].fTurn; /* Show temp map dialog */ asz[i] = g_strdup(szMove); } MoveListFreeSelectionList(plSelList); GTKSetCurrentParent(pw); GTKShowTempMap(ams, c, (const gchar **) asz, TRUE); g_free(ams); for (i = 0; i < c; ++i) g_free(asz[i]); g_free(asz); }
static void add_level(GtkTreeStore * model, GtkTreeIter * iter, const int n, const TanBoard anBoard, evalcontext * pec, cubeinfo * pci, const gboolean fInvert, float arOutput[NUM_ROLLOUT_OUTPUTS]) { int n0, n1; GtkTreeIter child_iter; cubeinfo ci; TanBoard an; float ar[NUM_ROLLOUT_OUTPUTS]; int anMove[8]; int i; char szRoll[3], szMove[100], *szEquity; /* cubeinfo for opponent on roll */ memcpy(&ci, pci, sizeof(cubeinfo)); ci.fMove = !pci->fMove; for (i = 0; i < NUM_ROLLOUT_OUTPUTS; ++i) arOutput[i] = 0.0f; for (n0 = 0; n0 < 6; ++n0) { for (n1 = 0; n1 <= n0; ++n1) { memcpy(an, anBoard, sizeof(an)); if (FindBestMove(anMove, n0 + 1, n1 + 1, an, pci, pec, defaultFilters) < 0) return; SwapSides(an); gtk_tree_store_append(model, &child_iter, iter); if (n) { add_level(model, &child_iter, n - 1, (ConstTanBoard) an, pec, &ci, !fInvert, ar); if (fInterrupt) return; } else { /* evaluate resulting position */ ProgressValueAdd(1); if (GeneralEvaluationE(ar, (ConstTanBoard) an, &ci, pec) < 0) return; } if (fInvert) InvertEvaluationR(ar, &ci); sprintf(szRoll, "%d%d", n0 + 1, n1 + 1); FormatMove(szMove, anBoard, anMove); szEquity = OutputMWC(ar[OUTPUT_CUBEFUL_EQUITY], fInvert ? pci : &ci, TRUE); gtk_tree_store_set(model, &child_iter, 0, szRoll, 1, szMove, 2, szEquity, -1); for (i = 0; i < NUM_ROLLOUT_OUTPUTS; ++i) arOutput[i] += (n0 == n1) ? ar[i] : 2.0f * ar[i]; } } for (i = 0; i < NUM_ROLLOUT_OUTPUTS; ++i) arOutput[i] /= 36.0f; /* add average equity */ szEquity = OutputMWC(arOutput[OUTPUT_CUBEFUL_EQUITY], fInvert ? pci : &ci, TRUE); gtk_tree_store_append(model, &child_iter, iter); gtk_tree_store_set(model, &child_iter, 0, _("Average equity"), 1, "", 2, szEquity, -1); if (!fInvert) InvertEvaluationR(arOutput, pci); }
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; }
/* * 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); } }