summaryrefslogtreecommitdiff
path: root/quacker
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2025-08-12 23:04:05 -0400
committerpommicket <pommicket@gmail.com>2025-08-12 23:04:05 -0400
commite43c01bd11560561daa771463c57442c3b8a761d (patch)
treea040ea23eaf10d8a7362f523777a8b61e8b55041 /quacker
parenta1a21037c465a1a01b2ca13b70f89becfc93546e (diff)
Integrate Macondo into move chooser
Diffstat (limited to 'quacker')
-rw-r--r--quacker/macondo.cpp37
-rw-r--r--quacker/macondo.h26
-rw-r--r--quacker/macondobackend.cpp21
-rw-r--r--quacker/macondobackend.h6
-rw-r--r--quacker/quacker.cpp28
-rw-r--r--quacker/quacker.h12
6 files changed, 81 insertions, 49 deletions
diff --git a/quacker/macondo.cpp b/quacker/macondo.cpp
index c089b42..55d5deb 100644
--- a/quacker/macondo.cpp
+++ b/quacker/macondo.cpp
@@ -5,45 +5,48 @@
#include <QGridLayout>
#include <QPushButton>
+#include <QCheckBox>
-Macondo::Macondo(Quackle::Game *game) : QWidget() {
+Macondo::Macondo(Quackle::Game *game, MoveBox *moveBox) : View() {
m_game = game;
+ m_moveBox = moveBox;
QGridLayout *layout = new QGridLayout(this);
- m_moveBox = new MoveBox;
- m_simulateButton = new QPushButton(tr("Simulate"));
+ m_useMacondo = new QCheckBox(tr("Use Macondo for 'Simulate'"));
layout->setAlignment(Qt::AlignTop);
- layout->addWidget(m_simulateButton, 0, 0);
- layout->addWidget(m_moveBox, 1, 0);
+ layout->addWidget(m_useMacondo, 0, 0);
const char *home = getenv("HOME");
// TODO: configurable path
std::string execPath = home ? home : "/";
execPath += "/apps/macondo/macondo";
initOptions = std::make_unique<MacondoInitOptions>(execPath);
m_backend = new MacondoBackend(game, *initOptions);
- connect(m_simulateButton, SIGNAL(clicked()), this, SLOT(simulate()));
- connect(m_backend, SIGNAL(gotSimMoves(const Quackle::MoveList &)), this, SLOT(gotSimMoves(const Quackle::MoveList &)));
+ connect(m_backend, SIGNAL(gotSimMoves(const Quackle::MoveList *)), this, SIGNAL(newMoves(const Quackle::MoveList *)));
}
-Macondo::~Macondo() {}
+Macondo::~Macondo() {
+ delete m_backend;
+}
void Macondo::simulate() {
+ if (m_backend->isRunning()) {
+ // stop analysis
+ stop();
+ return;
+ }
MacondoSimulateOptions options;
m_backend->simulate(options);
- m_moveBox->positionChanged(&m_game->currentPosition());
}
-
void Macondo::setGame(Quackle::Game *game) {
delete m_backend;
m_backend = new MacondoBackend(game, *initOptions);
m_game = game;
}
-void Macondo::gotSimMoves(const Quackle::MoveList &moves) {
- m_moveBox->movesChanged(&moves);
- /*printf("got %zu moves\n",moves.size());
- for (const Quackle::Move &move: moves) {
- std::cout << move << std::endl;
- }
- */
+void Macondo::stop() {
+ m_backend->stop();
+}
+
+bool Macondo::useForSimulation() const {
+ return m_useMacondo->isChecked();
}
diff --git a/quacker/macondo.h b/quacker/macondo.h
index 18441b5..de12fe1 100644
--- a/quacker/macondo.h
+++ b/quacker/macondo.h
@@ -1,9 +1,10 @@
#ifndef MACONDO_H
#define MACONDO_H
-#include <QWidget>
+#include "view.h"
+#include "game.h"
-class QPushButton;
+class QCheckBox;
class QTimer;
namespace Quackle {
class Game;
@@ -12,27 +13,26 @@ namespace Quackle {
class MacondoBackend;
struct MacondoInitOptions;
class MoveBox;
-class Macondo : public QWidget {
+class Macondo : public View {
Q_OBJECT
public:
- Macondo(Quackle::Game *);
+ Macondo(Quackle::Game *, MoveBox *);
~Macondo();
void setGame(Quackle::Game *);
+ // stop current analysis
+ void stop();
+ // should Macondo be used for simulations?
+ bool useForSimulation() const;
+signals:
+ void newMoves(const Quackle::MoveList *);
public slots:
void simulate();
-private slots:
- void gotSimMoves(const Quackle::MoveList &moves);
private:
- enum class Command {
- None,
- Simulate,
- Solve,
- };
- QPushButton *m_simulateButton;
+ QCheckBox *m_useMacondo;
Quackle::Game *m_game;
MacondoBackend *m_backend;
+ Quackle::MoveList m_moves;
int m_viewingPlyNumber = 0;
- Command m_command = Command::None;
MoveBox *m_moveBox;
std::unique_ptr<MacondoInitOptions> initOptions;
};
diff --git a/quacker/macondobackend.cpp b/quacker/macondobackend.cpp
index d109d53..2712512 100644
--- a/quacker/macondobackend.cpp
+++ b/quacker/macondobackend.cpp
@@ -218,7 +218,7 @@ void MacondoBackend::timer() {
if (!moves.empty()) {
// at this point the GCG is definitely fully loaded
removeTempGCG();
- emit gotSimMoves(moves);
+ emit gotSimMoves(&moves);
}
}
break;
@@ -270,11 +270,12 @@ void MacondoBackend::loadGCG() {
}
void MacondoBackend::killProcess() {
- if (m_process) {
- m_process->kill();
- m_process->deleteLater();
- m_process = nullptr;
- }
+ // This will give an annoying "destroyed while process running" message,
+ // but there's no way of avoiding it while keeping this method synchronous.
+ // (Destroying the process while it's running does what we want anyways,
+ // i.e., kills it)
+ delete m_process;
+ m_process = nullptr;
}
void MacondoBackend::processFinished(int, QProcess::ExitStatus) {
@@ -293,3 +294,11 @@ MacondoBackend::~MacondoBackend() {
m_process->kill();
}
}
+
+
+void MacondoBackend::stop() {
+ killProcess();
+ removeTempGCG();
+ m_runningSimulation = false;
+ m_command = Command::None;
+}
diff --git a/quacker/macondobackend.h b/quacker/macondobackend.h
index f61ae11..9d327d2 100644
--- a/quacker/macondobackend.h
+++ b/quacker/macondobackend.h
@@ -28,8 +28,11 @@ public:
void simulate(const MacondoSimulateOptions &);
~MacondoBackend();
std::string getSimResults();
+ inline bool isRunning() const { return m_command != Command::None; }
+ // stop current Macondo analysis
+ void stop();
signals:
- void gotSimMoves(const Quackle::MoveList &moves);
+ void gotSimMoves(const Quackle::MoveList *moves);
private slots:
void processStarted();
void processFinished(int, QProcess::ExitStatus);
@@ -47,6 +50,7 @@ private:
std::string m_tempGCG;
QProcess *m_process = nullptr;
QTimer *m_updateTimer = nullptr;
+ // is simulation being run right now? (i.e. has process been started & game been loaded?)
bool m_runningSimulation = false;
Quackle::Game *m_game;
QByteArray m_processOutput;
diff --git a/quacker/quacker.cpp b/quacker/quacker.cpp
index c386968..6bb25fc 100644
--- a/quacker/quacker.cpp
+++ b/quacker/quacker.cpp
@@ -619,18 +619,21 @@ void TopLevel::updatePositionViews()
updateListerDialogWithRack();
}
-void TopLevel::updateMoveViews()
+void TopLevel::updateMoveViews(const Quackle::MoveList *providedList)
{
- if (m_simulator->hasSimulationResults())
+ Quackle::MoveList list;
+ if (providedList) {
+ list = *providedList;
+ }
+ else if (m_simulator->hasSimulationResults())
{
- const Quackle::MoveList& moveList = m_simulator->moves(/* prune */ true, /* sort by win */ true);
- emit movesChanged(&moveList);
+ list = m_simulator->moves(/* prune */ true, /* sort by win */ true);
}
else
{
- const Quackle::MoveList moveList = m_game->currentPosition().moves();
- emit movesChanged(&moveList);
+ list = m_game->currentPosition().moves();
}
+ emit movesChanged(&list);
m_simulateAction->setEnabled(!m_game->currentPosition().moves().empty());
m_simulateDetailsAction->setEnabled(!m_game->currentPosition().moves().empty());
@@ -1067,6 +1070,15 @@ void TopLevel::simulateToggled(bool startSimulation)
if (!m_game->hasPositions())
return;
+ if (m_macondo->useForSimulation()) {
+ if (startSimulation) {
+ m_macondo->simulate();
+ } else {
+ m_macondo->stop();
+ }
+ return;
+ }
+
simulate(startSimulation);
if (startSimulation)
@@ -2003,7 +2015,9 @@ void TopLevel::createWidgets()
m_history = new History;
plugIntoHistoryMatrix(m_history);
- m_macondo = new Macondo(m_game);
+ m_macondo = new Macondo(m_game, m_moveBox);
+ plugIntoMatrix(m_macondo);
+ connect(m_macondo, SIGNAL(newMoves(const Quackle::MoveList *)), this, SLOT(updateMoveViews(const Quackle::MoveList *)));
m_tabWidget = new QTabWidget;
m_tabWidget->addTab(m_history, tr("Histor&y"));
diff --git a/quacker/quacker.h b/quacker/quacker.h
index cb47023..b9a9602 100644
--- a/quacker/quacker.h
+++ b/quacker/quacker.h
@@ -66,6 +66,7 @@ class BaseView;
class HistoryView;
class Letterbox;
class ListerDialog;
+class MoveBox;
class QuackerSettings;
class Settings;
class SimViewer;
@@ -200,10 +201,6 @@ protected slots:
// update *positional* views - emit positionChanged
void updatePositionViews();
- // updates move views from either simulation results if available
- // or kibitzed moves
- void updateMoveViews();
-
// update history views when a new position is added
void updateHistoryViews();
@@ -232,6 +229,11 @@ protected slots:
void startBirthday();
void birthdayBash();
void birthdayGram(int index, bool on);
+public slots:
+ // updates move views from either provided list,
+ // or simulation results if available,
+ // or kibitzed moves
+ void updateMoveViews(const Quackle::MoveList *list = nullptr);
signals:
// emitted when views (eg board) should update based on the
@@ -321,7 +323,7 @@ private:
HistoryView *m_dashboard;
QWidget *m_choicesWidget;
- View *m_moveBox;
+ MoveBox *m_moveBox;
View *m_noteEditor;
QFrame *m_frameWidget;