Skip to content

Commit 5e87c9c

Browse files
committed
Merge branch 'protocoltimeout-0'
2 parents f771b54 + 5548dd7 commit 5e87c9c

File tree

11 files changed

+186
-13
lines changed

11 files changed

+186
-13
lines changed

docs/cutechess-cli.6

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,10 @@ Enable pondering if the engine supports it.
496496
Set the search depth limit.
497497
.It Ic nodes Ns = Ns Ar count
498498
Set the node count limit.
499+
.It Ic tscale Ns = Ns Ar factor
500+
Scale engine timeouts by
501+
.Ar factor .
502+
Only use this option if necessary.
499503
.El
500504
.Sh EXAMPLES
501505
Play ten games between two Sloppy engines with a time control of 40

projects/cli/res/doc/help.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,5 +221,7 @@ Engine options:
221221
nodes=N Set the node count limit to N nodes
222222
ponder Enable pondering if the engine supports it. By default
223223
pondering is disabled.
224+
tscale=FACTOR Scale engine timeouts by FACTOR. Only use this option
225+
if necessary.
224226
option.OPTION=VALUE Set custom option OPTION to value VALUE
225227

projects/cli/src/main.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,19 @@ bool parseEngine(const QStringList& args, EngineData& data)
144144
{
145145
data.config.setClaimsValidated(false);
146146
}
147+
// Scaling timeouts
148+
else if (name == "tscale")
149+
{
150+
bool ok = false;
151+
double value = val.toDouble(&ok);
152+
if (!ok || value < EngineConfiguration::timeoutScaleMin
153+
|| value > EngineConfiguration::timeoutScaleMax)
154+
{
155+
qWarning() << "Invalid timeout scale factor:" << val;
156+
return false;
157+
}
158+
data.config.setTimeoutScale(value);
159+
}
147160
// Time control (moves/time+increment)
148161
else if (name == "tc")
149162
{

projects/gui/src/engineconfigurationdlg.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ EngineConfigurationDialog::EngineConfigurationDialog(
6262

6363
ui->m_protocolCombo->addItems(EngineFactory::protocols());
6464

65+
ui->m_tscaleSpin->setStyleSheet("QDoubleSpinBox {color: black} \
66+
QDoubleSpinBox[value='1'] {color: #d0d0d0}");
67+
6568
ui->m_optionsView->setModel(m_engineOptionModel);
6669
connect(m_engineOptionModel, SIGNAL(modelReset()),
6770
this, SLOT(resizeColumns()));
@@ -99,6 +102,16 @@ EngineConfigurationDialog::EngineConfigurationDialog(
99102
}
100103
});
101104

105+
connect(ui->m_tscaleSpin,
106+
static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
107+
[=](double value)
108+
{
109+
if (value != 1.)
110+
ui->m_tscaleSpin->setStyleSheet("QDoubleSpinBox {color: black}");
111+
else
112+
ui->m_tscaleSpin->setStyleSheet("QDoubleSpinBox {color: #d0d0d0}");
113+
});
114+
102115
ui->m_tabs->setTabEnabled(1, false);
103116
ui->m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
104117
}
@@ -119,6 +132,7 @@ void EngineConfigurationDialog::applyEngineInformation(
119132
int i = ui->m_protocolCombo->findText(engine.protocol());
120133
ui->m_protocolCombo->setCurrentIndex(i);
121134

135+
ui->m_tscaleSpin->setValue(engine.timeoutScale());
122136
ui->m_initStringEdit->setPlainText(engine.initStrings().join("\n"));
123137

124138
if (engine.whiteEvalPov())
@@ -144,6 +158,7 @@ EngineConfiguration EngineConfigurationDialog::engineConfiguration()
144158
engine.setCommand(ui->m_commandEdit->text());
145159
engine.setWorkingDirectory(ui->m_workingDirEdit->text());
146160
engine.setProtocol(ui->m_protocolCombo->currentText());
161+
engine.setTimeoutScale(ui->m_tscaleSpin->value());
147162

148163
QString initStr(ui->m_initStringEdit->toPlainText());
149164
if (!initStr.isEmpty())

projects/gui/ui/engineconfigdlg.ui

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,7 @@
9898
</property>
9999
</widget>
100100
</item>
101-
<item row="3" column="1">
102-
<widget class="QComboBox" name="m_protocolCombo"/>
103-
</item>
104-
<item row="4" column="0">
101+
<item row="5" column="0">
105102
<widget class="QLabel" name="label_5">
106103
<property name="text">
107104
<string>&amp;Init Strings:</string>
@@ -111,14 +108,14 @@
111108
</property>
112109
</widget>
113110
</item>
114-
<item row="4" column="1">
111+
<item row="5" column="1">
115112
<widget class="QPlainTextEdit" name="m_initStringEdit">
116113
<property name="lineWrapMode">
117114
<enum>QPlainTextEdit::NoWrap</enum>
118115
</property>
119116
</widget>
120117
</item>
121-
<item row="5" column="1">
118+
<item row="6" column="1">
122119
<widget class="QCheckBox" name="m_whitePovCheck">
123120
<property name="enabled">
124121
<bool>false</bool>
@@ -131,6 +128,67 @@
131128
</property>
132129
</widget>
133130
</item>
131+
<item row="3" column="1">
132+
<layout class="QHBoxLayout" name="horizontalLayout_5">
133+
<item>
134+
<widget class="QComboBox" name="m_protocolCombo"/>
135+
</item>
136+
<item>
137+
<spacer name="horizontalSpacer_2">
138+
<property name="orientation">
139+
<enum>Qt::Horizontal</enum>
140+
</property>
141+
<property name="sizeHint" stdset="0">
142+
<size>
143+
<width>40</width>
144+
<height>20</height>
145+
</size>
146+
</property>
147+
</spacer>
148+
</item>
149+
<item>
150+
<widget class="QLabel" name="m_timeoutsLabel">
151+
<property name="text">
152+
<string>Scale Timeouts:</string>
153+
</property>
154+
</widget>
155+
</item>
156+
<item>
157+
<widget class="QDoubleSpinBox" name="m_tscaleSpin">
158+
<property name="toolTip">
159+
<string>Scale engine timeouts by this factor. Only use if necessary! Default: 1.00</string>
160+
</property>
161+
<property name="styleSheet">
162+
<string notr="true"/>
163+
</property>
164+
<property name="wrapping">
165+
<bool>false</bool>
166+
</property>
167+
<property name="buttonSymbols">
168+
<enum>QAbstractSpinBox::NoButtons</enum>
169+
</property>
170+
<property name="specialValueText">
171+
<string/>
172+
</property>
173+
<property name="correctionMode">
174+
<enum>QAbstractSpinBox::CorrectToNearestValue</enum>
175+
</property>
176+
<property name="minimum">
177+
<double>0.200000000000000</double>
178+
</property>
179+
<property name="maximum">
180+
<double>120.000000000000000</double>
181+
</property>
182+
<property name="singleStep">
183+
<double>0.200000000000000</double>
184+
</property>
185+
<property name="value">
186+
<double>1.000000000000000</double>
187+
</property>
188+
</widget>
189+
</item>
190+
</layout>
191+
</item>
134192
</layout>
135193
</widget>
136194
<widget class="QWidget" name="tab_2">

projects/lib/src/chessengine.cpp

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
#include <QStringRef>
2323
#include <QtAlgorithms>
2424
#include "engineoption.h"
25-
25+
#include <QSettings>
2626

2727
int ChessEngine::s_count = 0;
2828

@@ -76,6 +76,7 @@ ChessEngine::ChessEngine(QObject* parent)
7676
m_pinging(false),
7777
m_whiteEvalPov(false),
7878
m_pondering(false),
79+
m_timeoutScale(1.0),
7980
m_pingTimer(new QTimer(this)),
8081
m_quitTimer(new QTimer(this)),
8182
m_idleTimer(new QTimer(this)),
@@ -84,19 +85,19 @@ ChessEngine::ChessEngine(QObject* parent)
8485
m_restartMode(EngineConfiguration::RestartAuto)
8586
{
8687
m_pingTimer->setSingleShot(true);
87-
m_pingTimer->setInterval(15000);
88+
m_pingTimer->setInterval(defaultPingTimeout);
8889
connect(m_pingTimer, SIGNAL(timeout()), this, SLOT(onPingTimeout()));
8990

9091
m_quitTimer->setSingleShot(true);
91-
m_quitTimer->setInterval(5000);
92+
m_quitTimer->setInterval(defaultQuitTimeout);
9293
connect(m_quitTimer, SIGNAL(timeout()), this, SLOT(onQuitTimeout()));
9394

9495
m_idleTimer->setSingleShot(true);
95-
m_idleTimer->setInterval(15000);
96+
m_idleTimer->setInterval(defaultIdleTimeout);
9697
connect(m_idleTimer, SIGNAL(timeout()), this, SLOT(onIdleTimeout()));
9798

9899
m_protocolStartTimer->setSingleShot(true);
99-
m_protocolStartTimer->setInterval(35000);
100+
m_protocolStartTimer->setInterval(defaultProtocolStartTimeout);
100101
connect(m_protocolStartTimer, SIGNAL(timeout()),
101102
this, SLOT(onProtocolStartTimeout()));
102103
}
@@ -140,8 +141,26 @@ void ChessEngine::applyConfiguration(const EngineConfiguration& configuration)
140141

141142
m_whiteEvalPov = configuration.whiteEvalPov();
142143
m_pondering = configuration.pondering();
144+
m_timeoutScale = configuration.timeoutScale();
143145
m_restartMode = configuration.restartMode();
144146
setClaimsValidated(configuration.areClaimsValidated());
147+
148+
// Read protocol timeouts from QSettings.
149+
// Scale timer intervals according to m_timeoutScale
150+
QSettings settings;
151+
settings.beginGroup("Timing");
152+
153+
int pingTimeout = m_timeoutScale * settings.value("PingTimeout", defaultPingTimeout).toInt();
154+
int quitTimeout = m_timeoutScale * settings.value("QuitTimeout", defaultQuitTimeout).toInt();
155+
int idleTimeout = m_timeoutScale * settings.value("IdleTimeout", defaultIdleTimeout).toInt();
156+
double protocolStartTimeout = m_timeoutScale * settings.value("ProtocolStartTimeout",
157+
defaultProtocolStartTimeout).toInt();
158+
settings.endGroup();
159+
160+
m_pingTimer->setInterval(pingTimeout);
161+
m_quitTimer->setInterval(quitTimeout);
162+
m_idleTimer->setInterval(idleTimeout);
163+
m_protocolStartTimer->setInterval(protocolStartTimeout);
145164
}
146165

147166
void ChessEngine::addOption(EngineOption* option)

projects/lib/src/chessengine.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ class LIB_EXPORT ChessEngine : public ChessPlayer
4444
Q_OBJECT
4545

4646
public:
47+
static constexpr int defaultPingTimeout = 15000;
48+
static constexpr int defaultQuitTimeout = 5000;
49+
static constexpr int defaultIdleTimeout = 15000;
50+
static constexpr int defaultProtocolStartTimeout = 35000;
51+
4752
/*!
4853
* The write mode used by \a write() when the engine is
4954
* being pinged. This doesn't affect the IO device's
@@ -77,7 +82,7 @@ class LIB_EXPORT ChessEngine : public ChessPlayer
7782
void start();
7883

7984
/*! Applies \a configuration to the engine. */
80-
void applyConfiguration(const EngineConfiguration& configuration);
85+
virtual void applyConfiguration(const EngineConfiguration& configuration);
8186

8287
/*!
8388
* Sends a ping message (an echo request) to the engine to
@@ -289,6 +294,7 @@ class LIB_EXPORT ChessEngine : public ChessPlayer
289294
bool m_pinging;
290295
bool m_whiteEvalPov;
291296
bool m_pondering;
297+
double m_timeoutScale;
292298
QTimer* m_pingTimer;
293299
QTimer* m_quitTimer;
294300
QTimer* m_idleTimer;

projects/lib/src/engineconfiguration.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ EngineConfiguration::EngineConfiguration()
2727
m_whiteEvalPov(false),
2828
m_pondering(false),
2929
m_validateClaims(true),
30+
m_timeoutScale(1.0),
3031
m_restartMode(RestartAuto)
3132
{
3233
}
@@ -41,6 +42,7 @@ EngineConfiguration::EngineConfiguration(const QString& name,
4142
m_whiteEvalPov(false),
4243
m_pondering(false),
4344
m_validateClaims(true),
45+
m_timeoutScale(1.0),
4446
m_restartMode(RestartAuto)
4547
{
4648
}
@@ -50,6 +52,7 @@ EngineConfiguration::EngineConfiguration(const QVariant& variant)
5052
m_whiteEvalPov(false),
5153
m_pondering(false),
5254
m_validateClaims(true),
55+
m_timeoutScale(1.0),
5356
m_restartMode(RestartAuto)
5457
{
5558
const QVariantMap map = variant.toMap();
@@ -60,6 +63,13 @@ EngineConfiguration::EngineConfiguration(const QVariant& variant)
6063
setStderrFile(map["stderrFile"].toString());
6164
setProtocol(map["protocol"].toString());
6265

66+
bool ok = true;
67+
if (map.contains("timeoutScaleFactor"))
68+
{
69+
double tscale = map["timeoutScaleFactor"].toDouble(&ok);
70+
setTimeoutScale(ok ? tscale : 1.0);
71+
}
72+
6373
if (map.contains("initStrings"))
6474
setInitStrings(map["initStrings"].toStringList());
6575
if (map.contains("whitepov"))
@@ -109,6 +119,7 @@ EngineConfiguration::EngineConfiguration(const EngineConfiguration& other)
109119
m_whiteEvalPov(other.m_whiteEvalPov),
110120
m_pondering(other.m_pondering),
111121
m_validateClaims(other.m_validateClaims),
122+
m_timeoutScale(other.m_timeoutScale),
112123
m_restartMode(other.m_restartMode)
113124
{
114125
const auto options = other.options();
@@ -133,6 +144,7 @@ EngineConfiguration& EngineConfiguration::operator=(EngineConfiguration&& other)
133144
m_whiteEvalPov = other.m_whiteEvalPov;
134145
m_pondering = other.m_pondering;
135146
m_validateClaims = other.m_validateClaims;
147+
m_timeoutScale = other.m_timeoutScale;
136148
m_restartMode = other.m_restartMode;
137149
m_options = other.m_options;
138150

@@ -155,6 +167,7 @@ QVariant EngineConfiguration::toVariant() const
155167
map.insert("workingDirectory", m_workingDirectory);
156168
map.insert("stderrFile", m_stderrFile);
157169
map.insert("protocol", m_protocol);
170+
map.insert("timeoutScaleFactor", m_timeoutScale);
158171

159172
if (!m_initStrings.isEmpty())
160173
map.insert("initStrings", m_initStrings);
@@ -361,6 +374,16 @@ void EngineConfiguration::setClaimsValidated(bool validate)
361374
m_validateClaims = validate;
362375
}
363376

377+
double EngineConfiguration::timeoutScale() const
378+
{
379+
return m_timeoutScale;
380+
}
381+
382+
void EngineConfiguration::setTimeoutScale(double value)
383+
{
384+
m_timeoutScale = qBound(timeoutScaleMin, value, timeoutScaleMax);
385+
}
386+
364387
EngineConfiguration& EngineConfiguration::operator=(const EngineConfiguration& other)
365388
{
366389
if (this != &other)
@@ -370,6 +393,7 @@ EngineConfiguration& EngineConfiguration::operator=(const EngineConfiguration& o
370393
m_workingDirectory = other.m_workingDirectory;
371394
m_stderrFile = other.m_stderrFile;
372395
m_protocol = other.m_protocol;
396+
m_timeoutScale = other.m_timeoutScale;
373397
m_arguments = other.m_arguments;
374398
m_initStrings = other.m_initStrings;
375399
m_variants = other.m_variants;

0 commit comments

Comments
 (0)