From 551c51c02649aeb38d72002d6bb70b58dbee1eb2 Mon Sep 17 00:00:00 2001 From: pommicket Date: Fri, 8 Aug 2025 10:42:40 -0400 Subject: MacondoBackend --- quacker/macondobackend.cpp | 110 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 quacker/macondobackend.cpp (limited to 'quacker/macondobackend.cpp') diff --git a/quacker/macondobackend.cpp b/quacker/macondobackend.cpp new file mode 100644 index 0000000..e172b9d --- /dev/null +++ b/quacker/macondobackend.cpp @@ -0,0 +1,110 @@ +#include "macondobackend.h" +#include "quackleio/gcgio.h" +#include "game.h" + +#include +#include +#include +#include + +static int getPlyNumber(const Quackle::GamePosition &position) { + int playerIndex = 0, numPlayers = position.players().size(); + for (const Quackle::Player &player: position.players()) { + if (player.id() == position.playerOnTurn().id()) { + break; + } + playerIndex++; + } + if (playerIndex >= numPlayers) { + throw "couldn't find player in player list"; + } + return (position.turnNumber() - 1) * numPlayers + + playerIndex; +} + + +MacondoBackend::MacondoBackend(Quackle::Game *game, const InitOptions &options) { + m_execPath = options.execPath; + m_game = game; +} + +void MacondoBackend::simulate(const SimulateOptions &) { + if (m_process) return; + printf("running macondo %s\n", m_execPath.c_str()); + m_process = new QProcess; + QStringList args; + m_process->start(m_execPath.c_str(), args); + connect(m_process, SIGNAL(started()), this, SLOT(processStarted())); + connect(m_process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processFinished(int, QProcess::ExitStatus))); + m_command = MacondoCommand::Simulate; +} + +void MacondoBackend::processStarted() { + loadGCG(); + switch (m_command) { + case MacondoCommand::None: + throw "process started with no command"; + case MacondoCommand::Simulate: + m_process->write("gen\nsim\n"); + m_runningSimulation = true; + break; + case MacondoCommand::Solve: + // TODO + break; + } +} + +void MacondoBackend::loadGCG() { + std::random_device randDev; + std::mt19937 rand(randDev()); + std::uniform_int_distribution distribution(0, 26); + if (!m_tempGCG.empty()) { + remove(m_tempGCG.c_str()); + } + // save game file with random name + char filename[] = "tmpGameXXXXXXXXXXXX.gcg"; + for (int i = 0; filename[i]; i++) { + if (filename[i] == 'X') { + filename[i] = distribution(rand) + 'A'; + } + } + m_tempGCG = filename; + QuackleIO::GCGIO gcg; + { + QFile file(filename); + file.open(QIODevice::WriteOnly | QIODevice::Text); + QTextStream fileStream(&file); + gcg.write(*m_game, fileStream); + } + std::stringstream commands; + commands << "load " << filename << "\n" + << "turn " << getPlyNumber(m_game->currentPosition()) << "\n"; + m_process->write(commands.str().c_str()); +} + +void MacondoBackend::killProcess() { + if (m_process) { + m_process->kill(); + } +} + +void MacondoBackend::processFinished(int, QProcess::ExitStatus) { + delete m_process; + m_process = nullptr; +} + +std::string MacondoBackend::getSimResults() { + if (m_runningSimulation) { + m_process->write("sim show\n"); + } + QByteArray data = m_process->readAllStandardError(); + fprintf(stderr,"%s",data.constData()); + data = m_process->readAllStandardOutput(); + printf("%s", data.constData()); + fflush(stdout); + return ""; +} + +MacondoBackend::~MacondoBackend() { + killProcess(); +} -- cgit v1.2.3