diff options
author | pommicket <pommicket@gmail.com> | 2025-08-08 10:42:40 -0400 |
---|---|---|
committer | pommicket <pommicket@gmail.com> | 2025-08-08 10:42:40 -0400 |
commit | 551c51c02649aeb38d72002d6bb70b58dbee1eb2 (patch) | |
tree | c8b7117657854171105c14e8568a6ec8c489e30f /quacker | |
parent | 91af6685bdbfad63a035bb7997a8f3d2eb20d64a (diff) |
MacondoBackend
Diffstat (limited to 'quacker')
-rw-r--r-- | quacker/CMakeLists.txt | 2 | ||||
-rw-r--r-- | quacker/macondo.cpp | 98 | ||||
-rw-r--r-- | quacker/macondo.h | 24 | ||||
-rw-r--r-- | quacker/macondobackend.cpp | 110 | ||||
-rw-r--r-- | quacker/macondobackend.h | 48 | ||||
-rw-r--r-- | quacker/quacker.cpp | 7 |
6 files changed, 187 insertions, 102 deletions
diff --git a/quacker/CMakeLists.txt b/quacker/CMakeLists.txt index ac60a7d..966e8f6 100644 --- a/quacker/CMakeLists.txt +++ b/quacker/CMakeLists.txt @@ -40,6 +40,7 @@ set(QUACKLE_SOURCES lexicondialog.cpp lister.cpp macondo.cpp + macondobackend.cpp main.cpp movebox.cpp newgame.cpp @@ -74,6 +75,7 @@ set(QUACKLE_HEADERS lexicondialog.h lister.h macondo.h + macondobackend.h movebox.h newgame.h noteeditor.h diff --git a/quacker/macondo.cpp b/quacker/macondo.cpp index e5ccf8e..83e4553 100644 --- a/quacker/macondo.cpp +++ b/quacker/macondo.cpp @@ -1,14 +1,12 @@ #include "macondo.h" +#include "macondobackend.h" #include "quacker.h" #include <QGridLayout> #include <QPushButton> -#include <QProcess> #include <QTimer> -#include <random> -Macondo::Macondo(TopLevel *topLevel) : View() { - m_topLevel = topLevel; +Macondo::Macondo(Quackle::Game *game) : QWidget() { m_updateTimer = new QTimer(this); QGridLayout *layout = new QGridLayout(this); m_simulateButton = new QPushButton(tr("Simulate")); @@ -16,94 +14,30 @@ Macondo::Macondo(TopLevel *topLevel) : View() { layout->setAlignment(Qt::AlignTop); const char *home = getenv("HOME"); // TODO: configurable path - m_execPath = home ? home : "/"; - m_execPath += "/apps/macondo/macondo"; + std::string execPath = home ? home : "/"; + execPath += "/apps/macondo/macondo"; + MacondoBackend::InitOptions initOptions(execPath); + m_backend = new MacondoBackend(game, initOptions); connect(m_simulateButton, SIGNAL(clicked()), this, SLOT(simulate())); connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(updateResults())); m_updateTimer->setInterval(1000); } void Macondo::simulate() { - 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 = Command::Simulate; + MacondoBackend::SimulateOptions options; + m_backend->simulate(options); + m_updateTimer->start(); } -void Macondo::processStarted() { - m_updateTimer->start(); - loadGCG(); - switch (m_command) { - case Command::None: - throw "process started with no command"; - case Command::Simulate: - m_process->write("gen\nsim\n"); - m_runningSimulation = true; +void Macondo::updateResults() { + switch (m_backend->command()) { + case MacondoCommand::None: break; - case Command::Solve: + case MacondoCommand::Simulate: + m_backend->getSimResults(); + break; + case MacondoCommand::Solve: // TODO break; } } - -void Macondo::killProcess() { - if (m_process) { - m_process->kill(); - } -} - -void Macondo::processFinished(int, QProcess::ExitStatus) { - delete m_process; - m_process = nullptr; -} - -Macondo::~Macondo() { - killProcess(); -} - -void Macondo::loadGCG() { - std::default_random_engine rand; - std::uniform_int_distribution<int> distribution(0, 26); - // 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_topLevel->writeFile(filename); - std::stringstream commands; - commands << "load " << filename << "\n" - << "turn " << m_viewingPlyNumber << "\n"; - m_process->write(commands.str().c_str()); -} - -void Macondo::updateResults() { - if (m_runningSimulation) { - m_process->write("sim show\n"); - } - QByteArray data = m_process->readAllStandardError(); - printf("%s",data.constData()); - data = m_process->readAllStandardOutput(); - printf("%s", data.constData()); - fflush(stdout); -} - -void Macondo::positionChanged(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"; - } - m_viewingPlyNumber = (position->turnNumber() - 1) * numPlayers - + playerIndex; -} diff --git a/quacker/macondo.h b/quacker/macondo.h index b8dbf73..77af35f 100644 --- a/quacker/macondo.h +++ b/quacker/macondo.h @@ -1,38 +1,28 @@ -#include <QProcess> #include <QWidget> -#include "view.h" - - class QPushButton; class QTimer; -class TopLevel; +namespace Quackle { + class Game; +} +class MacondoBackend; -class Macondo : public View { +class Macondo : public QWidget { Q_OBJECT public: - Macondo(TopLevel *topLevel); - ~Macondo(); + Macondo(Quackle::Game *); public slots: void simulate(); void updateResults(); - void processStarted(); - void processFinished(int, QProcess::ExitStatus); - virtual void positionChanged(const Quackle::GamePosition *position); private: enum class Command { None, Simulate, Solve, }; - void loadGCG(); - void killProcess(); - TopLevel *m_topLevel; QPushButton *m_simulateButton; QTimer *m_updateTimer; - std::string m_execPath; - QProcess *m_process = nullptr; + MacondoBackend *m_backend; int m_viewingPlyNumber = 0; - bool m_runningSimulation = false; Command m_command = Command::None; }; 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 <QFile> +#include <QProcess> +#include <QTextStream> +#include <random> + +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<int> 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(); +} diff --git a/quacker/macondobackend.h b/quacker/macondobackend.h new file mode 100644 index 0000000..dfda0c5 --- /dev/null +++ b/quacker/macondobackend.h @@ -0,0 +1,48 @@ +#ifndef MACONDO_BACKEND_H_ +#define MACONDO_BACKEND_H_ + +#include <QObject> +#include <QProcess> + +namespace Quackle { + class Game; +} + +enum class MacondoCommand { + None, + Simulate, + Solve, +}; + +class MacondoBackend: public QObject { +Q_OBJECT +public: + struct InitOptions { + inline InitOptions(std::string execPath) { + this->execPath = execPath; + } + std::string execPath; + }; + MacondoBackend(Quackle::Game *game, const InitOptions &); + struct SimulateOptions { + inline SimulateOptions() {} + }; + void simulate(const SimulateOptions &); + ~MacondoBackend(); + std::string getSimResults(); + inline MacondoCommand command() const { return m_command; } +protected slots: + void processStarted(); + void processFinished(int, QProcess::ExitStatus); +private: + void loadGCG(); + void killProcess(); + std::string m_execPath; + std::string m_tempGCG; + QProcess *m_process = nullptr; + bool m_runningSimulation = false; + Quackle::Game *m_game; + MacondoCommand m_command = MacondoCommand::None; +}; + +#endif diff --git a/quacker/quacker.cpp b/quacker/quacker.cpp index af50d2f..3502c3a 100644 --- a/quacker/quacker.cpp +++ b/quacker/quacker.cpp @@ -1293,7 +1293,10 @@ void TopLevel::loadFile(const QString &filename) } QTextStream stream(&file); + delete m_game; m_game = logania->read(stream, QuackleIO::Logania::MaintainBoardPreparation); + delete m_macondo; + m_macondo = new Macondo(m_game); file.close(); @@ -2001,9 +2004,7 @@ void TopLevel::createWidgets() m_history = new History; plugIntoHistoryMatrix(m_history); - m_macondo = new Macondo(this); - plugIntoMatrix(m_macondo); - plugIntoPositionMatrix(m_macondo); + m_macondo = new Macondo(m_game); m_tabWidget = new QTabWidget; m_tabWidget->addTab(m_history, tr("Histor&y")); |