aboutsummaryrefslogtreecommitdiff
path: root/engines/saga/puzzle.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/saga/puzzle.cpp')
-rw-r--r--engines/saga/puzzle.cpp560
1 files changed, 560 insertions, 0 deletions
diff --git a/engines/saga/puzzle.cpp b/engines/saga/puzzle.cpp
new file mode 100644
index 0000000000..c09a9c0462
--- /dev/null
+++ b/engines/saga/puzzle.cpp
@@ -0,0 +1,560 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2005-2006 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "saga/saga.h"
+
+#include "saga/actor.h"
+#include "saga/interface.h"
+#include "saga/scene.h"
+#include "saga/sprite.h"
+#include "saga/puzzle.h"
+#include "saga/render.h"
+#include "saga/resnames.h"
+
+#include "common/system.h"
+#include "common/timer.h"
+
+namespace Saga {
+
+#define PUZZLE_X_OFFSET 72
+#define PUZZLE_Y_OFFSET 46
+
+#define PUZZLE_FIT 0x01 // 1 when in correct position
+#define PUZZLE_MOVED 0x04 // 1 when somewhere in the box
+#define PUZZLE_ALL_SET PUZZLE_FIT | PUZZLE_MOVED
+
+
+enum rifOptions {
+ kROLater = 0,
+ kROAccept = 1,
+ kRODecline = 2,
+ kROHint = 3
+};
+
+Puzzle::Puzzle(SagaEngine *vm) : _vm(vm), _solved(false), _active(false) {
+ _lang = (_vm->getLanguage() == Common::DE_DEU) ? 1 : 0;
+
+ _hintRqState = kRQNoHint;
+ _hintOffer = 0;
+ _hintCount = 0;
+ _helpCount = 0;
+ _puzzlePiece = -1;
+ _newPuzzle = true;
+ _sliding = false;
+ _hintBox.left = 70;
+ _hintBox.top = 105;
+ _hintBox.setWidth(240);
+ _hintBox.setHeight(30);
+
+ initPieceInfo( 0, 268, 18, 0, 0, 0 + PUZZLE_X_OFFSET, 0 + PUZZLE_Y_OFFSET, 0, 3,
+ Point(0, 1), Point(0, 62), Point(15, 31), Point(0, 0), Point(0, 0), Point(0,0));
+ initPieceInfo( 1, 270, 52, 0, 0, 0 + PUZZLE_X_OFFSET, 32 + PUZZLE_Y_OFFSET, 0, 4,
+ Point(0, 31), Point(0, 47), Point(39, 47), Point(15, 1), Point(0, 0), Point(0, 0));
+ initPieceInfo( 2, 19, 51, 0, 0, 0 + PUZZLE_X_OFFSET, 0 + PUZZLE_Y_OFFSET, 0, 4,
+ Point(0, 0), Point(23, 46), Point(39, 15), Point(31, 0), Point(0, 0), Point(0, 0));
+ initPieceInfo( 3, 73, 0, 0, 0, 32 + PUZZLE_X_OFFSET, 0 + PUZZLE_Y_OFFSET, 0, 6,
+ Point(0, 0), Point(8, 16), Point(0, 31), Point(31, 31), Point(39, 15), Point(31, 0));
+ initPieceInfo( 4, 0, 35, 0, 0, 64 + PUZZLE_X_OFFSET, 16 + PUZZLE_Y_OFFSET, 0, 4,
+ Point(0, 15), Point(15, 46), Point(23, 32), Point(7, 1), Point(0, 0), Point(0, 0));
+ initPieceInfo( 5, 215, 0, 0, 0, 24 + PUZZLE_X_OFFSET, 32 + PUZZLE_Y_OFFSET, 0, 6,
+ Point(0, 15), Point(8, 31), Point(39, 31), Point(47, 16), Point(39, 0), Point(8, 0));
+ initPieceInfo( 6, 159, 0, 0, 0, 32 + PUZZLE_X_OFFSET, 48 + PUZZLE_Y_OFFSET, 0, 5,
+ Point(0, 16), Point(8, 31), Point(55, 31), Point(39, 1), Point(32, 15), Point(0, 0));
+ initPieceInfo( 7, 9, 70, 0, 0, 80 + PUZZLE_X_OFFSET, 32 + PUZZLE_Y_OFFSET, 0, 5,
+ Point(0, 31), Point(8, 47), Point(23, 47), Point(31, 31), Point(15, 1), Point(0, 0));
+ initPieceInfo( 8, 288, 18, 0, 0, 96 + PUZZLE_X_OFFSET, 0 + PUZZLE_Y_OFFSET, 0, 4,
+ Point(0, 31), Point(15, 62), Point(31, 32), Point(15, 1), Point(0, 0), Point(0, 0));
+ initPieceInfo( 9, 112, 0, 0, 0, 112 + PUZZLE_X_OFFSET, 0 + PUZZLE_Y_OFFSET, 0, 4,
+ Point(0, 0), Point(16, 31), Point(47, 31), Point(31, 0), Point(0, 0), Point(0, 0));
+ initPieceInfo(10, 27, 89, 0, 0, 104 + PUZZLE_X_OFFSET, 32 + PUZZLE_Y_OFFSET, 0, 4,
+ Point(0, 47), Point(31, 47), Point(31, 0), Point(24, 0), Point(0, 0), Point(0, 0));
+ initPieceInfo(11, 43, 0, 0, 0, 136 + PUZZLE_X_OFFSET, 32 + PUZZLE_Y_OFFSET, 0, 6,
+ Point(0, 0), Point(0, 47), Point(15, 47), Point(15, 15), Point(31, 15), Point(23, 0));
+ initPieceInfo(12, 0, 0, 0, 0, 144 + PUZZLE_X_OFFSET, 0 + PUZZLE_Y_OFFSET, 0, 4,
+ Point(0, 0), Point(24, 47), Point(39, 47), Point(39, 0), Point(0, 0), Point(0, 0));
+ initPieceInfo(13, 262, 0, 0, 0, 64 + PUZZLE_X_OFFSET, 0 + PUZZLE_Y_OFFSET, 0, 3,
+ Point(0, 0), Point(23, 46), Point(47, 0), Point(0, 0), Point(0, 0), Point(0, 0));
+ initPieceInfo(14, 271, 103, 0, 0, 152 + PUZZLE_X_OFFSET, 48 + PUZZLE_Y_OFFSET, 0, 4,
+ Point(0, 0), Point(0, 31), Point(31, 31), Point(31, 0), Point(0, 0), Point(0, 0));
+}
+
+void Puzzle::initPieceInfo(int i, int16 curX, int16 curY, byte offX, byte offY, int16 trgX,
+ int16 trgY, uint8 flag, uint8 count, Point point0, Point point1,
+ Point point2, Point point3, Point point4, Point point5) {
+ _pieceInfo[i].curX = curX;
+ _pieceInfo[i].curY = curY;
+ _pieceInfo[i].offX = offX;
+ _pieceInfo[i].offY = offY;
+ _pieceInfo[i].trgX = trgX;
+ _pieceInfo[i].trgY = trgY;
+ _pieceInfo[i].flag = flag;
+ _pieceInfo[i].count = count;
+ _pieceInfo[i].point[0] = point0;
+ _pieceInfo[i].point[1] = point1;
+ _pieceInfo[i].point[2] = point2;
+ _pieceInfo[i].point[3] = point3;
+ _pieceInfo[i].point[4] = point4;
+ _pieceInfo[i].point[5] = point5;
+}
+
+
+void Puzzle::execute(void) {
+ _active = true;
+ Common::g_timer->installTimerProc(&hintTimerCallback, kPuzzleHintTime, this);
+
+ initPieces();
+
+ showPieces();
+
+ _vm->_interface->setMode(kPanelConverse);
+ clearHint();
+ //_solved = true; // Cheat
+ //exitPuzzle();
+}
+
+void Puzzle::exitPuzzle(void) {
+ _active = false;
+
+ Common::g_timer->removeTimerProc(&hintTimerCallback);
+
+ _vm->_scene->changeScene(ITE_SCENE_LODGE, 0, kTransitionNoFade);
+ _vm->_interface->setMode(kPanelMain);
+}
+
+void Puzzle::initPieces(void) {
+ SpriteInfo *spI;
+ ActorData *puzzle = _vm->_actor->getActor(_vm->_actor->actorIndexToId(ITE_ACTOR_PUZZLE));
+ int frameNumber;
+ SpriteList *spriteList;
+ _vm->_actor->getSpriteParams(puzzle, frameNumber, spriteList);
+
+ for (int i = 0; i < PUZZLE_PIECES; i++) {
+ spI = &(spriteList->infoList[i]);
+ _pieceInfo[i].offX = (byte)(spI->width >> 1);
+ _pieceInfo[i].offY = (byte)(spI->height >> 1);
+
+ if (_newPuzzle) {
+ _pieceInfo[i].curX = pieceOrigins[i].x;
+ _pieceInfo[i].curY = pieceOrigins[i].y;
+ }
+ _piecePriority[i] = i;
+ }
+ _newPuzzle = false;
+}
+
+void Puzzle::showPieces(void) {
+ ActorData *puzzle = _vm->_actor->getActor(_vm->_actor->actorIndexToId(ITE_ACTOR_PUZZLE));
+ int frameNumber;
+ SpriteList *spriteList;
+ Surface *backBuffer = _vm->_gfx->getBackBuffer();
+ _vm->_actor->getSpriteParams(puzzle, frameNumber, spriteList);
+
+ for (int j = PUZZLE_PIECES - 1 ; j >= 0; j--) {
+ int num = _piecePriority[j];
+
+ if (_puzzlePiece != num) {
+ _vm->_sprite->draw(backBuffer, _vm->getDisplayClip(), *spriteList, num, Point(_pieceInfo[num].curX, _pieceInfo[num].curY), 256);
+ }
+ }
+}
+
+void Puzzle::drawCurrentPiece() {
+ ActorData *puzzle = _vm->_actor->getActor(_vm->_actor->actorIndexToId(ITE_ACTOR_PUZZLE));
+ Surface *backBuffer = _vm->_gfx->getBackBuffer();
+ int frameNumber;
+ SpriteList *spriteList;
+ _vm->_actor->getSpriteParams(puzzle, frameNumber, spriteList);
+
+ _vm->_sprite->draw(backBuffer, _vm->_scene->getSceneClip(), *spriteList, _puzzlePiece,
+ Point(_pieceInfo[_puzzlePiece].curX, _pieceInfo[_puzzlePiece].curY), 256);
+}
+
+void Puzzle::movePiece(Point mousePt) {
+ int newx, newy;
+
+ showPieces();
+
+ if (_puzzlePiece == -1)
+ return;
+
+ if (_sliding) {
+ newx = _slidePointX;
+ newy = _slidePointY;
+ } else {
+ if (mousePt.y >= 137)
+ return;
+
+ newx = mousePt.x;
+ newy = mousePt.y;
+ }
+
+ newx -= _pieceInfo[_puzzlePiece].offX;
+ newy -= _pieceInfo[_puzzlePiece].offY;
+
+ _pieceInfo[_puzzlePiece].curX = newx;
+ _pieceInfo[_puzzlePiece].curY = newy;
+
+ drawCurrentPiece();
+}
+
+void Puzzle::handleClick(Point mousePt) {
+ if (_puzzlePiece != -1) {
+ dropPiece(mousePt);
+
+ if (!_active)
+ return; // we won
+
+ drawCurrentPiece();
+ _puzzlePiece = -1;
+
+ return;
+ }
+
+ for (int j = 0; j < PUZZLE_PIECES; j++) {
+ int i = _piecePriority[j];
+ int adjX = mousePt.x - _pieceInfo[i].curX;
+ int adjY = mousePt.y - _pieceInfo[i].curY;
+
+ if (hitTestPoly(&_pieceInfo[i].point[0], _pieceInfo[i].count, Point(adjX, adjY))) {
+ _puzzlePiece = i;
+ break;
+ }
+ }
+
+ if (_puzzlePiece == -1)
+ return;
+
+ alterPiecePriority();
+
+ // Display scene background
+ _vm->_scene->draw();
+ showPieces();
+
+ int newx = mousePt.x - _pieceInfo[_puzzlePiece].offX;
+ int newy = mousePt.y - _pieceInfo[_puzzlePiece].offY;
+
+ if (newx != _pieceInfo[_puzzlePiece].curX
+ || newy != _pieceInfo[_puzzlePiece].curY) {
+ _pieceInfo[_puzzlePiece].curX = newx;
+ _pieceInfo[_puzzlePiece].curY = newy;
+ }
+ _vm->_interface->setStatusText(pieceNames[_lang][_puzzlePiece]);
+}
+
+void Puzzle::alterPiecePriority(void) {
+ for (int i = 1; i < PUZZLE_PIECES; i++) {
+ if (_puzzlePiece == _piecePriority[i]) {
+ for (int j = i - 1; j >= 0; j--)
+ _piecePriority[j+1] = _piecePriority[j];
+ _piecePriority[0] = _puzzlePiece;
+ break;
+ }
+ }
+}
+
+void Puzzle::slidePiece(int x1, int y1, int x2, int y2) {
+ int count;
+ Point slidePoints[320];
+
+ x1 += _pieceInfo[_puzzlePiece].offX;
+ y1 += _pieceInfo[_puzzlePiece].offY;
+
+ count = pathLine(&slidePoints[0], Point(x1, y1),
+ Point(x2 + _pieceInfo[_puzzlePiece].offX, y2 + _pieceInfo[_puzzlePiece].offY));
+
+ if (count > 1) {
+ int factor = count / 4;
+ _sliding = true;
+
+ if (!factor)
+ factor++;
+
+ for (int i = 1; i < count; i += factor) {
+ _slidePointX = slidePoints[i].x;
+ _slidePointY = slidePoints[i].y;
+ _vm->_render->drawScene();
+ _vm->_system->delayMillis(10);
+ }
+ _sliding = false;
+ }
+
+ _pieceInfo[_puzzlePiece].curX = x2;
+ _pieceInfo[_puzzlePiece].curY = y2;
+}
+
+void Puzzle::dropPiece(Point mousePt) {
+ int boxx = PUZZLE_X_OFFSET;
+ int boxy = PUZZLE_Y_OFFSET;
+ int boxw = boxx + 184;
+ int boxh = boxy + 80;
+
+ // if the center is within the box quantize within
+ // else move it back to its original start point
+ if (mousePt.x >= boxx && mousePt.x < boxw && mousePt.y >= boxy && mousePt.y <= boxh) {
+ ActorData *puzzle = _vm->_actor->getActor(_vm->_actor->actorIndexToId(ITE_ACTOR_PUZZLE));
+ SpriteInfo *spI;
+ int frameNumber;
+ SpriteList *spriteList;
+ _vm->_actor->getSpriteParams(puzzle, frameNumber, spriteList);
+
+ int newx = mousePt.x - _pieceInfo[_puzzlePiece].offX;
+ int newy = mousePt.y - _pieceInfo[_puzzlePiece].offY;
+
+ if (newx < boxx)
+ newx = PUZZLE_X_OFFSET;
+ if (newy < boxy)
+ newy = PUZZLE_Y_OFFSET;
+
+ spI = &(spriteList->infoList[_puzzlePiece]);
+
+ if (newx + spI->width > boxw)
+ newx = boxw - spI->width ;
+ if (newy + spI->height > boxh)
+ newy = boxh - spI->height ;
+
+ int x1 = ((newx - PUZZLE_X_OFFSET) & ~7) + PUZZLE_X_OFFSET;
+ int y1 = ((newy - PUZZLE_Y_OFFSET) & ~7) + PUZZLE_Y_OFFSET;
+ int x2 = x1 + 8;
+ int y2 = y1 + 8;
+ newx = (x2 - newx < newx - x1) ? x2 : x1;
+ newy = (y2 - newy < newy - y1) ? y2 : y1;
+
+ // if any part of the puzzle piece falls outside the box
+ // force it back in
+
+ // is the piece at the target location
+ if (newx == _pieceInfo[_puzzlePiece].trgX
+ && newy == _pieceInfo[_puzzlePiece].trgY) {
+ _pieceInfo[_puzzlePiece].flag |= (PUZZLE_MOVED | PUZZLE_FIT);
+ } else {
+ _pieceInfo[_puzzlePiece].flag &= ~PUZZLE_FIT;
+ _pieceInfo[_puzzlePiece].flag |= PUZZLE_MOVED;
+ }
+ _pieceInfo[_puzzlePiece].curX = newx;
+ _pieceInfo[_puzzlePiece].curY = newy;
+ } else {
+ int newx = pieceOrigins[_puzzlePiece].x;
+ int newy = pieceOrigins[_puzzlePiece].y;
+ _pieceInfo[_puzzlePiece].flag &= ~(PUZZLE_FIT | PUZZLE_MOVED);
+
+ // slide piece from current position to new position
+ slidePiece(_pieceInfo[_puzzlePiece].curX, _pieceInfo[_puzzlePiece].curY,
+ newx, newy);
+ }
+
+ // is the puzzle completed?
+
+ _solved = true;
+ for (int i = 0; i < PUZZLE_PIECES; i++)
+ if ((_pieceInfo[i].flag & PUZZLE_FIT) == 0) {
+ _solved = false;
+ break;
+ }
+
+ if (_solved)
+ exitPuzzle();
+}
+
+void Puzzle::hintTimerCallback(void *refCon) {
+ ((Puzzle *)refCon)->solicitHint();
+}
+
+void Puzzle::solicitHint(void) {
+ int i;
+
+ _vm->_actor->setSpeechColor(1, kITEColorBlack);
+
+ Common::g_timer->removeTimerProc(&hintTimerCallback);
+
+ switch (_hintRqState) {
+ case kRQSpeaking:
+ if (_vm->_actor->isSpeaking()) {
+ Common::g_timer->installTimerProc(&hintTimerCallback, 50000, this);
+ break;
+ }
+
+ _hintRqState = _hintNextRqState;
+ Common::g_timer->installTimerProc(&hintTimerCallback, 333333, this);
+ break;
+
+ case kRQNoHint:
+ // Pick a random hint request.
+ i = _hintOffer++;
+ if (_hintOffer >= NUM_SOLICIT_REPLIES)
+ _hintOffer = 0;
+
+ // Determine which of the journeymen will offer then
+ // hint, and then show that character's portrait.
+ _hintGiver = portraitList[i];
+ _hintSpeaker = _hintGiver - RID_ITE_JFERRET_SERIOUS;
+ _vm->_interface->setRightPortrait(_hintGiver);
+
+ _vm->_actor->nonActorSpeech(_hintBox, &solicitStr[_lang][i], 1, PUZZLE_SOLICIT_SOUNDS + i * 3 + _hintSpeaker, 0);
+
+ // Add Rif's reply to the list.
+ clearHint();
+
+ // Roll to see if Sakka scolds
+ if (_vm->_rnd.getRandomNumber(1)) {
+ _hintRqState = kRQSakkaDenies;
+ Common::g_timer->installTimerProc(&hintTimerCallback, 200000, this);
+ } else {
+ _hintRqState = kRQSpeaking;
+ _hintNextRqState = kRQHintRequested;
+ Common::g_timer->installTimerProc(&hintTimerCallback, 50000, this);
+ }
+
+ break;
+
+ case kRQHintRequested:
+ i = _vm->_rnd.getRandomNumber(NUM_SAKKA - 1);
+ _vm->_actor->nonActorSpeech(_hintBox, &sakkaStr[_lang][i], 1, PUZZLE_SAKKA_SOUNDS + i, 0);
+
+ _vm->_interface->setRightPortrait(RID_ITE_SAKKA_APPRAISING);
+
+ _hintRqState = kRQSpeaking;
+ _hintNextRqState = kRQHintRequestedStage2;
+ Common::g_timer->installTimerProc(&hintTimerCallback, 50000, this);
+
+ _vm->_interface->converseClear();
+ _vm->_interface->converseAddText(optionsStr[_lang][kROAccept], 1, 0, 0 );
+ _vm->_interface->converseAddText(optionsStr[_lang][kRODecline], 2, 0, 0 );
+ _vm->_interface->converseAddText(optionsStr[_lang][kROLater], 0, 0, 0 );
+ _vm->_interface->converseDisplayText();
+ break;
+
+ case kRQHintRequestedStage2:
+ if (_vm->_rnd.getRandomNumber(1)) { // Skip Reply part
+ i = _vm->_rnd.getRandomNumber(NUM_WHINES - 1);
+ _vm->_actor->nonActorSpeech(_hintBox, &whineStr[_lang][i], 1, PUZZLE_WHINE_SOUNDS + i * 3 + _hintSpeaker, 0);
+ }
+
+ _vm->_interface->setRightPortrait(_hintGiver);
+
+ _hintRqState = kRQSakkaDenies;
+ break;
+
+ case kRQSakkaDenies:
+ _vm->_interface->converseClear();
+ _vm->_interface->converseAddText(optionsStr[_lang][kROAccept], 1, 0, 0);
+ _vm->_interface->converseAddText(optionsStr[_lang][kRODecline], 2, 0, 0);
+ _vm->_interface->converseAddText(optionsStr[_lang][kROLater], 0, 0, 0);
+ _vm->_interface->converseDisplayText();
+
+ Common::g_timer->installTimerProc(&hintTimerCallback, kPuzzleHintTime, this);
+
+ _hintRqState = kRQSkipEverything;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Puzzle::handleReply(int reply) {
+ switch(reply) {
+ case 0: // Quit the puzzle
+ exitPuzzle();
+ break;
+
+ case 1: // Accept the hint
+ giveHint();
+ break;
+
+ case 2: // Decline the hint
+ _vm->_actor->abortSpeech();
+ _hintRqState = kRQNoHint;
+ Common::g_timer->removeTimerProc(&hintTimerCallback);
+ Common::g_timer->installTimerProc(&hintTimerCallback, kPuzzleHintTime * 2, this);
+ clearHint();
+ break;
+ }
+}
+
+void Puzzle::giveHint(void) {
+ int i, total = 0;
+
+ _vm->_interface->converseClear();
+
+ _vm->_actor->abortSpeech();
+ _vm->_interface->setRightPortrait(_hintGiver);
+
+ for (i = 0; i < PUZZLE_PIECES; i++)
+ total += _pieceInfo[i].flag & PUZZLE_FIT;
+
+ if (_hintCount == 0 && (_pieceInfo[1].flag & PUZZLE_FIT
+ || _pieceInfo[12].flag & PUZZLE_FIT))
+ _hintCount++;
+ if (_hintCount == 1 && _pieceInfo[14].flag & PUZZLE_FIT)
+ _hintCount++;
+
+ if (_hintCount == 2 && total > 3)
+ _hintCount++;
+
+ _vm->_actor->setSpeechColor(1, kITEColorBlack);
+
+ if (_hintCount < 3) {
+ _vm->_actor->nonActorSpeech(_hintBox, &hintStr[_lang][_hintCount], 1, PUZZLE_HINT_SOUNDS + _hintCount * 3 + _hintSpeaker, 0);
+ } else {
+ int piece = 0;
+
+ for (i = PUZZLE_PIECES - 1; i >= 0; i--) {
+ piece = _piecePriority[i];
+ if (_pieceInfo[piece].flag & PUZZLE_MOVED
+ && !(_pieceInfo[piece].flag & PUZZLE_FIT)) {
+ if (_helpCount < 12)
+ _helpCount++;
+ break;
+ }
+ }
+
+ if (i >= 0) {
+ static char hintBuf[64];
+ static const char *hintPtr = hintBuf;
+ sprintf(hintBuf, optionsStr[_lang][kROHint], pieceNames[_lang][piece]);
+
+ _vm->_actor->nonActorSpeech(_hintBox, &hintPtr, 1, PUZZLE_TOOL_SOUNDS + _hintSpeaker + piece * 3, 0);
+ }
+ else {
+ // If no pieces are in the wrong place
+ _vm->_actor->nonActorSpeech(_hintBox, &hintStr[_lang][3], 1, PUZZLE_HINT_SOUNDS + 3 * 3 + _hintSpeaker, 0);
+ }
+ }
+ _hintCount++;
+
+ _hintRqState = kRQNoHint;
+
+ _vm->_interface->converseAddText(optionsStr[_lang][kROLater], 0, 0, 0);
+ _vm->_interface->converseDisplayText();
+
+ Common::g_timer->removeTimerProc(&hintTimerCallback);
+ Common::g_timer->installTimerProc(&hintTimerCallback, kPuzzleHintTime, this);
+}
+
+void Puzzle::clearHint(void) {
+ _vm->_interface->converseClear();
+ _vm->_interface->converseAddText(optionsStr[_lang][kROLater], 0, 0, 0);
+ _vm->_interface->converseDisplayText();
+ _vm->_interface->setStatusText(" ");
+}
+
+} // End of namespace Saga