void testDoubling() { printf("\n\nTEST ACCETTAZIONE DOUBLE...\n"); int b[2][25] = { {2, 2, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},//ALL BEARED OFF {0, 3, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0},//ALL BEARED OFF //{2, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, //{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0} }; ms.anScore[0] = 0; ms.anScore[1] = 0; ms.nMatchTo = 7; ms.fMove = 0; ms.fTurn = 1; ms.fCubeOwner = -1; setBoard((ConstTanBoard)b); printBoard(msBoard()); printf("ACCETTAZIONE: %s\n\n", acceptDouble()?"OK":"NO"); ms.fMove = 1; ms.fTurn = 0; ms.fCubeOwner = -1; SwapSides(ms.anBoard); printBoard(msBoard()); printf("ACCETTAZIONE: %s\n", acceptDouble()?"OK":"NO"); }
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); }
extern void EvaluateRoll(float ar[NUM_ROLLOUT_OUTPUTS], int nDie1, int nDie2, const TanBoard anBoard, const cubeinfo * pci, const evalcontext * pec) { TanBoard anBoardTemp; cubeinfo ciOpp; memcpy(&ciOpp, pci, sizeof(cubeinfo)); ciOpp.fMove = !pci->fMove; memcpy(&anBoardTemp[0][0], &anBoard[0][0], 2 * 25 * sizeof(int)); if (FindBestMove(NULL, nDie1, nDie2, anBoardTemp, pci, NULL, defaultFilters) < 0) g_assert_not_reached(); SwapSides(anBoardTemp); GeneralEvaluationE(ar, (ConstTanBoard) anBoardTemp, &ciOpp, pec); return; }
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 ExportGameText(FILE * pf, listOLD * plGame, const int iGame, const int fLastGame) { listOLD *pl; moverecord *pmr; matchstate msExport; matchstate msOrig; int iMove = 0; statcontext *psc = NULL; static statcontext scTotal; xmovegameinfo *pmgi = NULL; GString *gsz; listOLD *pl_hint = NULL; statcontext *psc_rel; msOrig.nMatchTo = 0; if (!iGame) IniStatcontext(&scTotal); updateStatisticsGame(plGame); if (game_is_last(plGame)) pl_hint = game_add_pmr_hint(plGame); for (pl = plGame->plNext; pl != plGame; pl = pl->plNext) { pmr = pl->p; FixMatchState(&msExport, pmr); switch (pmr->mt) { case MOVE_GAMEINFO: ApplyMoveRecord(&msExport, plGame, pmr); gsz = g_string_new(NULL); TextPrologue(gsz, &msExport, iGame); fputs(gsz->str, pf); g_string_free(gsz, TRUE); if (exsExport.fIncludeMatchInfo) TextMatchInfo(pf, &mi); msOrig = msExport; pmgi = &pmr->g; psc = &pmr->g.sc; AddStatcontext(psc, &scTotal); /* FIXME: game introduction */ break; case MOVE_NORMAL: if (pmr->fPlayer != msExport.fMove) { SwapSides(msExport.anBoard); msExport.fMove = pmr->fPlayer; } msExport.fTurn = msExport.fMove = pmr->fPlayer; msExport.anDice[0] = pmr->anDice[0]; msExport.anDice[1] = pmr->anDice[1]; gsz = g_string_new(NULL); TextBoardHeader(gsz, &msExport, iGame, iMove); fputs(gsz->str, pf); g_string_free(gsz, TRUE); printTextBoard(pf, &msExport); gsz = g_string_new(NULL); TextAnalysis(gsz, &msExport, pmr); fputs(gsz->str, pf); g_string_free(gsz, TRUE); iMove++; break; case MOVE_DOUBLE: case MOVE_TAKE: case MOVE_DROP: gsz = g_string_new(NULL); TextBoardHeader(gsz, &msExport, iGame, iMove); fputs(gsz->str, pf); g_string_free(gsz, TRUE); printTextBoard(pf, &msExport); gsz = g_string_new(NULL); TextAnalysis(gsz, &msExport, pmr); fputs(gsz->str, pf); g_string_free(gsz, TRUE); iMove++; break; default: break; } if (exsExport.fIncludeAnnotation) TextPrintComment(pf, pmr); ApplyMoveRecord(&msExport, plGame, pmr); } if (pl_hint) game_remove_pmr_hint(pl_hint); if (pmgi && pmgi->fWinner != -1) { /* print game result */ fprintf(pf, ngettext("%s wins %d point", "%s wins %d points", pmgi->nPoints), ap[pmgi->fWinner].szName, pmgi->nPoints); } if (psc) { gsz = g_string_new(NULL); g_string_append_printf(gsz, _("\n\nGame statistics for game %d\n\n"), iGame + 1); TextDumpStatcontext(gsz, psc, msOrig.nMatchTo); fputs(gsz->str, pf); g_string_free(gsz, TRUE); } if (fLastGame) { gsz = g_string_new(NULL); if (msOrig.nMatchTo) g_string_append_printf(gsz, _("Match statistics\n\n")); else g_string_append_printf(gsz, _("Session statistics\n\n")); TextDumpStatcontext(gsz, &scTotal, msOrig.nMatchTo); psc_rel = relational_player_stats_get(ap[0].szName, ap[1].szName); if (psc_rel) { g_string_append_printf(gsz, _("\nStatistics from database\n\n")); TextDumpStatcontext(gsz, psc_rel, 0); g_free(psc_rel); } fputs(gsz->str, pf); g_string_free(gsz, TRUE); } TextEpilogue(pf, &msExport); }
static void printTextBoard(FILE * pf, const matchstate * pms) { TanBoard anBoard; char szBoard[2048]; char sz[32], szCube[32], szPlayer0[MAX_NAME_LEN + 3], szPlayer1[MAX_NAME_LEN + 3], szScore0[35], szScore1[35], szMatch[35]; char *apch[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; unsigned int anPips[2]; memcpy(anBoard, pms->anBoard, sizeof(anBoard)); apch[0] = szPlayer0; apch[6] = szPlayer1; if (pms->anScore[0] == 1) sprintf(apch[1] = szScore0, _("%d point"), pms->anScore[0]); else sprintf(apch[1] = szScore0, _("%d points"), pms->anScore[0]); if (pms->anScore[1] == 1) sprintf(apch[5] = szScore1, _("%d point"), pms->anScore[1]); else sprintf(apch[5] = szScore1, _("%d points"), pms->anScore[1]); if (pms->fDoubled) { apch[pms->fTurn ? 4 : 2] = szCube; sprintf(szPlayer0, "O: %s", ap[0].szName); sprintf(szPlayer1, "X: %s", ap[1].szName); sprintf(szCube, _("Cube offered at %d"), pms->nCube << 1); } else { sprintf(szPlayer0, "O: %s", ap[0].szName); sprintf(szPlayer1, "X: %s", ap[1].szName); apch[pms->fMove ? 4 : 2] = sz; if (pms->anDice[0]) sprintf(sz, _("Rolled %d%d"), pms->anDice[0], pms->anDice[1]); else if (!GameStatus((ConstTanBoard) anBoard, pms->bgv)) strcpy(sz, _("On roll")); else sz[0] = 0; if (pms->fCubeOwner < 0) { apch[3] = szCube; if (pms->nMatchTo) sprintf(szCube, _("%d point match (Cube: %d)"), pms->nMatchTo, pms->nCube); else sprintf(szCube, _("(Cube: %d)"), pms->nCube); } else { size_t cch = strlen(ap[pms->fCubeOwner].szName); if (cch > 20) cch = 20; sprintf(szCube, _("%c: %*s (Cube: %d)"), pms->fCubeOwner ? 'X' : 'O', (int) cch, ap[pms->fCubeOwner].szName, pms->nCube); apch[pms->fCubeOwner ? 6 : 0] = szCube; if (pms->nMatchTo) sprintf(apch[3] = szMatch, _("%d point match"), pms->nMatchTo); } } if (pms->fResigned) sprintf(strchr(sz, 0), _(", resigns %s"), gettext(aszGameResult[pms->fResigned - 1])); if (!pms->fMove) SwapSides(anBoard); fputs(DrawBoard(szBoard, (ConstTanBoard) anBoard, pms->fMove, apch, MatchIDFromMatchState(pms), anChequers[ms.bgv]), pf); PipCount((ConstTanBoard) anBoard, anPips); fprintf(pf, "Pip counts: O %u, X %u\n\n", anPips[0], anPips[1]); }
extern int ParseFIBSBoard(char *pch, TanBoard anBoard, char *szPlayer, char *szOpp, int *pnMatchTo, int *pnScore, int *pnScoreOpp, int anDice[2], int *pnCube, int *pfCubeOwner, int *pfDoubled, int *pfCrawford) { int i, c, n, fCanDouble, fOppCanDouble, anOppDice[2]; int nTmp, fNonCrawford, fPostCrawford; char *szTmp; int nTurn, nColor, nDirection; int anFIBSBoard[26]; /* Names and match length/score */ c = -1; sscanf(pch, "board:%31[^:]:%31[^:]:%d:%d:%d:%n", szPlayer, szOpp, pnMatchTo, pnScore, pnScoreOpp, &c); if (c < 0) return -1; pch += c; /* FIBS has a maximum match length of 99. Unlimited matches are * encoded with a match length of 9999. */ if (*pnMatchTo == 9999) *pnMatchTo = 0; if (*pnMatchTo && (*pnMatchTo <= *pnScore || *pnMatchTo <= *pnScoreOpp)) return -1; /* If the match length exceeds MAXSCORE we correct the match length * to MAXSCORE and the scores to the closest equivalents. */ if (*pnMatchTo > MAXSCORE) { if (*pnMatchTo - *pnScore > MAXSCORE) *pnScore = 0; else *pnScore -= *pnMatchTo - MAXSCORE; if (*pnMatchTo - *pnScoreOpp > MAXSCORE) *pnScoreOpp = 0; else *pnScoreOpp -= *pnMatchTo - MAXSCORE; *pnMatchTo = MAXSCORE; } /* Board */ for (i = 0; i < 26; ++i) { c = -1; sscanf(pch, "%d:%n", &n, &c); if (c < 0) return -1; pch += c; anFIBSBoard[i] = -n; } c = -1; sscanf(pch, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%*d:%*d:%*d:%*d:%*d:%*d:" "%*d:%d:%d:%n", &nTurn, anDice, anDice + 1, anOppDice, anOppDice + 1, pnCube, &fCanDouble, &fOppCanDouble, pfDoubled, &nColor, &nDirection, &fNonCrawford, &fPostCrawford, &c); if (c < 0) return -1; /* Consistency check: 0 is a valid value for nColor but signifies * end of game which is invalid for our purposes here. */ if (!nTurn || !nColor || !nDirection) return -1; /* Check whether the cube was turned. That is indicated by the * pfDoubed flag for the "player" and by setting the may double * flag to zero for both players for the opponent. Actually * we could completely ignore the pfDoubled flag but it could * still help, when processing data from other sources than * fibs.com. */ if (!*pfDoubled && !fCanDouble && !fOppCanDouble) *pfDoubled = 1; int fMustSwap = 0; if (*pfDoubled) fMustSwap = !fMustSwap; if (nTurn * nColor < 0) fMustSwap = !fMustSwap; /* Opponent's turn? */ if (fMustSwap) { szTmp = szPlayer; szPlayer = szOpp; szOpp = szTmp; nTmp = *pnScore; *pnScore = *pnScoreOpp; *pnScoreOpp = nTmp; nTmp = fCanDouble; fCanDouble = fOppCanDouble; fOppCanDouble = nTmp; } if (nTurn * nColor < 0) nDirection = -nDirection; nColor = nTurn > 0 ? 1 : -1; for (i = 0; i < 24; ++i) { n = nDirection < 0 ? anFIBSBoard[i + 1] : anFIBSBoard[25 - i - 1]; if (nColor * n < 0) { anBoard[1][i] = n < 0 ? -n : n; anBoard[0][23 - i] = 0; } else if (nColor * n > 0) { anBoard[1][i] = 0; anBoard[0][23 - i] = n < 0 ? -n : n; } else { anBoard[1][i] = anBoard[0][23 - i] = 0; } } if (nDirection < 0) { n = anFIBSBoard[25]; anBoard[1][24] = n < 0 ? -n : n; n = anFIBSBoard[0]; anBoard[0][24] = n < 0 ? -n : n; } else { n = anFIBSBoard[0]; anBoard[1][24] = n < 0 ? -n : n; n = anFIBSBoard[25]; anBoard[0][24] = n < 0 ? -n : n; } /* See https://savannah.gnu.org/bugs/?36485 for this. */ if (*pfDoubled) SwapSides(anBoard); if (!anDice[0] && anOppDice[0]) { anDice[0] = anOppDice[0]; anDice[1] = anOppDice[1]; } /* * Crawford detection. This is rather tricky with FIBS board states * because FIBS sets both may-double flags to 1 in the Crawford game. * * We have to inspect the last and second last field for that. * The last field is the post-Crawford flag, the second last * field is the non-Crawford flag. * * Until at least one of the players is 1-away, you cannot deduce whether * the Crawford rule is in use or not. Once one of the players * is 1-away, the non-Crawford flag is set to 3 if the Crawford rule * is not in use; otherwise everything is still 0. * * Once the Crawford game is finished, the post-Crawford flag is set * to 1. * * Since we cannot find out whether the Crawford rule is in use or not * in the pre-Crawford games, the cubeful evaluation can be slightly * biased. But since we the vast majority of matches on FIBS is played * with the Crawford rule and we assume usage of the Crawford rule * as a default, the bias is negligible. */ if (!*pnMatchTo) { *pfCrawford = 0; } else { if (*pnMatchTo - *pnScore == 1 || *pnMatchTo - *pnScoreOpp == 1) { if (fNonCrawford || fPostCrawford) { *pfCrawford = 0; } else { *pfCrawford = 1; } } else { *pfCrawford = 0; } } *pfCubeOwner = fCanDouble != fOppCanDouble ? fCanDouble : -1; return 0; }