/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * 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. * */ #include "sherlock/tattoo/tattoo_darts.h" #include "sherlock/tattoo/tattoo_fixed_text.h" #include "sherlock/tattoo/tattoo.h" namespace Sherlock { namespace Tattoo { enum { DART_COLOR_FORE = 5, PLAYER_COLOR = 11 }; static const int STATUS_INFO_X = 430; static const int STATUS_INFO_Y = 50; static const int STATUS_INFO_WIDTH = 205; static const int STATUS_INFO_HEIGHT = 330; static const int STATUS2_INFO_X = 510; static const int STATUS2_X_ADD = STATUS2_INFO_X - STATUS_INFO_X; static const int DART_BAR_VX = 10; static const int DART_HEIGHT_Y = 121; static const int DART_BAR_SIZE = 150; static const int DARTBOARD_LEFT = 73; static const int DARTBOARD_TOP = 68; static const int DARTBOARD_WIDTH = 257; static const int DARTBOARD_HEIGHT = 256; static const int DARTBOARD_TOTALX = DARTBOARD_WIDTH * 120 / 100; static const int DARTBOARD_TOTALY = DARTBOARD_HEIGHT * 120 / 100; static const int DARTBOARD_TOTALTOP = DARTBOARD_TOP - DARTBOARD_WIDTH / 10; static const int DARTBOARD_TOTALLEFT = DARTBOARD_LEFT - DARTBOARD_HEIGHT / 10; static const int CRICKET_VALUE[7] = { 20, 19, 18, 17, 16, 15, 25 }; Darts::Darts(SherlockEngine *vm) : _vm(vm) { _gameType = GAME_301; _hand1 = _hand2 = nullptr; _dartGraphics = nullptr; _dartsLeft = nullptr; _dartMap = nullptr; _dartBoard = nullptr; Common::fill(&_cricketScore[0][0], &_cricketScore[0][7], 0); Common::fill(&_cricketScore[1][0], &_cricketScore[1][7], 0); _score1 = _score2 = 0; _roundNum = 0; _roundScore = 0; _level = 0; _oldDartButtons = false; _handX = 0; _compPlay = 1; } void Darts::playDarts(GameType gameType) { Events &events = *_vm->_events; Screen &screen = *_vm->_screen; int oldFontType = screen.fontNumber(); int playerNum = 0; int roundStart, score; int lastDart; int numHits = 0; bool gameOver = false; bool done = false; const char *const NUM_HITS_STR[3] = { "a", FIXED(Double), FIXED(Triple) }; screen.setFont(7); _spacing = screen.fontHeight() + 2; while (!_vm->shouldQuit()) { roundStart = score = (playerNum == 0) ? _score1 : _score2; showNames(playerNum); showStatus(playerNum); _roundScore = 0; for (int idx = 0; idx < 3; ++idx) { if (_compPlay == 1) lastDart = throwDart(idx + 1, playerNum * 2); /* Throw one dart */ else if (_compPlay == 2) lastDart = throwDart(idx + 1, playerNum + 1); /* Throw one dart */ else lastDart = throwDart(idx + 1, 0); /* Throw one dart */ if (_gameType == GAME_301) { score -= lastDart; _roundScore += lastDart; } else { numHits = lastDart >> 16; if (numHits == 0) numHits = 1; if (numHits > 3) numHits = 3; lastDart = lastDart & 0xffff; updateCricketScore(playerNum, lastDart, numHits); score = (playerNum == 0) ? _score1 : _score2; } if (_gameType == GAME_301) { if (playerNum == 0) _score1 = score; else _score2 = score; if (score == 0) // Someone won gameOver = true; } else { // check for cricket game over bool allClosed = true; bool otherAllClosed = true; int nOtherScore; for (int y = 0; y < 7; y++) { if (_cricketScore[playerNum][y] < 3) allClosed = false; } for (int y = 0; y < 7; ++y) { if (_cricketScore[playerNum ^ 1][y] < 3) otherAllClosed = false; } if (allClosed) { nOtherScore = (playerNum == 0) ? _score2 : _score1; if (score >= nOtherScore) gameOver = true; } } // Show scores showStatus(playerNum); screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(_dartInfo.left, _dartInfo.top - 1), Common::Rect(_dartInfo.left, _dartInfo.top - 1, _dartInfo.right, _dartInfo.bottom - 1)); screen.print(Common::Point(_dartInfo.left, _dartInfo.top), 0, "%s # %d", FIXED(Dart), idx + 1); if (_gameType == GAME_301) { if (_vm->getLanguage() == Common::FR_FRA) screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing), 0, "%s %s: %d", FIXED(Scored), FIXED(Points), lastDart); else screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing), 0, "%s %d %s", FIXED(Scored), lastDart, FIXED(Points)); } else { if (lastDart != 25) screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing), 0, "%s %s %d", FIXED(Hit), NUM_HITS_STR[numHits - 1], lastDart); else screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing), 0, "%s %s %s", FIXED(Hit), NUM_HITS_STR[numHits - 1], FIXED(Bullseye)); } if (score != 0 && playerNum == 0 && !gameOver) screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing * 3), 0, "%s", FIXED(PressAKey)); if (gameOver) { screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing * 3), 0, "%s", FIXED(GameOver)); if (playerNum == 0) { screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing * 4), 0, "%s %s", FIXED(Holmes), FIXED(Wins)); _vm->setFlagsDirect(531); } else { screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing * 4), 0, "%s %s!", _opponent.c_str(), FIXED(Wins)); _vm->setFlagsDirect(530); } screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing * 5), 0, "%s", FIXED(PressAKey)); done = true; idx = 10; } else if (_gameType == GAME_301 && score < 0) { screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing * 2), 0, "%s!", FIXED(Busted)); // End turn idx = 10; score = roundStart; if (playerNum == 0) _score1 = score; else _score2 = score; } // Clear keyboard events events.clearEvents(); if ((playerNum == 0 && _compPlay == 1) || _compPlay == 0 || done) { if (events.kbHit()) { Common::KeyState keyState = events.getKey(); if (keyState.keycode == Common::KEYCODE_ESCAPE) { done = true; idx = 10; } } } else { events.wait(20); } screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(_dartInfo.left, _dartInfo.top - 1), Common::Rect(_dartInfo.left, _dartInfo.top - 1, _dartInfo.right, _dartInfo.bottom - 1)); screen.blitFrom(screen._backBuffer1); } playerNum ^= 1; if (!playerNum) ++_roundNum; if (!done) { screen._backBuffer2.blitFrom((*_dartBoard)[0], Common::Point(0, 0)); screen._backBuffer1.blitFrom(screen._backBuffer2); screen.blitFrom(screen._backBuffer2); } } closeDarts(); screen.fadeToBlack(); screen.setFont(oldFontType); } void Darts::initDarts() { _dartInfo = Common::Rect(430, 50, 430 + 205, 50 + 330); if (_gameType == GAME_CRICKET) { _dartInfo = Common::Rect(430, 245, 430 + 205, 245 + 150); } Common::fill(&_cricketScore[0][0], &_cricketScore[0][7], 0); Common::fill(&_cricketScore[1][0], &_cricketScore[1][7], 0); switch (_gameType) { case GAME_501: _score1 = _score2 = 501; _gameType = GAME_301; break; case GAME_301: _score1 = _score2 = 301; break; default: // Cricket _score1 = _score2 = 0; break; } _roundNum = 1; if (_level == 9) { // No computer players _compPlay = 0; _level = 0; } else if (_level == 8) { _level = _vm->getRandomNumber(3); _compPlay = 2; } else { // Check for opponent flags for (int idx = 0; idx < 4; ++idx) { if (_vm->readFlags(314 + idx)) _level = idx; } } _opponent = FIXED(Jock); } void Darts::loadDarts() { Resources &res = *_vm->_res; Screen &screen = *_vm->_screen; byte palette[PALETTE_SIZE]; // Load images _hand1 = new ImageFile("hand1.vgs"); _hand2 = new ImageFile("hand2.vgs"); _dartGraphics = new ImageFile("darts.vgs"); _dartsLeft = new ImageFile("DartsLft.vgs"); _dartMap = new ImageFile("DartMap.vgs"); _dartBoard = new ImageFile("DartBd.vgs"); // Load and set the palette Common::SeekableReadStream *stream = res.load("DartBoard.pal"); stream->read(palette, PALETTE_SIZE); screen.translatePalette(palette); screen.setPalette(palette); delete stream; // Load the initial background screen._backBuffer1.blitFrom((*_dartBoard)[0], Common::Point(0, 0)); screen._backBuffer2.blitFrom(screen._backBuffer1); screen.blitFrom(screen._backBuffer1); } void Darts::closeDarts() { delete _dartBoard; delete _dartsLeft; delete _dartGraphics; delete _dartMap; delete _hand1; delete _hand2; } void Darts::showNames(int playerNum) { Screen &screen = *_vm->_screen; byte color; color = playerNum == 0 ? PLAYER_COLOR : DART_COLOR_FORE; screen.print(Common::Point(STATUS_INFO_X, STATUS_INFO_Y), 0, "%s", FIXED(Holmes)); screen._backBuffer1.fillRect(Common::Rect(STATUS_INFO_X, STATUS_INFO_Y + _spacing + 1, STATUS_INFO_X + 50, STATUS_INFO_Y + _spacing + 3), color); screen.fillRect(Common::Rect(STATUS_INFO_X, STATUS_INFO_Y + _spacing + 1, STATUS_INFO_X + 50, STATUS_INFO_Y + _spacing + 3), color); color = playerNum == 1 ? PLAYER_COLOR : DART_COLOR_FORE; screen.print(Common::Point(STATUS_INFO_X, STATUS_INFO_Y), 0, "%s", _opponent.c_str()); screen._backBuffer1.fillRect(Common::Rect(STATUS2_INFO_X, STATUS_INFO_Y + _spacing + 1, STATUS2_INFO_X + 50, STATUS_INFO_Y + _spacing + 3), color); screen.fillRect(Common::Rect(STATUS2_INFO_X, STATUS_INFO_Y + _spacing + 1, STATUS2_INFO_X + 50, STATUS_INFO_Y + _spacing + 3), color); screen._backBuffer2.blitFrom(screen._backBuffer1); } void Darts::showStatus(int playerNum) { Screen &screen = *_vm->_screen; const char *const CRICKET_SCORE_NAME[7] = { "20", "19", "18", "17", "16", "15", FIXED(Bull) }; screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(STATUS_INFO_X, STATUS_INFO_Y + 10), Common::Rect(STATUS_INFO_X, STATUS_INFO_Y + 10, STATUS_INFO_X + STATUS_INFO_WIDTH, STATUS_INFO_Y + STATUS_INFO_HEIGHT - 10)); screen.print(Common::Point(STATUS_INFO_X + 30, STATUS_INFO_Y + _spacing + 4), 0, "%d", _score1); screen.print(Common::Point(STATUS2_INFO_X + 30, STATUS_INFO_Y + _spacing + 4), 0, "%d", _score2); int temp = (_gameType == GAME_CRICKET) ? STATUS_INFO_Y + 10 * _spacing + 5 : STATUS_INFO_Y + 55; screen.print(Common::Point(STATUS_INFO_X, temp), 0, "%s: %d", FIXED(Round), _roundNum); if (_gameType == GAME_301) { screen.print(Common::Point(STATUS_INFO_X, STATUS_INFO_Y + 75), 0, "%s: %d", FIXED(TurnTotal), _roundScore); } else { // Show cricket scores for (int x = 0; x < 7; ++x) { screen.print(Common::Point(STATUS_INFO_X, STATUS_INFO_Y + 40 + x * _spacing), 0, "%s:", CRICKET_SCORE_NAME[x]); for (int y = 0; y < 2; ++y) { switch (CRICKET_SCORE_NAME[y][x]) { case 1: screen.print(Common::Point(STATUS_INFO_X + 38 + y*STATUS2_X_ADD, STATUS_INFO_Y + 40 + x * _spacing), 0, "/"); break; case 2: screen.print(Common::Point(STATUS_INFO_X + 38 + y*STATUS2_X_ADD, STATUS_INFO_Y + 40 + x * _spacing), 0, "X"); break; case 3: screen.print(Common::Point(STATUS_INFO_X + 38 + y * STATUS2_X_ADD - 1, STATUS_INFO_Y + 40 + x * _spacing), 0, "X"); screen.print(Common::Point(STATUS_INFO_X + 37 + y * STATUS2_X_ADD, STATUS_INFO_Y + 40 + x * _spacing), 0, "O"); break; default: break; } } } } screen.blitFrom(screen._backBuffer1, Common::Point(STATUS_INFO_X, STATUS_INFO_Y + 10), Common::Rect(STATUS_INFO_X, STATUS_INFO_Y + 10, STATUS_INFO_X + STATUS_INFO_WIDTH, STATUS_INFO_Y + STATUS_INFO_HEIGHT - 10)); } void Darts::erasePowerBars() { Screen &screen = *_vm->_screen; // Erase the old power bars and replace them with empty ones screen.fillRect(Common::Rect(DART_BAR_VX, DART_HEIGHT_Y, DART_BAR_VX + 9, DART_HEIGHT_Y + DART_BAR_SIZE), 0); screen._backBuffer1.transBlitFrom((*_dartGraphics)[0], Common::Point(DART_BAR_VX - 1, DART_HEIGHT_Y - 1)); screen.slamArea(DART_BAR_VX - 1, DART_HEIGHT_Y - 1, 10, DART_BAR_SIZE + 2); } bool Darts::dartHit() { Events &events = *_vm->_events; events.pollEventsAndWait(); // Keyboard check if (events.kbHit()) { events.clearEvents(); return true; } bool result = events._pressed && !_oldDartButtons; _oldDartButtons = events._pressed; return result; } int Darts::doPowerBar(const Common::Point &pt, byte color, int goToPower, int orientation) { Events &events = *_vm->_events; Screen &screen = *_vm->_screen; int x = 0; events.clearEvents(); events.delay(100); while (!_vm->shouldQuit()) { if (x >= DART_BAR_SIZE) break; if ((goToPower - 1) == x) break; else if (goToPower == 0) { if (dartHit()) break; } screen._backBuffer1.fillRect(Common::Rect(pt.x, pt.y + DART_BAR_SIZE - 1 - x, pt.x + 8, pt.y + DART_BAR_SIZE - 2 - x), color); screen._backBuffer1.transBlitFrom((*_dartGraphics)[0], Common::Point(pt.x - 1, pt.y - 1)); screen.slamArea(pt.x, pt.y + DART_BAR_SIZE - 1 - x, 8, 2); if (!(x % 8)) events.wait(1); x += 1; } return MIN(x * 100 / DART_BAR_SIZE, 100); } int Darts::drawHand(int goToPower, int computer) { Events &events = *_vm->_events; Screen &screen = *_vm->_screen; const int HAND_OFFSET[2] = { 72, 44 }; ImageFile *hands; int hand; goToPower = (goToPower * DARTBOARD_WIDTH) / 150; if (!computer) { hand = 0; hands = _hand1; } else { hand = 1; hands = _hand2; } _handSize.x = (*hands)[0]._offset.x + (*hands)[0]._width; _handSize.y = (*hands)[0]._offset.y + (*hands)[0]._height; // Clear keyboard buffer events.clearEvents(); events.delay(100); Common::Point pt(DARTBOARD_LEFT - HAND_OFFSET[hand], SHERLOCK_SCREEN_HEIGHT - _handSize.y); int x = 0; while (!_vm->shouldQuit()) { if (x >= DARTBOARD_WIDTH) break; if ((goToPower - 1) == x) break; else if (goToPower == 0) { if (dartHit()) break; } screen._backBuffer1.transBlitFrom((*hands)[0], pt); screen.slamArea(pt.x - 1, pt.y, _handSize.x + 1, _handSize.y); screen.restoreBackground(Common::Rect(pt.x, pt.y, pt.x + _handSize.x, pt.y + _handSize.y)); if (!(x % 8)) events.wait(1); ++x; ++pt.x; } _handX = pt.x - 1; return MIN(x * 100 / DARTBOARD_WIDTH, 100); } Common::Point Darts::convertFromScreenToScoreCoords(const Common::Point &pt) const { return Common::Point(CLIP((int)pt.x, 0, DARTBOARD_WIDTH), CLIP((int)pt.y, 0, DARTBOARD_HEIGHT)); } int Darts::dartScore(const Common::Point &pt) { Common::Point pos(pt.x - DARTBOARD_LEFT, pt.y - DARTBOARD_TOP); if (pos.x < 0 || pos.y < 0) return 0; int score; if (pos.x < DARTBOARD_WIDTH && pos.y < DARTBOARD_HEIGHT) { pos = convertFromScreenToScoreCoords(pos); score = *(const byte *)(*_dartMap)[0]._frame.getBasePtr(pos.x, pos.y); if (_gameType == GAME_301) { if (score >= 100) { if (score <= 120) // Hit a double score = (score - 100) * 2; else // Hit a triple score = (score - 120) * 3; } } else if (score >= 100) { if (score >= 120) // Hit a double score = (2 << 16) + (score - 100); else // Hit a triple score = (3 << 16) + (score - 120); } } else { score = 0; } return score; } void Darts::drawDartThrow(const Common::Point &dartPos, int computer) { Events &events = *_vm->_events; Screen &screen = *_vm->_screen; int cx, cy; int handCy; int drawX = 0, drawY = 0, oldDrawX = 0, oldDrawY = 0; int xSize = 0, ySize = 0, oldxSize = 0, oldySize = 0; int handOCx, handOCy; int ocx, ocy; int handOldxSize, handOldySize; int delta = 9; int dartNum; int hddy; // Draw the animation of the hand throwing the dart first // See which hand animation to use ImageFile &hands = !computer ? *_hand1 : *_hand2; int numFrames = !computer ? 14 : 13; ocx = ocy = handOCx = handOCy = 0; oldxSize = oldySize = handOldxSize = handOldySize = 1; cx = dartPos.x; cy = SHERLOCK_SCREEN_HEIGHT - _handSize.y - 20; hddy = (cy - dartPos.y) / (numFrames - 7); hddy += 2; hddy = hddy * 10 / 8; if (dartPos.y > 275) hddy += 3; for (int idx = 0; idx < numFrames; ++idx) { _handSize.x = hands[idx]._offset.x + hands[idx]._width; _handSize.y = hands[idx]._offset.y + hands[idx]._height; handCy = SHERLOCK_SCREEN_HEIGHT - _handSize.y; screen._backBuffer1.transBlitFrom(hands[idx], Common::Point(_handX, handCy)); screen.slamArea(_handX, handCy, _handSize.x + 1, _handSize.y); screen.slamArea(handOCx, handOCy, handOldxSize, handOldySize); screen.restoreBackground(Common::Rect(_handX, handCy, _handX + _handSize.x, handCy + _handSize.y)); handOCx = _handX; handOCy = handCy; handOldxSize = _handSize.x; handOldySize = _handSize.y; if (idx > 6) { dartNum = idx - 6; if (computer) dartNum += 19; xSize = (*_dartGraphics)[dartNum]._width; ySize = (*_dartGraphics)[dartNum]._height; ocx = drawX = cx - (*_dartGraphics)[dartNum]._width / 2; ocy = drawY = cy - (*_dartGraphics)[dartNum]._height; // Draw dart screen._backBuffer1.transBlitFrom((*_dartGraphics)[dartNum], dartPos); if (drawX < 0) { xSize += drawX; if (xSize < 0) xSize = 1; drawX = 0; } if (drawY < 0) { ySize += drawY; if (ySize < 0) ySize = 1; drawY = 0; } // Flush the drawn dart to the screen screen.slamArea(drawX, drawY, xSize, ySize); if (oldDrawX != -1) // Flush the erased dart area screen.slamArea(oldDrawX, oldDrawY, oldxSize, oldySize); screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(drawX, drawY), Common::Rect(drawX, drawY, drawX + xSize, drawY + ySize)); oldDrawX = drawX; oldDrawY = drawY; oldxSize = xSize; oldySize = ySize; cy -= hddy; } events.wait(1); } // Clear the last little bit of the hand from the screen screen.slamArea(handOCx, handOCy, handOldxSize, handOldySize); // Erase the old dart if (oldDrawX != -1) screen.slamArea(oldDrawX, oldDrawY, oldxSize, oldySize); screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(drawX, drawY), Common::Rect(drawX, drawY, drawX + xSize, drawY + ySize)); cx = dartPos.x; cy = dartPos.y + 2; oldDrawX = oldDrawY = -1; for (int idx = 5; idx <= 23; ++idx) { dartNum = idx - 4; if (computer) dartNum += 19; if (idx < 14) cy -= delta--; else if (idx == 14) delta = 1; if (idx > 14) cy += delta++; xSize = (*_dartGraphics)[dartNum]._width; ySize = (*_dartGraphics)[dartNum]._height; ocx = drawX = cx - (*_dartGraphics)[dartNum]._width / 2; ocy = drawY = cy - (*_dartGraphics)[dartNum]._height; screen._backBuffer1.transBlitFrom((*_dartGraphics)[dartNum], Common::Point(drawX, drawY)); if (drawX < 0) { xSize += drawX; if (xSize < 0) xSize = 1; drawX = 0; } if (drawY < 0) { ySize += drawY; if (ySize < 0) ySize = 1; drawY = 0; } // flush the dart screen.slamArea(drawX, drawY, xSize, ySize); if (oldDrawX != -1) screen.slamArea(oldDrawX, oldDrawY, oldxSize, oldySize); if (idx != 23) screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(drawX, drawY), Common::Rect(drawX, drawY, drawX + xSize, drawY + ySize)); // erase dart events.wait(1); oldDrawX = drawX; oldDrawY = drawY; oldxSize = xSize; oldySize = ySize; } dartNum = 19; if (computer) dartNum += 19; xSize = (*_dartGraphics)[dartNum]._width; ySize = (*_dartGraphics)[dartNum]._height; // Draw final dart on the board screen._backBuffer1.transBlitFrom((*_dartGraphics)[dartNum], Common::Point(ocx, ocy)); screen._backBuffer2.transBlitFrom((*_dartGraphics)[dartNum], Common::Point(ocx, ocy)); screen.slamArea(ocx, ocy, xSize, ySize); } int Darts::findNumberOnBoard(int aim, Common::Point &pt) { ImageFrame &img = (*_dartMap)[0]; if ((aim > 20) && ((aim != 25) && (aim != 50))) { if ((aim <= 40) && ((aim & 1) == 0)) { aim /= 2; aim += 100; } else { aim /= 3; aim += 120; } } bool done = false; for (int y = 0; y < img._width && !done; ++y) { for (int x = 0; x < img._height && !done; ++x) { byte score = *(const byte *)img._frame.getBasePtr(x, y); if (score == aim) { // Found a match. Aim at non-double/triple numbers whenever possible. // ie. Aim at 18 instead of triple 6 or double 9 done = true; if (aim < 21) { pt.x = x + 10; pt.y = y + 10; score = *(const byte *)img._frame.getBasePtr(x, y); if (score != aim) done = false; } else { // Aiming at double or triple pt.x = x + 3; pt.y = y + 3; } } } } pt = convertFromScreenToScoreCoords(pt); if (aim == 3) pt.y += 30; if (aim == 17) pt.y += 10; if (aim == 15) { pt.y += 5; pt.x += 5; } pt.y = DARTBOARD_HEIGHT - pt.y; return done; } void Darts::getComputerNumber(int playerNum, Common::Point &targetPos) { int score; int aim = 0; Common::Point pt; bool done = false; int cricketaimset = false; bool shootBull = false; score = (playerNum == 0) ? _score1 : _score2; if (_gameType == GAME_301) { // Try to hit number aim = score; if(score > 60) shootBull = true; } else { if (_cricketScore[playerNum][6] < 3) { // shoot at bull first aim = CRICKET_VALUE[6]; cricketaimset = true; } else { // Now check and shoot in this order: 20,19,18,17,16,15 for (int idx = 0; idx < 7; ++idx) { if (_cricketScore[playerNum][idx] < 3) { aim = CRICKET_VALUE[idx]; cricketaimset = true; break; } } } if (!cricketaimset) { // Everything is closed // just in case we don't get set in loop below, which should never happen aim = 14; for (int idx = 0; idx < 7; ++idx) { if (_cricketScore[playerNum^1][idx] < 3) { // Opponent has this open aim = CRICKET_VALUE[idx]; if (idx == 6) shootBull = true; } } } } if (shootBull) { // Aim at bulls eye targetPos.x = targetPos.y = 75; if (_level <= 1) { if (_vm->getRandomNumber(1) == 1) { targetPos.x += (_vm->getRandomNumber(20)-10); targetPos.y += (_vm->getRandomNumber(20)-10); } } } else { // Loop in case number does not exist on board do { done = findNumberOnBoard(aim, pt); --aim; } while (!done); pt.x += DARTBOARD_TOTALLEFT * 70 / 100; pt.y += DARTBOARD_TOTALTOP * 70 / 100; // old * 3/2 targetPos.x = pt.x * 100 / DARTBOARD_TOTALX * 3 / 2; targetPos.y = pt.y * 100 / DARTBOARD_TOTALY * 3 / 2; } // the higher the level, the more accurate the throw int v = _vm->getRandomNumber(9); v += _level * 2; if (v <= 2) { targetPos.x += _vm->getRandomNumber(70) - 35; targetPos.y += _vm->getRandomNumber(70) - 35; } else if (v <= 4) { targetPos.x += _vm->getRandomNumber(50) - 25; targetPos.y += _vm->getRandomNumber(50) - 25; } else if (v <= 6) { targetPos.x += _vm->getRandomNumber(30) - 15; targetPos.y += _vm->getRandomNumber(30) - 15; } else if (v <= 8) { targetPos.x += _vm->getRandomNumber(20) -10; targetPos.y += _vm->getRandomNumber(20) -10; } else if (v <= 10) { targetPos.x += _vm->getRandomNumber(11) - 5; targetPos.y += _vm->getRandomNumber(11) - 5; } if (targetPos.x < 1) targetPos.x = 1; if (targetPos.y < 1) targetPos.y = 1; } int Darts::throwDart(int dartNum, int computer) { Events &events = *_vm->_events; Screen &screen = *_vm->_screen; int height; int horiz; Common::Point targetPos; Common::String temp; /* clear keyboard buffer */ events.clearEvents(); erasePowerBars(); screen.print(Common::Point(_dartInfo.left, _dartInfo.top), 0, "%s # %d", FIXED(Dart), dartNum); drawDartsLeft(dartNum, computer); if (!computer) { screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing), 0, FIXED(HitAKey)); screen.print(Common::Point(_dartInfo.left, _dartInfo.top + _spacing * 2), 0, FIXED(ToStart)); } if (!computer) { // Wait for a hit while (!dartHit()) ; } else { events.wait(1); } drawDartsLeft(dartNum + 1, computer); screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(_dartInfo.left, _dartInfo.top - 1), Common::Rect(_dartInfo.left, _dartInfo.top - 1, _dartInfo.right, _dartInfo.bottom - 1)); screen.blitFrom(screen._backBuffer1, Common::Point(_dartInfo.left, _dartInfo.top - 1), Common::Rect(_dartInfo.left, _dartInfo.top - 1, _dartInfo.right, _dartInfo.bottom - 1)); if (computer) { getComputerNumber(computer - 1, targetPos); } else { // Keyboard control targetPos = Common::Point(0, 0); } horiz = drawHand(targetPos.x, computer); height = doPowerBar(Common::Point(DART_BAR_VX, DART_HEIGHT_Y), DART_COLOR_FORE, targetPos.y, 1); // Invert height height = 101 - height; // Copy power bars to the secondary back buffer screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(DART_BAR_VX - 1, DART_HEIGHT_Y - 1), Common::Rect(DART_BAR_VX - 1, DART_HEIGHT_Y - 1, DART_BAR_VX - 1 + 10, DART_HEIGHT_Y - 1 + DART_BAR_SIZE + 2)); Common::Point dartPos(DARTBOARD_TOTALLEFT + horiz*DARTBOARD_TOTALX / 100, DARTBOARD_TOTALTOP + height * DARTBOARD_TOTALY / 100); dartPos.x += 2 - _vm->getRandomNumber(4); dartPos.y += 2 - _vm->getRandomNumber(4); drawDartThrow(dartPos, computer); return dartScore(dartPos); } void Darts::doCricketScoreHits(int player, int scoreIndex, int numHits) { while (numHits--) { if (_cricketScore[player][scoreIndex] < 3) _cricketScore[player][scoreIndex]++; else if (_cricketScore[player ^ 1][scoreIndex] < 3) { if (player == 0) _score1 += CRICKET_VALUE[scoreIndex]; else _score2 += CRICKET_VALUE[scoreIndex]; } } } void Darts::updateCricketScore(int player, int dartHit, int multiplier) { if (dartHit < 15) return; if (dartHit <= 20) doCricketScoreHits(player, 20 - dartHit, multiplier); else if (dartHit == 25) doCricketScoreHits(player, 6, multiplier); } void Darts::drawDartsLeft(int dartNum, int computer) { Screen &screen = *_vm->_screen; const int DART_X1[3] = { 391, 451, 507 }; const int DART_Y1[3] = { 373, 373, 373 }; const int DART_X2[3] = { 393, 441, 502 }; const int DART_Y2[3] = { 373, 373, 373 }; screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(DART_X1[0], DART_Y1[0]), Common::Rect(DART_X1[0], DART_Y1[0], SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); for (int idx = 2; idx >= dartNum - 1; --idx) { if (computer) screen._backBuffer1.transBlitFrom((*_dartsLeft)[idx + 3], Common::Point(DART_X2[idx], DART_Y2[idx])); else screen._backBuffer1.transBlitFrom((*_dartsLeft)[idx], Common::Point(DART_X1[idx], DART_Y1[idx])); } screen.slamArea(DART_X1[0], DART_Y1[0], SHERLOCK_SCREEN_WIDTH - DART_X1[0], SHERLOCK_SCREEN_HEIGHT - DART_Y1[0]); } } // End of namespace Tattoo } // End of namespace Sherlock