extern void CommandExportGameText(char *sz) { FILE *pf; sz = NextToken(&sz); if (!plGame) { outputl(_("No game in progress (type `new game' to start one).")); return; } if (!sz || !*sz) { outputl(_("You must specify a file to export to (see `help export " "game text').")); return; } if (!confirmOverwrite(sz, fConfirmSave)) return; if (!strcmp(sz, "-")) pf = stdout; else if ((pf = g_fopen(sz, "w")) == 0) { outputerr(sz); return; } ExportGameText(pf, plGame, getGameNumber(plGame), FALSE); if (pf != stdout) fclose(pf); setDefaultFileName(sz); }
extern void CommandRelationalShowDetails(char *sz) { gchar output[4096]; statcontext *psc; gchar *player0 = NextToken(&sz); gchar *player1 = NextToken(&sz); if (!player0) { outputerrf(_ ("You must specify a player name to list the details for " "(see `help relational show details').")); return; } psc = relational_player_stats_get(player0, player1); if (!psc) { outputerrf(_("Empty player stats or player(s) not found")); return; } DumpStatcontext(output, psc, player0, player1 ? player1 : _("Opponents"), 0); g_free(psc); #if USE_GTK if (fX) { GTKTextWindow(output, _("Player statistics"), DT_INFO, NULL); } else #endif { outputl(_("Player statistics\n\n")); outputl(output); } }
extern void CommandRelationalTest( char *UNUSED(sz) ) { const char *err = TestDB(dbProviderType); if (err == NULL) outputl( _("Database test is successful!") ); else outputl(err); }
extern void CommandRelationalSelect(char *sz) { unsigned int i, j; RowSet *rs; if (!sz || !*sz) { outputl(_("You must specify a sql query to run.")); return; } rs = RunQuery(sz); if (!rs) return; if (rs->rows == 0) { outputl(_("No rows found.\n")); return; } #if USE_GTK if (fX) GtkShowQuery(rs); else #endif for (i = 0; i < rs->rows; i++) { if (i == 1) { /* Underline headings */ char *line, *p; unsigned int k; int totalwidth = 0; for (k = 0; k < rs->cols; k++) { totalwidth += rs->widths[k] + 1; if (k != 0) totalwidth += 2; } line = malloc(totalwidth + 1); memset(line, '-', totalwidth); p = line; for (k = 0; k < rs->cols - 1; k++) { p += rs->widths[k]; p[1] = '|'; p += 3; } line[totalwidth] = '\0'; outputl(line); free(line); } for (j = 0; j < rs->cols; j++) { if (j > 0) output(" | "); outputf("%*s", (int) rs->widths[j], rs->data[i][j]); } outputl(""); } FreeRowset(rs); }
extern void CommandRelationalErase(char *sz) { char *mq, *gq, buf[1024]; DBProvider *pdb; char *player_name; int player_id; if (!sz || !*sz || ((player_name = NextToken(&sz)) == NULL)) { outputl( _("You must specify a player name to remove " "(see `help relational erase player').") ); return; } if ((pdb = ConnectToDB(dbProviderType)) == NULL) return; player_id = GetPlayerId(pdb, player_name); if (player_id == -1) { outputl (_("Player not found or player stats empty")); return; } /* Get all matches involving player */ mq = g_strdup_printf ("FROM session WHERE player_id0 = %d OR player_id1 = %d", player_id, player_id); /* first remove any gamestats and games */ gq = g_strdup_printf ("FROM game WHERE session_id in (select session_id %s)", mq); sprintf(buf, "DELETE FROM gamestat WHERE game_id in (select game_id %s)", gq); pdb->UpdateCommand(buf); sprintf(buf, "DELETE %s", gq); pdb->UpdateCommand(buf); /* Now remove any matchstats */ sprintf(buf, "DELETE FROM matchstat WHERE session_id in (select session_id %s)", mq); pdb->UpdateCommand(buf); /* then remove any matches */ sprintf(buf, "DELETE %s", mq); pdb->UpdateCommand(buf); /* then the player */ sprintf(buf, "DELETE FROM player WHERE player_id = %d", player_id); pdb->UpdateCommand(buf); g_free(mq); g_free(gq); pdb->Commit(); pdb->Disconnect(); }
static int PySQLiteConnect(const char *dbfilename, const char *user, const char *password) { PyObject *con; char *name, *filename, *buf; int exists; name = g_strdup_printf("%s.db", dbfilename); filename = g_build_filename (szHomeDirectory, name, NULL); exists = g_file_test(filename, G_FILE_TEST_EXISTS); buf = g_strdup_printf("PySQLiteConnect(r'%s')", filename); /* Connect to database*/ con = PyRun_String(buf, Py_eval_input, pdict, pdict); g_free(name); g_free(filename); g_free(buf); if (con == NULL) { PyErr_Print(); return -1; } else if (con == Py_None) { outputl( _("Error connecting to database") ); return -1; } if (!exists) { /* Empty database file created - create tables */ return 0; } else return 1; }
extern DBProvider* GetDBProvider(DBProviderType dbType) { #if USE_PYTHON static int setup = FALSE; if (!setup) { if (LoadPythonFile("database.py") == 0) { PyObject *m; /* Get main python dictionary */ if ((m = PyImport_AddModule("__main__")) == NULL) { outputl( _("Error importing 'main' module") ); } else { pdict = PyModule_GetDict(m); setup = TRUE; } } if (!setup) return NULL; } #endif #if !NUM_PROVIDERS return NULL; #else if (dbType == INVALID_PROVIDER) return NULL; return &providers[dbType]; #endif }
extern int ExternalRead(int h, char *pch, size_t cch) { char *p = pch, *pEnd; #ifndef WIN32 ssize_t n; psighandler sh; #else int n; #endif while (cch) { ProcessEvents(); if (fInterrupt) return -2; #ifndef WIN32 PortableSignal(SIGPIPE, SIG_IGN, &sh, FALSE); #endif #ifdef WIN32 /* reading from sockets doesn't work on Windows * use recv instead */ n = recv((SOCKET) h, p, cch, 0); #else n = read(h, p, cch); #endif #ifndef WIN32 PortableSignalRestore(SIGPIPE, &sh); #endif if (!n) { outputl(_("External connection closed.")); return -1; } else if (n < 0) { if (errno == EINTR) continue; SockErr(_("reading from external connection")); return -1; } if ((pEnd = memchr(p, '\n', n))) { *pEnd = 0; return 0; } cch -= n; p += n; } p[cch - 1] = 0; return 0; }
extern void CommandExportMatchText(char *sz) { FILE *pf; listOLD *pl; int nGames; char *szCurrent; int i; sz = NextToken(&sz); if (!sz || !*sz) { outputl(_("You must specify a file to export to (see `help export " "match text').")); return; } /* Find number of games in match */ for (pl = lMatch.plNext, nGames = 0; pl != &lMatch; pl = pl->plNext, nGames++); for (pl = lMatch.plNext, i = 0; pl != &lMatch; pl = pl->plNext, i++) { szCurrent = filename_from_iGame(sz, i); if (!i) { if (!confirmOverwrite(sz, fConfirmSave)) return; setDefaultFileName(sz); } if (!strcmp(szCurrent, "-")) pf = stdout; else if ((pf = g_fopen(szCurrent, "w")) == 0) { outputerr(szCurrent); return; } ExportGameText(pf, pl->p, i, i == nGames - 1); if (pf != stdout) fclose(pf); } }
extern void CommandRelationalAddMatch(char *sz) { DBProvider *pdb; char *buf, *buf2, *date; char warnings[1024] = ""; int session_id, existing_id, player_id0, player_id1; char *arg = NULL; gboolean quiet = FALSE; arg = NextToken(&sz); if (arg) quiet = !strcmp(arg, "quiet"); if (ListEmpty(&lMatch)) { outputl( _("No match is being played.") ); return; } /* Warn if match is not finished or fully analyzed */ if (!quiet && !GameOver()) strcat(warnings, _("The match is not finished\n")); if (!quiet && !MatchAnalysed()) strcat(warnings, _("All of the match is not analyzed\n")); if (*warnings) { strcat(warnings, _("\nAdd match anyway?")); if (!GetInputYN(warnings)) return; } if ((pdb = ConnectToDB(dbProviderType)) == NULL) return; existing_id = RelationalMatchExists(pdb); if (existing_id != -1) { if (!quiet && !GetInputYN(_("Match exists, overwrite?"))) return; /* Remove any game stats and games */ buf2 = g_strdup_printf("FROM game WHERE session_id = %d", existing_id); buf = g_strdup_printf("DELETE FROM gamestat WHERE game_id in (SELECT game_id %s)", buf2); pdb->UpdateCommand(buf); g_free(buf); buf = g_strdup_printf("DELETE %s", buf2); pdb->UpdateCommand(buf); g_free(buf); g_free(buf2); /* Remove any match stats and session */ buf = g_strdup_printf("DELETE FROM matchstat WHERE session_id = %d", existing_id); pdb->UpdateCommand(buf); g_free(buf); buf = g_strdup_printf("DELETE FROM session WHERE session_id = %d", existing_id); pdb->UpdateCommand(buf); g_free(buf); } session_id = GetNextId(pdb, "session"); player_id0 = AddPlayer(pdb, ap[0].szName); player_id1 = AddPlayer(pdb, ap[1].szName); if (session_id == -1 || player_id0 == -1 || player_id1 == -1) { outputl( _("Error adding match.") ); return; } if( mi.nYear ) date = g_strdup_printf("%04d-%02d-%02d", mi.nYear, mi.nMonth, mi.nDay); else date = NULL; buf = g_strdup_printf("INSERT INTO session(session_id, checksum, player_id0, player_id1, " "result, length, added, rating0, rating1, event, round, place, annotator, comment, date) " "VALUES (%d, '%s', %d, %d, %d, %d, CURRENT_TIMESTAMP, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')", session_id, GetMatchCheckSum(), player_id0, player_id1, MatchResult(ms.nMatchTo), ms.nMatchTo, NS(mi.pchRating[0]), NS(mi.pchRating[1]), NS(mi.pchEvent), NS(mi.pchRound), NS(mi.pchPlace), NS(mi.pchAnnotator), NS(mi.pchComment), NS(date)); updateStatisticsMatch ( &lMatch ); if (pdb->UpdateCommand(buf)) { if (AddStats(pdb, session_id, player_id0, 0, "matchstat", ms.nMatchTo, &scMatch) && AddStats(pdb, session_id, player_id1, 1, "matchstat", ms.nMatchTo, &scMatch)) { if (storeGameStats) AddGames(pdb, session_id, player_id0, player_id1); pdb->Commit(); } } g_free(buf); g_free(date); pdb->Disconnect(); }
static void TextRolloutProgress(float aarOutput[][NUM_ROLLOUT_OUTPUTS], float aarStdDev[][NUM_ROLLOUT_OUTPUTS], const rolloutcontext * prc, const cubeinfo aci[], unsigned int initial_game_count, const int iGame, const int iAlternative, const int nRank, const float rJsd, const int fStopped, const int fShowRanks, int fCubeRollout, rolloutprogress * prp) { char *pch, *pc; time_t t; static unsigned int n_games_todo = 0; static unsigned int n_games_done = 0; static int min_games_done = 0; /* write progress 1/10th trial or just when called if mt */ if (!iAlternative) outputl(""); pch = OutputRolloutResult(NULL, (char (*)[1024])prp->ppch[iAlternative], (float (*)[NUM_ROLLOUT_OUTPUTS]) aarOutput[iAlternative], (float (*)[NUM_ROLLOUT_OUTPUTS]) aarStdDev[iAlternative], &aci[0], iAlternative, 1, prc->fCubeful); if (fShowRanks && iGame > 1) { pc = strrchr(pch, '\n'); *pc = 0; if (fCubeRollout) sprintf(pc, " %c", fStopped ? 's' : 'r'); else sprintf(pc, " %d%c", nRank, fStopped ? 's' : 'r'); if (nRank != 1 || fCubeRollout) sprintf(strchr(pc, 0), " %5.3f\n", rJsd); else strcat(pc, "\n"); } prp->iNextAlternative++; prp->iNextAlternative = (prp->iNextAlternative) % prp->n; if (iAlternative == (prp->n - 1)) prp->iNextGame += prc->nTrials / 10; output(pch); output(OutputRolloutContext(NULL, prc)); if (iAlternative == 0) { n_games_todo = 0; n_games_done = 0; min_games_done = prc->nTrials; } n_games_done += iGame + 1; if (!fStopped) { n_games_todo += prc->nTrials - (iGame + 1); if (iGame < min_games_done) min_games_done = iGame + 1; } if (iAlternative != (prp->n - 1)) return; /* time elapsed and time left */ t = time_left(n_games_todo, n_games_done, initial_game_count, prp->tStart); outputf(_("Time elapsed %s"), formatDelta(time(NULL) - prp->tStart)); outputf(_(" Estimated time left %s\n"), formatDelta(t)); /* estimated SE */ /* calculate estimated SE */ if (iGame <= 10) return; if (prc->fCubeful) pc = OutputMWC(estimatedSE (aarStdDev[0][OUTPUT_CUBEFUL_EQUITY], iGame, prc->nTrials), &aci[0], FALSE); else pc = OutputEquityScale(estimatedSE (aarStdDev[0][OUTPUT_EQUITY], iGame, prc->nTrials), &aci[0], &aci[0], FALSE); if (prp->ppch && prp->ppch[0] && *prp->ppch[0]) outputf(_("Estimated SE for \"%s\" after %d trials %s\n"), prp->ppch[0], prc->nTrials, pc); else outputf(_("Estimated SE after %d trials %s\n"), prc->nTrials, pc); }
extern void CommandExternal(char *sz) { #if !HAVE_SOCKETS outputl(_("This installation of GNU Backgammon was compiled without\n" "socket support, and does not implement external controllers.")); #else int h, hPeer, cb; struct sockaddr *psa; char szCommand[256]; char *szResponse = NULL; struct sockaddr_in saRemote; socklen_t saLen; scancontext scanctx; int fExit; int fRestart = TRUE; int retval; sz = NextToken(&sz); if (!sz || !*sz) { outputl(_("You must specify the name of the socket to the external controller.")); return; } memset(&scanctx, 0, sizeof(scanctx)); ExtInitParse(&scanctx.scanner); listenloop: { fExit = FALSE; scanctx.fDebug = FALSE; scanctx.fNewInterface = FALSE; if ((h = ExternalSocket(&psa, &cb, sz)) < 0) { SockErr(sz); ExtDestroyParse(scanctx.scanner); return; } if (bind(h, psa, cb) < 0) { SockErr(sz); closesocket(h); free(psa); ExtDestroyParse(scanctx.scanner); return; } free(psa); if (listen(h, 1) < 0) { SockErr("listen"); closesocket(h); ExternalUnbind(sz); ExtDestroyParse(scanctx.scanner); return; } outputf(_("Waiting for a connection from %s...\n"), sz); outputx(); ProcessEvents(); /* Must set length when using windows */ saLen = sizeof(struct sockaddr); while ((hPeer = accept(h, (struct sockaddr *) &saRemote, &saLen)) < 0) { if (errno == EINTR) { ProcessEvents(); if (fInterrupt) { closesocket(h); ExternalUnbind(sz); ExtDestroyParse(scanctx.scanner); return; } continue; } SockErr("accept"); closesocket(h); ExternalUnbind(sz); ExtDestroyParse(scanctx.scanner); return; } closesocket(h); ExternalUnbind(sz); /* print info about remove client */ outputf(_("Accepted connection from %s.\n"), inet_ntoa(saRemote.sin_addr)); outputx(); ProcessEvents(); while (!fExit && !(retval = ExternalRead(hPeer, szCommand, sizeof(szCommand)))) { if ((ExtParse(&scanctx, szCommand)) == 0) { /* parse error */ szResponse = scanctx.szError; } else { ProcessedFIBSBoard processedBoard; GValue *optionsmapgv; GValue *boarddatagv; GString *dbgStr; int anScore[2]; int fCrawford, fJacoby; char *asz[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; char szBoard[10000]; char **aszLines; char **aszLinesOrig; char *szMatchID; gchar *szOptStr; switch (scanctx.ct) { case COMMAND_HELP: szResponse = g_strdup("\tNo help information available\n"); break; case COMMAND_SET: szOptStr = g_value_get_gstring_gchar(g_list_nth_data(scanctx.pCmdData, 0)); if (g_ascii_strcasecmp(szOptStr, KEY_STR_DEBUG) == 0) { scanctx.fDebug = g_value_get_int(g_list_nth_data(scanctx.pCmdData, 1)); szResponse = g_strdup_printf("Debug output %s\n", scanctx.fDebug ? "ON" : "OFF"); } else if (g_ascii_strcasecmp(szOptStr, KEY_STR_NEWINTERFACE) == 0) { scanctx.fNewInterface = g_value_get_int(g_list_nth_data(scanctx.pCmdData, 1)); szResponse = g_strdup_printf("New interface %s\n", scanctx.fNewInterface ? "ON" : "OFF"); } else { szResponse = g_strdup_printf("Error: set option '%s' not supported\n", szOptStr); } g_list_gv_boxed_free(scanctx.pCmdData); break; case COMMAND_VERSION: szResponse = g_strdup("Interface: " EXTERNAL_INTERFACE_VERSION "\n" "RFBF: " RFBF_VERSION_SUPPORTED "\n" "Engine: " WEIGHTS_VERSION "\n" "Software: " VERSION "\n"); break; case COMMAND_NONE: szResponse = g_strdup("Error: no command given\n"); break; case COMMAND_FIBSBOARD: case COMMAND_EVALUATION: if (scanctx.fDebug) { optionsmapgv = (GValue *) g_list_nth_data(g_value_get_boxed(scanctx.pCmdData), 1); boarddatagv = (GValue *) g_list_nth_data(g_value_get_boxed(scanctx.pCmdData), 0); dbgStr = g_string_new(DEBUG_PREFIX); g_value_tostring(dbgStr, optionsmapgv, 0); g_string_append(dbgStr, "\n" DEBUG_PREFIX); g_value_tostring(dbgStr, boarddatagv, 0); g_string_append(dbgStr, "\n" DEBUG_PREFIX "\n"); ExternalWrite(hPeer, dbgStr->str, strlen(dbgStr->str)); ProcessFIBSBoardInfo(&scanctx.bi, &processedBoard); anScore[0] = processedBoard.nScoreOpp; anScore[1] = processedBoard.nScore; /* If the session isn't using Crawford rule, set crawford flag to false */ fCrawford = scanctx.fCrawfordRule ? processedBoard.fCrawford : FALSE; /* Set the Jacoby flag appropriately from the external interface settings */ fJacoby = scanctx.fJacobyRule; szMatchID = MatchID((unsigned int *) processedBoard.anDice, 1, processedBoard.nResignation, processedBoard.fDoubled, 1, processedBoard.fCubeOwner, fCrawford, processedBoard.nMatchTo, anScore, processedBoard.nCube, fJacoby, GAME_PLAYING); DrawBoard(szBoard, (ConstTanBoard) & processedBoard.anBoard, 1, asz, szMatchID, 15); aszLines = g_strsplit(&szBoard[0], "\n", 32); aszLinesOrig = aszLines; while (*aszLines) { ExternalWrite(hPeer, DEBUG_PREFIX, strlen(DEBUG_PREFIX)); ExternalWrite(hPeer, *aszLines, strlen(*aszLines)); ExternalWrite(hPeer, "\n", 1); aszLines++; } dbgStr = g_string_assign(dbgStr, ""); g_string_append_printf(dbgStr, DEBUG_PREFIX "X is %s, O is %s\n", processedBoard.szPlayer, processedBoard.szOpp); if (processedBoard.nMatchTo) { g_string_append_printf(dbgStr, DEBUG_PREFIX "Match Play %s Crawford Rule\n", scanctx.fCrawfordRule ? "with" : "without"); g_string_append_printf(dbgStr, DEBUG_PREFIX "Score: %d-%d/%d%s, ", processedBoard.nScore, processedBoard.nScoreOpp, processedBoard.nMatchTo, fCrawford ? "*" : ""); } else { g_string_append_printf(dbgStr, DEBUG_PREFIX "Money Session %s Jacoby Rule, %s Beavers\n", scanctx.fJacobyRule ? "with" : "without", scanctx.fBeavers ? "with" : "without"); g_string_append_printf(dbgStr, DEBUG_PREFIX "Score: %d-%d, ", processedBoard.nScore, processedBoard.nScoreOpp); } g_string_append_printf(dbgStr, "Roll: %d%d\n", processedBoard.anDice[0], processedBoard.anDice[1]); g_string_append_printf(dbgStr, DEBUG_PREFIX "CubeOwner: %d, Cube: %d, Turn: %c, Doubled: %d, Resignation: %d\n", processedBoard.fCubeOwner, processedBoard.nCube, 'X', processedBoard.fDoubled, processedBoard.nResignation); g_string_append(dbgStr, DEBUG_PREFIX "\n"); ExternalWrite(hPeer, dbgStr->str, strlen(dbgStr->str)); g_string_free(dbgStr, TRUE); g_strfreev(aszLinesOrig); } g_value_unsetfree(scanctx.pCmdData); if (scanctx.ct == COMMAND_EVALUATION) szResponse = ExtEvaluation(&scanctx); else szResponse = ExtFIBSBoard(&scanctx); break; case COMMAND_EXIT: closesocket(hPeer); fExit = TRUE; break; default: szResponse = g_strdup("Unsupported Command\n"); } unset_scan_context(&scanctx, FALSE); } if (szResponse) { if (ExternalWrite(hPeer, szResponse, strlen(szResponse))) break; g_free(szResponse); szResponse = NULL; } } /* Interrupted : get out of listen loop */ if (retval == -2) { ProcessEvents(); fRestart = FALSE; } closesocket(hPeer); if (szResponse) g_free(szResponse); szResponse = NULL; scanctx.szError = NULL; } if (fRestart) goto listenloop; unset_scan_context(&scanctx, TRUE); #endif }
extern void CommandExportPositionText(char *sz) { FILE *pf; int fHistory; moverecord *pmr; int iMove; GString *gsz; sz = NextToken(&sz); if (ms.gs == GAME_NONE) { outputl(_("No game in progress (type `new game' to start one).")); return; } if (!sz || !*sz) { outputl(_("You must specify a file to export to (see `help export " "position text').")); return; } pmr = get_current_moverecord(&fHistory); if (!confirmOverwrite(sz, fConfirmSave)) return; if (!strcmp(sz, "-")) pf = stdout; else if ((pf = g_fopen(sz, "w")) == 0) { outputerr(sz); return; } gsz = g_string_new(NULL); TextPrologue(gsz, &ms, getGameNumber(plGame)); fputs(gsz->str, pf); g_string_free(gsz, TRUE); if (exsExport.fIncludeMatchInfo) TextMatchInfo(pf, &mi); if (fHistory) iMove = getMoveNumber(plGame, pmr) - 1; else if (plLastMove) iMove = getMoveNumber(plGame, plLastMove->p); else iMove = -1; gsz = g_string_new(NULL); TextBoardHeader(gsz, &ms, getGameNumber(plGame), iMove); fputs(gsz->str, pf); g_string_free(gsz, TRUE); printTextBoard(pf, &ms); if (pmr) { gsz = g_string_new(NULL); TextAnalysis(gsz, &ms, pmr); fputs(gsz->str, pf); g_string_free(gsz, TRUE); if (exsExport.fIncludeAnnotation) TextPrintComment(pf, pmr); } TextEpilogue(pf, &ms); if (pf != stdout) fclose(pf); setDefaultFileName(sz); }
extern void CommandExternal( char *sz ) { #if !HAVE_SOCKETS outputl( _("This installation of GNU Backgammon was compiled without\n" "socket support, and does not implement external controllers.") ); #else int h, hPeer, cb; struct sockaddr *psa; char szCommand[ 256 ]; char *szResponse = NULL; struct sockaddr_in saRemote; socklen_t saLen; extcmd *pec; sz = NextToken( &sz ); if( !sz || !*sz ) { outputl( _("You must specify the name of the socket to the external controller.") ); return; } listenloop: { if( ( h = ExternalSocket( &psa, &cb, sz ) ) < 0 ) { SockErr( sz ); return; } if( bind( h, psa, cb ) < 0 ) { SockErr( sz ); closesocket( h ); free( psa ); return; } free( psa ); if( listen( h, 1 ) < 0 ) { SockErr( "listen" ); closesocket( h ); ExternalUnbind( sz ); return; } outputf( _("Waiting for a connection from %s...\n"), sz); outputx(); ProcessEvents(); /* Must set length when using windows */ saLen = sizeof(struct sockaddr); while( ( hPeer = accept( h, (struct sockaddr*)&saRemote, &saLen ) ) < 0 ) { if( errno == EINTR ) { ProcessEvents(); if( fInterrupt ) { closesocket( h ); ExternalUnbind( sz ); return; } continue; } SockErr( "accept" ); closesocket( h ); ExternalUnbind( sz ); return; } closesocket( h ); ExternalUnbind( sz ); /* print info about remove client */ outputf(_("Accepted connection from %s.\n"), inet_ntoa( saRemote.sin_addr ) ); outputx(); ProcessEvents(); while( !ExternalRead( hPeer, szCommand, sizeof( szCommand ) ) ) { if ( ( pec = ExtParse( szCommand ) ) == 0 ) { /* parse error */ szResponse = szError; } else { switch ( pec->ct ) { case COMMAND_NONE: szResponse = g_strdup( "Error: no command given\n" ); break; case COMMAND_FIBSBOARD: szResponse = ExtFIBSBoard( pec ); break; case COMMAND_EVALUATION: szResponse = ExtEvaluation( pec ); break; } } if ( szResponse ) { if ( ExternalWrite( hPeer, szResponse, strlen( szResponse ) ) ) break; g_free( szResponse ); } } closesocket( hPeer ); } goto listenloop; #endif }
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; }
static char * ExtEvaluation( extcmd *pec ) { char szName[ MAX_NAME_LEN ], szOpp[ MAX_NAME_LEN ]; int nMatchTo, anScore[ 2 ], anDice[ 2 ], nCube, fCubeOwner, fDoubled, fCrawford, fJacoby; TanBoard anBoard; float arOutput[ NUM_ROLLOUT_OUTPUTS ]; cubeinfo ci; int nScore, nScoreOpponent; char *szResponse; float r; evalcontext ec; 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 ("Jacoby Setting: %d\n", fJacoby);*/ /* printf ("Crawford Setting: %d\n", fCrawford); */ SetCubeInfo ( &ci, nCube, fCubeOwner, 1, nMatchTo, anScore, fCrawford, fJacoby, nBeavers, bgvDefault ); ec.fCubeful = pec->fCubeful; ec.nPlies = pec->nPlies; ec.fUsePrune = pec->fUsePrune; ec.fDeterministic = pec->fDeterministic; ec.rNoise = pec->rNoise; if ( GeneralEvaluationE( arOutput, (ConstTanBoard)anBoard, &ci, &ec ) ) return NULL; if ( nMatchTo ) { if ( ec.fCubeful ) r = arOutput[ OUTPUT_CUBEFUL_EQUITY ]; else r = eq2mwc( arOutput[ OUTPUT_EQUITY ], &ci ); } else r = ec.fCubeful ? arOutput[ 6 ] : arOutput[ 5 ]; szResponse = g_strdup_printf( "%f %f %f %f %f %f\n", arOutput[ 0 ], arOutput[ 1 ], arOutput[ 2 ], arOutput[ 3 ], arOutput[ 4 ], r ); } return szResponse; }