Commit 68bbbf5d authored by Ian Wadham's avatar Ian Wadham

Change version to 4.3. Add Play Next Level action. Implement Instant Replay,...

Change version to 4.3.  Add Play Next Level action.  Implement Instant Replay, Replay Last Level, Show A Solution and Replay Any Level actions.  Finish implementing interruption of a demo or replay.  Disable several logging messages and remove some obsolete code.

svn path=/trunk/KDE/kdegames/kgoldrunner/; revision=962084
parent a767cd7f
......@@ -211,6 +211,13 @@ void KGoldrunner::setupActions()
gameMapper->setMapping (a, NEW);
a->setText (i18n ("&New Game..."));
a = gameAction ("next_level", NEXT_LEVEL,
i18n ("Pla&y Next Level"),
i18n ("Play next level."),
i18n ("Try the next level in the game "
"you are playing."),
Qt::Key_Y);
a = KStandardGameAction::load (gameMapper, SLOT(map()), this);
actionCollection()->addAction (a->objectName(), a);
gameMapper->setMapping (a, LOAD);
......@@ -258,27 +265,39 @@ void KGoldrunner::setupActions()
a = KStandardGameAction::solve (gameMapper, SLOT (map()), this);
actionCollection()->addAction (a->objectName(), a);
gameMapper->setMapping (a, SOLVE);
a->setToolTip (i18n ("Show how to win this level"));
a->setText (i18n ("&Show A Solution"));
a->setToolTip (i18n ("Show how to win this level."));
a->setWhatsThis (i18n ("Play a recording of how to win this level, if "
"there is one available."));
a = gameAction ("instant_replay", INSTANT_REPLAY,
i18n ("&Instant Replay"),
i18n ("Instant replay"),
i18n ("Show a recording of the latest level played."),
QKeySequence()); // No key assigned.
i18n ("Instant replay."),
i18n ("Show a recording of the level "
"you are currently playing."),
Qt::Key_R);
a = gameAction ("replay_last", REPLAY_LAST,
i18n ("Replay &Last Level"),
i18n ("Replay last level."),
i18n ("Show a recording of the last level you "
"played and finished, regardless of whether "
"you won or lost."),
Qt::Key_A);
a = gameAction ("replay_any", REPLAY_ANY,
i18n ("&Replay Any Level"),
i18n ("Replay any level"),
i18n ("Replay any level."),
i18n ("Show a recording of any level you have "
"played so far."),
i18n ("Show a recording of any level played so far."),
QKeySequence()); // No key assigned.
killHero = gameAction ("kill_hero", KILL_HERO,
i18n ("&Kill Hero"),
i18n ("Kill Hero"),
i18n ("Kill Hero."),
i18n ("Kill the hero, in case he finds himself in "
"a situation from which he cannot escape"),
"a situation from which he cannot escape."),
Qt::Key_Q);
// Quit
......@@ -300,8 +319,8 @@ void KGoldrunner::setupActions()
QAction * ed = editAction ("create_level", CREATE_LEVEL,
i18n ("&Create Level"),
i18n ("Create level"),
i18n ("Create a completely new level"));
i18n ("Create level."),
i18n ("Create a completely new level."));
ed->setIcon (KIcon ("document-new"));
ed->setIconText (i18n ("Create"));
......@@ -377,8 +396,8 @@ void KGoldrunner::setupActions()
#ifdef ENABLE_SOUND_SUPPORT
KToggleAction * setSounds = settingAction ("options_sounds", PLAY_SOUNDS,
i18n ("&Play Sounds"),
i18n ("Play sound effects"),
i18n ("Play sound effects during the game"));
i18n ("Play sound effects."),
i18n ("Play sound effects during the game."));
bool soundOnOff = gameGroup.readEntry ("Sound", false);
setSounds->setChecked (soundOnOff);
......@@ -400,15 +419,15 @@ void KGoldrunner::setupActions()
KToggleAction * setMouse = settingAction ("mouse_mode", MOUSE,
i18n ("&Mouse Controls Hero"),
i18n ("Mouse controls hero"),
i18n ("Mouse controls hero."),
i18n ("Use the mouse to control "
"the hero's moves"));
"the hero's moves."));
KToggleAction * setKeyboard = settingAction ("keyboard_mode", KEYBOARD,
i18n ("&Keyboard Controls Hero"),
i18n ("Keyboard controls hero"),
i18n ("Keyboard controls hero."),
i18n ("Use the keyboard to control "
"the hero's moves"));
"the hero's moves."));
KToggleAction * setLaptop = settingAction ("laptop_mode", LAPTOP,
i18n ("&Hybrid Control (Laptop)"),
......@@ -434,32 +453,32 @@ void KGoldrunner::setupActions()
KToggleAction * nSpeed = settingAction ("normal_speed", NORMAL_SPEED,
i18n ("Normal Speed"),
i18n ("Set normal speed"),
i18n ("Set normal game speed (12 units)"));
i18n ("Set normal speed."),
i18n ("Set normal game speed (12 units)."));
KToggleAction * bSpeed = settingAction ("beginner_speed",
BEGINNER_SPEED,
i18n ("Beginner Speed"),
i18n ("Set beginners' speed"),
i18n ("Set beginners' game speed (6 units)"));
i18n ("Set beginners' speed."),
i18n ("Set beginners' game speed (6 units)."));
KToggleAction * cSpeed = settingAction ("champion_speed",
CHAMPION_SPEED,
i18n ("Champion Speed"),
i18n ("Set champions' speed"),
i18n ("Set champions' game speed (18 units)")
i18n ("Set champions' speed."),
i18n ("Set champions' game speed (18 units).")
);
a = gameAction ("increase_speed", INC_SPEED,
i18n ("Increase Speed"),
i18n ("Increase speed"),
i18n ("Increase the game speed by one unit"),
i18n ("Increase speed."),
i18n ("Increase the game speed by one unit."),
Qt::Key_Plus);
a = gameAction ("decrease_speed", DEC_SPEED,
i18n ("Decrease Speed"),
i18n ("Decrease speed"),
i18n ("Decrease the game speed by one unit"),
i18n ("Decrease speed."),
i18n ("Decrease the game speed by one unit."),
Qt::Key_Minus);
QActionGroup* speedGrp = new QActionGroup (this);
......@@ -527,7 +546,7 @@ void KGoldrunner::setupActions()
keyControl ("bug_fix", i18n ("Test Bug Fix"), Qt::Key_B, BUG_FIX);
keyControl ("show_positions", i18n ("Show Positions"), Qt::Key_W, S_POSNS);
keyControl ("logging", i18n ("Start Logging"), Qt::Key_G, LOGGING);
keyControl ("show_hero", i18n ("Show Hero"), Qt::Key_R, S_HERO);
keyControl ("show_hero", i18n ("Show Hero"), Qt::Key_E, S_HERO);
keyControl ("show_obj", i18n ("Show Object"), Qt::Key_Slash, S_OBJ);
keyControl ("show_enemy_0", i18n ("Show Enemy") + '0', Qt::Key_0, ENEMY_0);
......
<?xml version="1.0" encoding="UTF-8"?>
<gui name="kgoldrunner"
version="10"
version="12"
xmlns="http://www.kde.org/standards/kxmlgui/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.kde.org/standards/kxmlgui/1.0
http://www.kde.org/standards/kxmlgui/1.0/kxmlgui.xsd">
<MenuBar>
<Menu name="game" >
<Action append="save_merge" name="save_edits" />
<Action append="misc_merge" name="kill_hero" />
<Action append="new_merge" name="next_level" />
<Action append="save_merge" name="save_edits" />
<Action append="misc_merge" name="kill_hero" />
</Menu>
<Menu name="move" >
<Action append="save_merge" name="instant_replay" />
<Action append="save_merge" name="replay_last" />
<Action append="save_merge" name="replay_any" />
</Menu>
<Menu name="editor" > <text>&amp;Editor</text>
<Action name="create_level" />
<Action name="edit_any" />
<Action name="create_level" />
<Action name="edit_any" />
<Separator/>
<Action name="save_edits" />
<Action name="move_level" />
<Action name="delete_level" />
<Action name="save_edits" />
<Action name="move_level" />
<Action name="delete_level" />
<Separator/>
<Action name="create_game" />
<Action name="edit_game" />
<Action name="create_game" />
<Action name="edit_game" />
</Menu>
<Menu name="themes" > <text>&amp;Themes</text>
<ActionList name="theme_list" />
<ActionList name="theme_list" />
</Menu>
<Menu name="settings" >
<Action append="save_merge" name="options_sounds" />
<Action append="save_merge" name="options_demo" />
<Action append="save_merge" name="options_sounds" />
<Action append="save_merge" name="options_demo" />
<Separator append="save_merge" />
<Action append="save_merge" name="mouse_mode" />
<Action append="save_merge" name="keyboard_mode" />
<Action append="save_merge" name="laptop_mode" />
<Action append="save_merge" name="mouse_mode" />
<Action append="save_merge" name="keyboard_mode" />
<Action append="save_merge" name="laptop_mode" />
<Separator append="save_merge" />
<Action append="save_merge" name="normal_speed" />
<Action append="save_merge" name="beginner_speed" />
<Action append="save_merge" name="champion_speed" />
<Action append="save_merge" name="increase_speed" />
<Action append="save_merge" name="decrease_speed" />
</Menu>
<Menu name="help" >
<Action name="tutorial" />
<Action append="save_merge" name="normal_speed" />
<Action append="save_merge" name="beginner_speed" />
<Action append="save_merge" name="champion_speed" />
<Action append="save_merge" name="increase_speed" />
<Action append="save_merge" name="decrease_speed" />
</Menu>
</MenuBar>
......@@ -67,19 +66,19 @@
</ToolBar>
<ActionProperties>
<Action shortcut="P; Escape" name="game_pause" />
<Action shortcut="S" name="game_save" />
<Action shortcut="Ctrl+S" name="save_edits" />
<Action shortcut="P; Escape" name="game_pause" />
<Action shortcut="S" name="game_save" />
<Action shortcut="Ctrl+S" name="save_edits" />
<Action shortcut="Up; I" name="move_up" />
<Action shortcut="Right; L" name="move_right" />
<Action shortcut="Down; K" name="move_down" />
<Action shortcut="Left; J" name="move_left" />
<Action shortcut="Space" name="stop" />
<Action shortcut="Z; U" name="dig_left" />
<Action shortcut="C; O" name="dig_right" />
<Action shortcut="Up; I" name="move_up" />
<Action shortcut="Right; L" name="move_right" />
<Action shortcut="Down; K" name="move_down" />
<Action shortcut="Left; J" name="move_left" />
<Action shortcut="Space" name="stop" />
<Action shortcut="Z; U" name="dig_left" />
<Action shortcut="C; O" name="dig_right" />
<Action shortcut="+" name="increase_speed" />
<Action shortcut="-" name="decrease_speed" />
<Action shortcut="+" name="increase_speed" />
<Action shortcut="-" name="decrease_speed" />
</ActionProperties>
</gui>
......@@ -295,10 +295,11 @@ void KGrLGDialog::lgSelect (QListWidgetItem * item)
*******************************************************************************/
void KGrMessage::information (QWidget * parent,
const QString &caption, const QString &text)
const QString & caption, const QString & text,
const QString & dontShowAgain)
{
// KDE does word-wrapping and will observe "\n" line-breaks.
KMessageBox::information (parent, text, caption);
KMessageBox::information (parent, text, caption, dontShowAgain);
}
int KGrMessage::warning (QWidget * parent, const QString &caption,
......
This diff is collapsed.
......@@ -74,11 +74,7 @@ public slots:
void incScore (const int n); // Update the score.
private:
// TODO - Only startAnyLevel() is used (from newGame...).
void startLevelOne(); // Start any game from level 1.
void startAnyLevel(); // Start any game from any level.
void startNextLevel(); // Start next level of current game.
void startLevel (int startingAt, int requestedLevel);
void selectLevel (const SelectAction action, const int requestedLevel);
void toggleSoundsOnOff(); // Set sound enabled or disabled.
......@@ -95,7 +91,9 @@ private slots:
void interruptDemo();
private:
void startTutorial(); // Start tutorial game.
void startInstantReplay();
void replayLastLevel();
void showHint(); // Show hint for current level.
QString getTitle(); // Collection - Level NNN, Name.
......@@ -155,6 +153,7 @@ private slots:
private:
bool playLevel (const QString & prefix, const int levelNo,
const bool newLevel);
void setupLevelPlayer();
void showTutorialMessages (int levelNo);
void checkHighScore(); // Check if high score for current game.
......@@ -169,6 +168,7 @@ private:
KGrLevelPlayer * levelPlayer; // Where the level is played.
KGrRecording * recording; // A recording of the play.
bool playback; // Play back or record?
GameAction demoType; // The type of replay or demo.
bool startupDemo; // Startup demo running?
KGrCanvas * view; // Where the game is displayed.
......
......@@ -84,9 +84,10 @@ enum Status {STANDING, FALLING, WALKING, CLIMBING, CAPTIVE};
enum KBAction {KB_UP, KB_DOWN, KB_LEFT, KB_RIGHT,
KB_DIGLEFT, KB_DIGRIGHT, KB_STOP};
// Action codes when selecting a level or game for play or editing.
// Action codes when selecting a level or game for play, editing or replay.
enum SelectAction {SL_START, SL_ANY, SL_CREATE, SL_UPDATE, SL_SAVE,
SL_MOVE, SL_DELETE, SL_CR_GAME, SL_UPD_GAME};
SL_MOVE, SL_DELETE, SL_CR_GAME, SL_UPD_GAME,
SL_REPLAY, SL_SOLVE};
/// Codes for the rules of the selected game and level.
const char TraditionalRules = 'T';
......@@ -99,7 +100,8 @@ class KGrMessage
{
public:
static void information (QWidget * parent, const QString & caption,
const QString & text);
const QString & text,
const QString & dontShowAgain = QString());
static int warning (QWidget * parent, const QString & caption,
const QString & text, const QString & label0,
const QString & label1,
......@@ -149,8 +151,9 @@ public:
QByteArray draws; ///< The random numbers used during play.
};
enum GameAction {NEW, LOAD, SAVE_GAME, PAUSE, HIGH_SCORE, KILL_HERO,
HINT, DEMO, SOLVE, INSTANT_REPLAY, REPLAY_ANY};
enum GameAction {NEW, NEXT_LEVEL, LOAD, SAVE_GAME, PAUSE, HIGH_SCORE,
KILL_HERO, HINT,
DEMO, SOLVE, INSTANT_REPLAY, REPLAY_LAST, REPLAY_ANY};
enum EditAction {CREATE_LEVEL, EDIT_ANY, SAVE_EDITS, MOVE_LEVEL,
DELETE_LEVEL, CREATE_GAME, EDIT_GAME};
......
......@@ -71,11 +71,20 @@ KGrLevelPlayer::~KGrLevelPlayer()
int ch = 0;
for (int i = 0; i <= (recIndex + 1); i ++) {
ch = (uchar)(recording->content.at(i));
fprintf (stderr, "%03d ", ch);
dbe2 "%03d ", ch);
if (ch == 0)
break;
}
fprintf (stderr, "\n%d bytes\n", recIndex + 1);
dbe2 "\n%d bytes\n", recIndex + 1);
int j = 0;
while (j < recording->draws.size()) {
ch = (uchar)(recording->draws.at(j));
dbe2 "%03d ", ch);
if (ch == 0)
break;
j++;
}
dbe2 "\n%d bytes\n", j);
// TODO - Do we need this delete?
// while (! enemies.isEmpty()) {
......@@ -385,7 +394,7 @@ void KGrLevelPlayer::setTarget (int pointerI, int pointerJ)
// The human player is playing now.
if (! playback) {
if ((pointerI == targetI) && (pointerJ == targetJ) && (recCount < 255)){
dbe "T %04d recIndex %03d REC: codes %d %d %d\n",
dbe3 "T %04d recIndex %03d REC: codes %d %d %d\n",
T, recIndex - 2, (uchar)(recording->content.at (recIndex-2)),
(uchar)(recording->content.at (recIndex-1)),
(uchar)(recording->content.at (recIndex)));
......@@ -393,7 +402,7 @@ void KGrLevelPlayer::setTarget (int pointerI, int pointerJ)
recording->content [recIndex] = (uchar) recCount;
}
else {
dbe "T %04d recIndex %03d REC: codes %d %d %d\n",
dbe3 "T %04d recIndex %03d REC: codes %d %d %d\n",
T, recIndex - 2, (uchar)(recording->content.at (recIndex-2)),
(uchar)(recording->content.at (recIndex-1)),
(uchar)(recording->content.at (recIndex)));
......@@ -403,7 +412,7 @@ void KGrLevelPlayer::setTarget (int pointerI, int pointerJ)
recording->content [recIndex] = (uchar) 1;
recording->content [recIndex + 1] = (uchar) 0xff;
recCount = 1;
dbe "T %04d recIndex %03d REC: codes %d %d %d - NEW TARGET\n",
dbe3 "T %04d recIndex %03d REC: codes %d %d %d - NEW TARGET\n",
T, recIndex - 2, pointerI, pointerJ,
(uchar)(recording->content.at (recIndex)));
}
......@@ -416,15 +425,14 @@ void KGrLevelPlayer::setTarget (int pointerI, int pointerJ)
void KGrLevelPlayer::doDig (int button)
{
// If not ready or game control is not by mouse, ignore mouse-clicks.
if ((playState == NotReady) || (controlMode != MOUSE)) {
// Click to end demo/playback mode.
if (playback) {
interruptPlayback();
return;
}
// Click to end demo/playback mode.
if (playback) {
playback = false;
emit interruptDemo();
// If not ready or game control is not by mouse, ignore mouse-clicks.
if ((playState == NotReady) || (controlMode != MOUSE)) {
return;
}
......@@ -448,7 +456,7 @@ void KGrLevelPlayer::doDig (int button)
// If not the hero's first move, interrupt the previous mouse-move.
recording->content [recIndex] =
recording->content [recIndex] - 1;
dbe "T %04d recIndex %03d REC: codes %d %d %d\n",
dbe3 "T %04d recIndex %03d REC: codes %d %d %d\n",
T, recIndex - 2,
(uchar)(recording->content.at (recIndex-2)),
(uchar)(recording->content.at (recIndex-1)),
......@@ -456,7 +464,7 @@ void KGrLevelPlayer::doDig (int button)
recIndex++;
}
// Record the digging code.
dbe "T %04d recIndex %03d REC: dig code %d\n",
dbe3 "T %04d recIndex %03d REC: dig code %d\n",
T, recIndex, recordByte);
recording->content [recIndex++] = recordByte;
......@@ -471,13 +479,14 @@ void KGrLevelPlayer::doDig (int button)
void KGrLevelPlayer::setDirectionByKey (Direction dirn)
{
// Keystrokes control the hero.
if ((playState == NotReady) || (controlMode == MOUSE)) {
// Any key ends playback mode.
if (playback) {
interruptPlayback();
return;
}
if (playback) { // Any key ends demo/playback mode.
playback = false;
emit interruptDemo();
// Keystrokes control the hero.
if ((playState == NotReady) || (controlMode == MOUSE)) {
return;
}
......@@ -498,7 +507,7 @@ void KGrLevelPlayer::setDirectionByKey (Direction dirn)
Direction KGrLevelPlayer::getDirection (int heroI, int heroJ)
{
int index = (playback) ? recIndex : recIndex - 2;
dbe "T %04d recIndex %03d hero at [%02d, %02d] aiming at [%02d, %02d]\n",
dbe3 "T %04d recIndex %03d hero at [%02d, %02d] aiming at [%02d, %02d]\n",
T, index, heroI, heroJ, targetI, targetJ);
if ((controlMode == MOUSE) || (controlMode == LAPTOP)) {
// If using a pointer device, calculate the hero's next direction,
......@@ -663,6 +672,9 @@ void KGrLevelPlayer::tick (bool missed, int scaledTime)
{
if (playback) { // Replay a recorded move.
if (! doRecordedMove()) {
playback = false;
emit interruptDemo();
dbk << "END_OF_RECORDING - emit interruptDemo();";
return; // End of recording.
}
}
......@@ -755,7 +767,7 @@ void KGrLevelPlayer::makeReappearanceSequence()
reappearPos [left - 1] = temp;
left--;
}
kDebug() << "Randoms" << reappearPos;
dbk3 << "Randoms" << reappearPos;
reappearIndex = 0;
}
......@@ -799,7 +811,7 @@ void KGrLevelPlayer::enemyReappear (int & gridI, int & gridJ)
}
}
}
kDebug() << "Reappear at" << i << j;
dbk3 << "Reappear at" << i << j;
gridI = i;
gridJ = j;
}
......@@ -825,7 +837,6 @@ bool KGrLevelPlayer::doRecordedMove()
while (true) {
// Check for end of recording.
if ((code == 0xff) || (code == 0)) {
playback = false;
return false;
}
// Check for a key press or mouse button click.
......@@ -833,7 +844,7 @@ bool KGrLevelPlayer::doRecordedMove()
playState = Playing;
code = code - 0x80;
if ((code == DIG_LEFT) || (code == DIG_RIGHT)) {
dbe "T %04d recIndex %03d PLAY dig code %d\n",
dbe3 "T %04d recIndex %03d PLAY dig code %d\n",
T, recIndex, code);
startDigging ((Direction)(code));
}
......@@ -851,7 +862,7 @@ bool KGrLevelPlayer::doRecordedMove()
// targetI = code;
// targetJ = (uchar)(recording->content [recIndex + 1]);
recCount = (uchar)(recording->content [recIndex + 2]);
dbe "T %04d recIndex %03d PLAY codes %d %d %d - NEW TARGET\n",
dbe3 "T %04d recIndex %03d PLAY codes %d %d %d - NEW TARGET\n",
T, recIndex, i, j, recCount);
// T, recIndex, targetI, targetJ, recCount);
......@@ -860,12 +871,12 @@ bool KGrLevelPlayer::doRecordedMove()
// emit setMousePos (i, j);
}
else {
dbe "T %04d recIndex %03d PLAY codes %d %d %d\n",
dbe3 "T %04d recIndex %03d PLAY codes %d %d %d\n",
T, recIndex, targetI, targetJ, recCount);
}
if (--recCount <= 0) {
recIndex = recIndex + 3;
dbe "T %04d recIndex %03d PLAY - next index\n",
dbe3 "T %04d recIndex %03d PLAY - next index\n",
T, recIndex);
}
break;
......@@ -874,6 +885,85 @@ bool KGrLevelPlayer::doRecordedMove()
return true;
}
void KGrLevelPlayer::interruptPlayback()
{
// Check if still replaying the wait-time before the first move.
if (playState != Playing) {
return;
}
uchar code = recording->content [recIndex];
// Check for end-of-recording already reached.
if ((code == 0xff) || (code == 0)) {
return;
}
dbk2 << "recIndex" << recIndex << "recCount" << recCount
<< "randIndex" << randIndex;
int ch = 0;
int i = 0;
while (i < recording->content.size()) {
ch = (uchar)(recording->content.at(i));
dbe2 "%03d ", ch);
if (ch == 0)
break;
i++;
}
dbe2 "\n%d bytes\n", i - 1);
i = 0;
while (i < recording->draws.size()) {
ch = (uchar)(recording->draws.at(i));
dbe2 "%03d ", ch);
if (ch == 0)
break;
i++;
}
dbe2 "\n%d bytes\n", i - 1);
if (code >= 0x80) {
// TODO - Need code here to tie off keystroke-move counter and step on.
}
else if (recCount > 0) {
// Set mouse-move counter to show how many ticks have been replayed.
uchar byte = (uchar)(recording->content [recIndex + 2]);
recording->content [recIndex + 2] = (uchar) (byte - recCount);
recIndex = recIndex + 2; // Record here if same mouse position.
}
recording->content [recIndex + 1] = 0xff;
for (int i = (recIndex + 2); i < recording->content.size(); i++) {
recording->content [i] = 0;
}
for (int i = randIndex; i < recording->draws.size(); i++) {
recording->draws [i] = 0;
}
dbk2 << "recIndex" << recIndex << "recCount" << recCount
<< "randIndex" << randIndex;
i = 0;
while (i < recording->content.size()) {
ch = (uchar)(recording->content.at(i));
dbe2 "%03d ", ch);
if (ch == 0)
break;
i++;
}
dbe2 "\n%d bytes\n", i - 1);
i = 0;
while (i < recording->draws.size()) {
ch = (uchar)(recording->draws.at(i));
dbe2 "%03d ", ch);
if (ch == 0)
break;
i++;
}
dbe2 "\n%d bytes\n", i - 1);
playback = false;
emit interruptDemo();
dbk << "INTERRUPT - emit interruptDemo();";
}
/******************************************************************************/
/************************** AUTHORS' DEBUGGING AIDS **************************/
/******************************************************************************/
......
......@@ -363,6 +363,7 @@ private:
QVector<int> reappearPos;
void makeReappearanceSequence();
bool doRecordedMove();