summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2025-08-22 17:23:26 -0400
committerpommicket <pommicket@gmail.com>2025-08-22 17:23:26 -0400
commit58043157260420418177510a03dc59c28ad58c32 (patch)
tree1af92f04274b6ee979e4956947ee348baacf3def
parent31c6114fb3a7db322fba89bb9021c694da248384 (diff)
Macondo endgame options
-rw-r--r--quacker/macondo.cpp18
-rw-r--r--quacker/macondo.h6
-rw-r--r--quacker/macondobackend.cpp16
-rw-r--r--quacker/macondobackend.h2
4 files changed, 33 insertions, 9 deletions
diff --git a/quacker/macondo.cpp b/quacker/macondo.cpp
index 36b7c38..0cd0021 100644
--- a/quacker/macondo.cpp
+++ b/quacker/macondo.cpp
@@ -1,8 +1,3 @@
-/*
-TODO:
-- more endgame options
-*/
-
#include "macondo.h"
#include "macondobackend.h"
@@ -93,7 +88,16 @@ Macondo::Macondo(Quackle::Game *game) : View() {
m_endgameMaxPlies = new QSpinBox;
m_endgameMaxPlies->setRange(1, 100);
m_endgameMaxPlies->setValue(settings.value("macondo/endgameMaxPlies", 15).toInt());
+ m_firstWinOptimization = new QCheckBox(tr("First-win optimization"));
+ m_firstWinOptimization->setToolTip(tr("Stop analysis as soon as a win is found. Speeds up analysis, but no longer ensures the best possible spread."));
+ m_firstWinOptimization->setChecked(settings.value("macondo/firstWinOptimization", false).toBool());
+ m_preventSlowRoll = new QCheckBox(tr("Prevent slow-roll"));
+ m_preventSlowRoll->setChecked(settings.value("macondo/preventSlowRoll", false).toBool());
+ m_preventSlowRoll->setToolTip(tr("Skip analyzing \"slow-plays\" when seemingly better options exist. This speeds up the solver, but may miss optimal endgame sequences."));
endgameLayout->addLayout(new LabelLayout(tr("Plies"), m_endgameMaxPlies));
+ endgameLayout->addWidget(m_firstWinOptimization);
+ endgameLayout->addWidget(m_preventSlowRoll);
+
QVBoxLayout *layout = new QVBoxLayout(this);
layout->setAlignment(Qt::AlignTop);
layout->addLayout(execPathLayout);
@@ -113,6 +117,8 @@ Macondo::~Macondo() {
settings.setValue("macondo/earlyCutoff", m_earlyCutoff->isChecked());
settings.setValue("macondo/skipNonEmptying", m_skipNonEmptying->isChecked());
settings.setValue("macondo/skipTieBreaker", m_skipTieBreaker->isChecked());
+ settings.setValue("macondo/firstWinOptimization", m_firstWinOptimization->isChecked());
+ settings.setValue("macondo/preventSlowRoll", m_preventSlowRoll->isChecked());
delete m_backend;
}
@@ -204,6 +210,8 @@ void Macondo::solve() {
} else {
MacondoEndgameOptions options;
options.maxPlies = m_endgameMaxPlies->value();
+ options.firstWinOptimization = m_firstWinOptimization->isChecked();
+ options.preventSlowRoll = m_preventSlowRoll->isChecked();
m_backend->solveEndgame(options);
}
m_isSolving = true;
diff --git a/quacker/macondo.h b/quacker/macondo.h
index dfd9d97..d56a577 100644
--- a/quacker/macondo.h
+++ b/quacker/macondo.h
@@ -47,11 +47,16 @@ private:
void connectBackendSignals();
bool checkExecPath();
void updateSolveButton();
+
// == options ==
QCheckBox *m_useMacondo;
QLineEdit *m_execPath;
+
// == endgame options ==
QSpinBox *m_endgameMaxPlies;
+ QCheckBox *m_firstWinOptimization;
+ QCheckBox *m_preventSlowRoll;
+
// == pre-endgame options ===
QCheckBox *m_generatedMovesOnly;
QCheckBox *m_earlyCutoff;
@@ -59,6 +64,7 @@ private:
QCheckBox *m_skipTieBreaker;
QLineEdit *m_opponentRack;
QSpinBox *m_preEndgameMaxPlies;
+
QPushButton *m_solve;
Quackle::Game *m_game;
MacondoBackend *m_backend;
diff --git a/quacker/macondobackend.cpp b/quacker/macondobackend.cpp
index 47d3465..f9d6190 100644
--- a/quacker/macondobackend.cpp
+++ b/quacker/macondobackend.cpp
@@ -18,7 +18,8 @@ using std::vector;
// We can change these whenever Macondo's output format changes.
static const QByteArray simPlaysStartMarker("Play Leave Score Win% Equity");
static const QByteArray simPlaysEndMarker("Iterations:");
-static const QByteArray endgameSpreadDiffMarker("Best sequence has a spread difference (value) of ");
+static const QByteArray endgameSpreadDiffMarker1("Best sequence has a spread difference (value) of ");
+static const QByteArray endgameSpreadDiffMarker2("Spread diff: "); // this is used if first-win-optim is enabled
static const QByteArray endgameFinalSpreadMarker("Final spread after seq: ");
static const QByteArray endgameBestSeqMarker("Best sequence:\n");
// marks current ply depth during endgame solving
@@ -268,7 +269,9 @@ static Quackle::MoveList extractSimMoves(QByteArray &processOutput) {
}
static bool extractEndgameMove(QByteArray &processOutput, Quackle::Move &move) {
- int spreadDiffMarkerIdx = processOutput.indexOf(endgameSpreadDiffMarker);
+ const QByteArray &spreadDiffMarker = processOutput.contains(endgameSpreadDiffMarker1)
+ ? endgameSpreadDiffMarker1 : endgameSpreadDiffMarker2;
+ int spreadDiffMarkerIdx = processOutput.indexOf(spreadDiffMarker);
if (spreadDiffMarkerIdx < 0) {
// delete all output except for the last line (which may be incomplete)
int lastLineIndex = processOutput.lastIndexOf('\n');
@@ -279,7 +282,7 @@ static bool extractEndgameMove(QByteArray &processOutput, Quackle::Move &move) {
}
return false;
}
- int spreadDiffStart = spreadDiffMarkerIdx + endgameSpreadDiffMarker.length();
+ int spreadDiffStart = spreadDiffMarkerIdx + spreadDiffMarker.length();
int spreadDiffEnd = processOutput.indexOf("\n", spreadDiffStart);
if (spreadDiffEnd < 0) return false;
int spreadDiff = -999;
@@ -418,7 +421,10 @@ void MacondoBackend::timer() {
data = m_process->readAllStandardOutput();
anyNewOutput |= data.size() != 0;
m_processOutput.append(data);
- //printf("%.*s",data.size(), data.constData());
+ if (false) {
+ // print Macondo stdout
+ printf("%.*s",data.size(), data.constData());
+ }
fflush(stdout);
}
const char *dots = updateDots(anyNewOutput);
@@ -600,6 +606,8 @@ void MacondoBackend::processStarted() {
{
std::stringstream command;
command << "endgame ";
+ command << "-first-win-optim " << (m_endgameOptions.firstWinOptimization ? "true" : "false") << " ";
+ command << "-prevent-slowroll " << (m_endgameOptions.preventSlowRoll ? "true" : "false") << " ";
command << "-plies " << m_endgameOptions.maxPlies << " ";
command << "\n";
m_process->write(command.str().c_str());
diff --git a/quacker/macondobackend.h b/quacker/macondobackend.h
index 048c787..c35102b 100644
--- a/quacker/macondobackend.h
+++ b/quacker/macondobackend.h
@@ -17,6 +17,8 @@ struct MacondoSimulateOptions {
};
struct MacondoEndgameOptions {
inline MacondoEndgameOptions() {}
+ bool firstWinOptimization = false;
+ bool preventSlowRoll = false;
int maxPlies = 15;
};
struct MacondoPreEndgameOptions {