From 4956c4f2f7605dc7332b0e51e77a25fe88caef69 Mon Sep 17 00:00:00 2001 From: pommicket Date: Fri, 22 Aug 2025 09:57:10 -0400 Subject: Macondo max plies options --- quacker/macondo.cpp | 45 +++++++++++++++++++++++++++++++++++++-------- quacker/macondo.h | 8 +++++++- quacker/macondobackend.cpp | 25 ++++++++++++++++--------- quacker/macondobackend.h | 4 ++++ 4 files changed, 64 insertions(+), 18 deletions(-) (limited to 'quacker') diff --git a/quacker/macondo.cpp b/quacker/macondo.cpp index f732b32..83a197a 100644 --- a/quacker/macondo.cpp +++ b/quacker/macondo.cpp @@ -1,14 +1,13 @@ /* TODO: -- detect Macondo crashing? -- configurable max plies -- other peg/endgame options +- more peg/endgame options */ #include "macondo.h" #include "macondobackend.h" #include +#include #include #include #include @@ -18,9 +17,19 @@ TODO: #include #include #include +#include #include "customqsettings.h" +// Convenience wrapper around an hbox containing a label and another widget. +class LabelLayout: public QHBoxLayout { +public: + LabelLayout(const QString &label, QWidget *widget): QHBoxLayout() { + addWidget(new QLabel(label)); + addWidget(widget); + } +}; + Macondo::Macondo(Quackle::Game *game) : View() { CustomQSettings settings; m_game = game; @@ -28,7 +37,8 @@ Macondo::Macondo(Quackle::Game *game) : View() { boldFont.setWeight(QFont::Bold); m_useMacondo = new QCheckBox(tr("Use Macondo for 'Simulate'")); m_useMacondo->setChecked(settings.value("macondo/useForSimulate", false).toBool()); - std::string execPath = settings.value("macondo/execPath", "").toString().toStdString(); + QString defaultExecPath = QCoreApplication::applicationDirPath() + "/macondo/macondo"; + std::string execPath = settings.value("macondo/execPath", defaultExecPath).toString().toStdString(); m_initOptions = std::make_unique(execPath); m_backend = new MacondoBackend(game, *m_initOptions); connectBackendSignals(); @@ -40,22 +50,37 @@ Macondo::Macondo(Quackle::Game *game) : View() { connect(m_execPath, SIGNAL(editingFinished()), this, SLOT(execPathChanged())); m_solve = new QPushButton(tr("Solve")); m_solve->setDisabled(true); + + QHBoxLayout *execPathLayout = new QHBoxLayout; + execPathLayout->addWidget(execPathLabel); + execPathLayout->addWidget(m_execPath); + execPathLayout->addWidget(selectExecButton); + QGroupBox *pegBox = new QGroupBox(tr("Pre-endgame options")); QVBoxLayout *pegLayout = new QVBoxLayout; m_generatedMovesOnly = new QCheckBox(tr("Generated moves only")); m_generatedMovesOnly->setToolTip("Only analyze the moves that have been generated in the 'Choices' box."); m_generatedMovesOnly->setChecked(settings.value("macondo/generatedMovesOnly", false).toBool()); + m_preEndgameMaxPlies = new QSpinBox; + m_preEndgameMaxPlies->setRange(1, 100); + m_preEndgameMaxPlies->setValue(settings.value("macondo/preEndgameMaxPlies", 4).toInt()); pegLayout->addWidget(m_generatedMovesOnly); + pegLayout->addLayout(new LabelLayout(tr("Endgame plies"), m_preEndgameMaxPlies)); pegBox->setLayout(pegLayout); - QHBoxLayout *execPathLayout = new QHBoxLayout; - execPathLayout->addWidget(execPathLabel); - execPathLayout->addWidget(m_execPath); - execPathLayout->addWidget(selectExecButton); + + QGroupBox *endgameBox = new QGroupBox(tr("Endgame options")); + QVBoxLayout *endgameLayout = new QVBoxLayout; + endgameBox->setLayout(endgameLayout); + m_endgameMaxPlies = new QSpinBox; + m_endgameMaxPlies->setRange(1, 100); + m_endgameMaxPlies->setValue(settings.value("macondo/endgameMaxPlies", 15).toInt()); + endgameLayout->addLayout(new LabelLayout(tr("Plies"), m_endgameMaxPlies)); QVBoxLayout *layout = new QVBoxLayout(this); layout->setAlignment(Qt::AlignTop); layout->addLayout(execPathLayout); layout->addWidget(m_useMacondo); layout->addWidget(pegBox); + layout->addWidget(endgameBox); layout->addWidget(m_solve); connect(m_solve, SIGNAL(clicked()), this, SLOT(solve())); } @@ -64,6 +89,8 @@ Macondo::~Macondo() { CustomQSettings settings; settings.setValue("macondo/useForSimulate", m_useMacondo->isChecked()); settings.setValue("macondo/generatedMovesOnly", m_generatedMovesOnly->isChecked()); + settings.setValue("macondo/endgameMaxPlies", m_endgameMaxPlies->value()); + settings.setValue("macondo/preEndgameMaxPlies", m_preEndgameMaxPlies->value()); delete m_backend; } @@ -135,6 +162,7 @@ void Macondo::solve() { } else { if (m_tilesUnseen > 7) { MacondoPreEndgameOptions options; + options.endgamePlies = m_preEndgameMaxPlies->value(); if (m_generatedMovesOnly->isChecked()) { if (m_movesFromKibitzer.empty()) { QMessageBox::critical(this, @@ -148,6 +176,7 @@ void Macondo::solve() { m_backend->solvePreEndgame(options); } else { MacondoEndgameOptions options; + options.maxPlies = m_endgameMaxPlies->value(); m_backend->solveEndgame(options); } m_isSolving = true; diff --git a/quacker/macondo.h b/quacker/macondo.h index 9c85987..86d8b59 100644 --- a/quacker/macondo.h +++ b/quacker/macondo.h @@ -7,6 +7,7 @@ class QCheckBox; class QPushButton; class QLineEdit; +class QSpinBox; class MacondoBackend; struct MacondoInitOptions; class MoveBox; @@ -46,9 +47,14 @@ private: void connectBackendSignals(); bool checkExecPath(); void updateSolveButton(); + // == options == QCheckBox *m_useMacondo; - QCheckBox *m_generatedMovesOnly; QLineEdit *m_execPath; + // == endgame options == + QSpinBox *m_endgameMaxPlies; + // == pre-endgame options === + QCheckBox *m_generatedMovesOnly; + QSpinBox *m_preEndgameMaxPlies; QPushButton *m_solve; Quackle::Game *m_game; MacondoBackend *m_backend; diff --git a/quacker/macondobackend.cpp b/quacker/macondobackend.cpp index d123b95..fa3c334 100644 --- a/quacker/macondobackend.cpp +++ b/quacker/macondobackend.cpp @@ -118,16 +118,17 @@ bool MacondoBackend::simulate(const MacondoSimulateOptions &options, const Quack return true; } -void MacondoBackend::solveEndgame(const MacondoEndgameOptions &) { +void MacondoBackend::solveEndgame(const MacondoEndgameOptions &options) { + m_endgameOptions = options; startProcess(); m_command = Command::SolveEndgame; } void MacondoBackend::solvePreEndgame(const MacondoPreEndgameOptions &options) { - startProcess(); - m_command = Command::SolvePreEndgame; m_preEndgamePlaysToAnalyze = 0; m_preEndgameOptions = options; + startProcess(); + m_command = Command::SolvePreEndgame; } static bool parseInt(const string &s, int &value, size_t *len) { @@ -473,12 +474,11 @@ void MacondoBackend::timer() { i += preEndgameProgressMarker.length(); m_processStderr = QByteArray(m_processStderr.constData() + i, m_processStderr.size() - i); string numPlaysStr(m_processStderr.constData(), std::min(32, m_processStderr.size())); - int numPlays = 0; - parseInt(numPlaysStr, numPlays, nullptr); - std::stringstream message; - message << "Analyzed " << numPlays << "/" << m_preEndgamePlaysToAnalyze << " plays" << dots; - emit statusMessage(QString::fromStdString(message.str())); + parseInt(numPlaysStr, m_preEndgamePlaysAnalyzed, nullptr); } + std::stringstream message; + message << "Analyzed " << m_preEndgamePlaysAnalyzed << "/" << m_preEndgamePlaysToAnalyze << " plays" << dots; + emit statusMessage(QString::fromStdString(message.str())); } else { // no progress yet emit statusMessage(QString("Solving pre-endgame") + dots); @@ -584,6 +584,7 @@ void MacondoBackend::processStarted() { command << "-only-solve \"" << moveStr << "\" "; } } + command << "-endgameplies " << m_preEndgameOptions.endgamePlies << " "; command << "-disable-id true "; command << "-early-cutoff true "; command << "\n"; @@ -591,7 +592,13 @@ void MacondoBackend::processStarted() { } break; case Command::SolveEndgame: - m_process->write("endgame -plies 20\n"); + { + std::stringstream command; + command << "endgame "; + command << "-plies " << m_endgameOptions.maxPlies << " "; + command << "\n"; + m_process->write(command.str().c_str()); + } break; } } diff --git a/quacker/macondobackend.h b/quacker/macondobackend.h index c8bcfdf..8af328f 100644 --- a/quacker/macondobackend.h +++ b/quacker/macondobackend.h @@ -17,10 +17,12 @@ struct MacondoSimulateOptions { }; struct MacondoEndgameOptions { inline MacondoEndgameOptions() {} + int maxPlies = 15; }; struct MacondoPreEndgameOptions { // if empty, we'll get Macondo to analyze all possible moves Quackle::MoveList movesToAnalyze; + int endgamePlies = 4; inline MacondoPreEndgameOptions() {} }; @@ -64,6 +66,7 @@ private: QTimer *m_updateTimer = nullptr; int m_solveStatusDots = 3; int m_preEndgamePlaysToAnalyze = 0; + int m_preEndgamePlaysAnalyzed = 0; // is simulation being run right now? (i.e. has process been started & game been loaded?) bool m_runningSimulation = false; Quackle::Game *m_game; @@ -72,6 +75,7 @@ private: Command m_command = Command::None; Quackle::MoveList m_movesToLoad; MacondoPreEndgameOptions m_preEndgameOptions; + MacondoEndgameOptions m_endgameOptions; }; #endif -- cgit v1.2.3