/* 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 3 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, see . * */ /* * Based on ScottFree interpreter version 1.14 developed by Swansea * University Computer Society without disassembly of any other game * drivers, only of game databases as permitted by EEC law (for purposes * of compatibility). * * Licensed under GPLv2 * * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott */ #include "glk/scott/scott.h" #include "glk/scott/saga_draw.h" #include "glk/scott/resource.h" #include "glk/scott/decompress_text.h" #include "glk/scott/seas_of_blood.h" namespace Glk { namespace Scott { #define VICTORY 0 #define LOSS 1 #define DRAW 2 #define FLEE 3 #define ERROR 99 int getEnemyStats(int *strike, int *stamina, int *boatFlag); void battleLoop(int enemy, int strike, int stamina, int boatFlag); void swapStaminaAndCrewStrength(void); void bloodBattle(void); void adventureSheet(void) { g_scott->glk_stream_set_current(g_scott->glk_window_get_stream(_G(_bottomWindow))); g_scott->glk_set_style(style_Preformatted); g_scott->output("\nADVENTURE SHEET\n\n"); g_scott->output("SKILL :"); g_scott->outputNumber(9); g_scott->output(" STAMINA :"); g_scott->outputNumber(_G(_counters)[3]); g_scott->output("\nLOG :"); g_scott->outputNumber(_G(_counters)[6]); if (_G(_counters)[6] < 10) g_scott->output(" PROVISIONS :"); else g_scott->output(" PROVISIONS :"); // one less space! g_scott->outputNumber(_G(_counters)[5]); g_scott->output("\nCREW STRIKE:"); g_scott->outputNumber(9); g_scott->output(" CREW STRENGTH:"); g_scott->outputNumber(_G(_counters)[7]); g_scott->output("\n\n * * * * * * * * * * * * * * * * * * * * *\n\n"); g_scott->listInventory(); g_scott->output("\n"); g_scott->glk_set_style(style_Normal); } void bloodAction(int p) { switch (p) { case 0: break; case 1: // Update LOG _G(_counters)[6]++; break; case 2: // Battle g_scott->look(); g_scott->output("You are attacked \n"); g_scott->output(" \n"); g_scott->hitEnter(); bloodBattle(); break; default: error("bloodAction: Unhandled special action %d", p); break; } } void mirrorLeftHalf(void) { for (int line = 0; line < 12; line++) { for (int col = 32; col > 16; col--) { _G(_buffer)[line * 32 + col - 1][8] = _G(_buffer)[line * 32 + (32 - col)][8]; for (int pixrow = 0; pixrow < 8; pixrow++) _G(_buffer)[line * 32 + col - 1][pixrow] = _G(_buffer)[line * 32 + (32 - col)][pixrow]; flip(_G(_buffer)[line * 32 + col - 1]); } } } void replaceColour(uint8_t before, uint8_t after) { // I don't think any of the data has bit 7 set, // so masking it is probably unnecessary, but this is what // the original code does. uint8_t beforeink = before & 7; uint8_t afterink = after & 7; uint8_t inkmask = 0x07; uint8_t beforepaper = beforeink << 3; uint8_t afterpaper = afterink << 3; uint8_t papermask = 0x38; for (int j = 0; j < 384; j++) { if ((_G(_buffer)[j][8] & inkmask) == beforeink) { _G(_buffer)[j][8] = (_G(_buffer)[j][8] & ~inkmask) | afterink; } if ((_G(_buffer)[j][8] & papermask) == beforepaper) { _G(_buffer)[j][8] = (_G(_buffer)[j][8] & ~papermask) | afterpaper; } } } void drawColour(uint8_t x, uint8_t y, uint8_t colour, uint8_t length) { for (int i = 0; i < length; i++) { _G(_buffer)[y * 32 + x + i][8] = colour; } } void makeLight(void) { for (int i = 0; i < 384; i++) { _G(_buffer)[i][8] = _G(_buffer)[i][8] | 0x40; } } void flipImage(void) { uint8_t mirror[384][9]; for (int line = 0; line < 12; line++) { for (int col = 32; col > 0; col--) { for (int pixrow = 0; pixrow < 9; pixrow++) mirror[line * 32 + col - 1][pixrow] = _G(_buffer)[line * 32 + (32 - col)][pixrow]; flip(mirror[line * 32 + col - 1]); } } memcpy(_G(_buffer), mirror, 384 * 9); } void drawObjectImage(uint8_t x, uint8_t y) { for (int i = 0; i < _G(_gameHeader)->_numItems; i++) { if (_G(_items)[i]._flag != MY_LOC) continue; if (_G(_items)[i]._location != MY_LOC) continue; drawSagaPictureAtPos(_G(_items)[i]._image, x, y); _G(_shouldDrawObjectImages) = 0; } } void drawBlood(int loc) { memset(_G(_buffer), 0, 384 * 9); uint8_t *ptr = _G(_bloodImageData); for (int i = 0; i < loc; i++) { while (*(ptr) != 0xff) ptr++; ptr++; } while (ptr < _G(_bloodImageData) + 2010) { switch (*ptr) { case 0xff: if (loc == 13) { _G(_buffer)[8 * 32 + 18][8] = _G(_buffer)[8 * 32 + 18][8] & ~0x40; _G(_buffer)[8 * 32 + 17][8] = _G(_buffer)[8 * 32 + 17][8] & ~0x40; _G(_buffer)[8 * 32 + 9][8] = _G(_buffer)[8 * 32 + 9][8] & ~0x40; _G(_buffer)[8 * 32 + 10][8] = _G(_buffer)[8 * 32 + 10][8] & ~0x40; } return; case 0xfe: mirrorLeftHalf(); break; case 0xfD: replaceColour(*(ptr + 1), *(ptr + 2)); ptr += 2; break; case 0xfc: // Draw colour: x, y, attribute, length drawColour(*(ptr + 1), *(ptr + 2), *(ptr + 3), *(ptr + 4)); ptr = ptr + 4; break; case 0xfb: // Make all screen colours bright makeLight(); break; case 0xfa: // Flip entire image horizontally flipImage(); break; case 0xf9: // Draw object image (if present) at x, y drawObjectImage(*(ptr + 1), *(ptr + 2)); ptr = ptr + 2; break; default: // else draw image *ptr at x, y drawSagaPictureAtPos(*ptr, *(ptr + 1), *(ptr + 2)); ptr = ptr + 2; } ptr++; } } void seasOfBloodRoomImage(void) { _G(_shouldDrawObjectImages) = 1; drawBlood(MY_LOC); for (int ct = 0; ct <= _G(_gameHeader)->_numItems; ct++) if (_G(_items)[ct]._image && _G(_shouldDrawObjectImages)) { if ((_G(_items)[ct]._flag & 127) == MY_LOC && _G(_items)[ct]._location == MY_LOC) { g_scott->drawImage(_G(_items)[ct]._image); } } drawSagaPictureFromBuffer(); } //static void SOBPrint(winid_t w, const char *fmt, ...) //#ifdef __GNUC__ // __attribute__((__format__(__printf__, 2, 3))) //#endif // ; static void SOBPrint(winid_t w, const char *fmt, ...) { va_list ap; char msg[2048]; int size = sizeof msg; va_start(ap, fmt); vsnprintf(msg, size, fmt, ap); va_end(ap); g_scott->glk_put_string_stream(g_scott->glk_window_get_stream(w), msg); } glui32 optimalDicePixelSize(glui32 *width, glui32 *height) { int idealWidth = 8; int idealHeight = 8; *width = idealWidth; *height = idealHeight; int multiplier = 1; uint graphwidth, graphheight; g_scott->glk_window_get_size(_G(_leftDiceWin), &graphwidth, &graphheight); multiplier = graphheight / idealHeight; if ((glui32)(idealWidth * multiplier) > graphwidth) multiplier = graphwidth / idealWidth; if (multiplier < 2) multiplier = 2; multiplier = multiplier / 2; *width = idealWidth * multiplier; *height = idealHeight * multiplier; return multiplier; } static void drawBorder(winid_t win) { uint width, height; g_scott->glk_stream_set_current(g_scott->glk_window_get_stream(win)); g_scott->glk_window_get_size(win, &width, &height); height--; width -= 2; g_scott->glk_window_move_cursor(win, 0, 0); g_scott->glk_put_char_uni(0x250F); // Top left corner for (glui32 i = 1; i < width; i++) g_scott->glk_put_char_uni(0x2501); // Top g_scott->glk_put_char_uni(0x2513); // Top right corner for (glui32 i = 1; i < height; i++) { g_scott->glk_window_move_cursor(win, 0, i); g_scott->glk_put_char_uni(0x2503); g_scott->glk_window_move_cursor(win, width, i); g_scott->glk_put_char_uni(0x2503); } g_scott->glk_window_move_cursor(win, 0, height); g_scott->glk_put_char_uni(0x2517); for (glui32 i = 1; i < width; i++) g_scott->glk_put_char_uni(0x2501); g_scott->glk_put_char_uni(0x251B); } static void redrawStaticText(winid_t win, int boatFlag) { g_scott->glk_stream_set_current(g_scott->glk_window_get_stream(win)); g_scott->glk_window_move_cursor(win, 2, 4); if (boatFlag) { g_scott->glk_put_string("STRIKE :\n"); g_scott->glk_window_move_cursor(win, 2, 5); g_scott->glk_put_string("CRW STR :"); } else { g_scott->glk_put_string("SKILL :\n"); g_scott->glk_window_move_cursor(win, 2, 5); g_scott->glk_put_string("STAMINA :"); } if (win == _G(_battleRight)) { uint width; g_scott->glk_window_get_size(_G(_battleRight), &width, 0); g_scott->glk_window_move_cursor(_G(_battleRight), width - 6, 1); g_scott->glk_put_string("YOU"); } } static void redrawBattleScreen(int boatFlag) { uint graphwidth, graphheight; glui32 optimal_width, optimal_height; g_scott->glk_window_get_size(_G(_leftDiceWin), &graphwidth, &graphheight); _G(_dicePixelSize) = optimalDicePixelSize(&optimal_width, &optimal_height); _G(_diceXOffset) = (graphwidth - optimal_width) / 2; _G(_diceYOffset) = (graphheight - optimal_height - _G(_dicePixelSize)) / 2; drawBorder(_G(_topWindow)); drawBorder(_G(_battleRight)); redrawStaticText(_G(_topWindow), boatFlag); redrawStaticText(_G(_battleRight), boatFlag); } static void setupBattleScreen(int boatFlag) { winid_t parent = g_scott->glk_window_get_parent(_G(_topWindow)); g_scott->glk_window_set_arrangement(parent, winmethod_Above | winmethod_Fixed, 7, _G(_topWindow)); g_scott->glk_window_clear(_G(_topWindow)); g_scott->glk_window_clear(_G(_bottomWindow)); _G(_battleRight) = g_scott->glk_window_open(_G(_topWindow), winmethod_Right | winmethod_Proportional, 50, wintype_TextGrid, 0); _G(_leftDiceWin) = g_scott->glk_window_open(_G(_topWindow), winmethod_Right | winmethod_Proportional, 30, wintype_Graphics, 0); _G(_rightDiceWin) = g_scott->glk_window_open(_G(_battleRight), winmethod_Left | winmethod_Proportional, 30, wintype_Graphics, 0); // Set the graphics window background to match the top window background, best as we can, and clear the window. if (g_scott->glk_style_measure(_G(_topWindow), style_Normal, stylehint_BackColor, &_G(_backgroundColour))) { g_scott->glk_window_set_background_color(_G(_leftDiceWin), _G(_backgroundColour)); g_scott->glk_window_set_background_color(_G(_rightDiceWin), _G(_backgroundColour)); g_scott->glk_window_clear(_G(_leftDiceWin)); g_scott->glk_window_clear(_G(_rightDiceWin)); } if (_G(_palChosen) == C64B) _G(_diceColour) = 0x5f48e9; else _G(_diceColour) = 0xff0000; redrawBattleScreen(boatFlag); } void bloodBattle(void) { int enemy, strike, stamina, boatFlag; enemy = getEnemyStats(&strike, &stamina, &boatFlag); // Determine their stats if (enemy == 0) { error("Seas of blood battle: No enemy in location?\n"); return; } setupBattleScreen(boatFlag); battleLoop(enemy, strike, stamina, boatFlag); // Into the battle loops if (boatFlag) swapStaminaAndCrewStrength(); // Switch back stamina - crew strength g_scott->glk_window_close(_G(_leftDiceWin), nullptr); g_scott->glk_window_close(_G(_rightDiceWin), nullptr); g_scott->glk_window_close(_G(_battleRight), nullptr); g_scott->closeGraphicsWindow(); g_scott->openGraphicsWindow(); seasOfBloodRoomImage(); } int getEnemyStats(int *strike, int *stamina, int *boatFlag) { int enemy, i = 0; while (i < 124) { enemy = _G(_enemyTable)[i]; if (_G(_items)[enemy]._location == MY_LOC) { i++; *strike = _G(_enemyTable)[i++]; *stamina = _G(_enemyTable)[i++]; *boatFlag = _G(_enemyTable)[i]; if (*boatFlag) { swapStaminaAndCrewStrength(); // Switch stamina - crew strength } return enemy; } i = i + 4; // Skip to next entry } return 0; } void drawRect(winid_t win, int32_t x, int32_t y, int32_t width, int32_t height, int32_t color) { g_scott->glk_window_fill_rect(win, color, x * _G(_dicePixelSize) + _G(_diceXOffset), y * _G(_dicePixelSize) + _G(_diceYOffset), width * _G(_dicePixelSize), height * _G(_dicePixelSize)); } void drawGraphicalDice(winid_t win, int number) { // The eye-less dice backgrounds consist of two rectangles on top of each // other drawRect(win, 1, 2, 7, 5, _G(_diceColour)); drawRect(win, 2, 1, 5, 7, _G(_diceColour)); switch (number + 1) { case 1: drawRect(win, 4, 4, 1, 1, _G(_backgroundColour)); break; case 2: drawRect(win, 2, 6, 1, 1, _G(_backgroundColour)); drawRect(win, 6, 2, 1, 1, _G(_backgroundColour)); break; case 3: drawRect(win, 2, 6, 1, 1, _G(_backgroundColour)); drawRect(win, 4, 4, 1, 1, _G(_backgroundColour)); drawRect(win, 6, 2, 1, 1, _G(_backgroundColour)); break; case 4: drawRect(win, 2, 6, 1, 1, _G(_backgroundColour)); drawRect(win, 6, 2, 1, 1, _G(_backgroundColour)); drawRect(win, 2, 2, 1, 1, _G(_backgroundColour)); drawRect(win, 6, 6, 1, 1, _G(_backgroundColour)); break; case 5: drawRect(win, 2, 6, 1, 1, _G(_backgroundColour)); drawRect(win, 6, 2, 1, 1, _G(_backgroundColour)); drawRect(win, 2, 2, 1, 1, _G(_backgroundColour)); drawRect(win, 6, 6, 1, 1, _G(_backgroundColour)); drawRect(win, 4, 4, 1, 1, _G(_backgroundColour)); break; case 6: drawRect(win, 2, 6, 1, 1, _G(_backgroundColour)); drawRect(win, 6, 2, 1, 1, _G(_backgroundColour)); drawRect(win, 2, 2, 1, 1, _G(_backgroundColour)); drawRect(win, 2, 4, 1, 1, _G(_backgroundColour)); drawRect(win, 6, 4, 1, 1, _G(_backgroundColour)); drawRect(win, 6, 6, 1, 1, _G(_backgroundColour)); break; default: break; } } void updateDice(int ourTurn, int leftDice, int rightDice) { leftDice--; rightDice--; g_scott->glk_window_clear(_G(_leftDiceWin)); g_scott->glk_window_clear(_G(_rightDiceWin)); _G(_diceXOffset) = _G(_diceXOffset) - _G(_dicePixelSize); drawGraphicalDice(_G(_leftDiceWin), leftDice); _G(_diceXOffset) = _G(_diceXOffset) + _G(_dicePixelSize); drawGraphicalDice(_G(_rightDiceWin), rightDice); winid_t win = ourTurn ? _G(_battleRight) : _G(_topWindow); g_scott->glk_window_move_cursor(win, 2, 1); g_scott->glk_stream_set_current(g_scott->glk_window_get_stream(win)); g_scott->glk_put_char_uni(0x2680 + leftDice); g_scott->glk_put_char('+'); g_scott->glk_put_char_uni(0x2680 + rightDice); g_scott->glk_window_move_cursor(win, 2, 2); SOBPrint(win, "%d %d", leftDice + 1, rightDice + 1); } void printSum(int ourTurn, int sum, int strike) { winid_t win = ourTurn ? _G(_battleRight) : _G(_topWindow); g_scott->glk_stream_set_current(g_scott->glk_window_get_stream(win)); g_scott->glk_window_move_cursor(win, 6, 1); SOBPrint(win, "+ %d = %d", strike, sum); g_scott->glk_stream_set_current(g_scott->glk_window_get_stream(_G(_battleRight))); g_scott->glk_window_move_cursor(_G(_battleRight), 6, 1); g_scott->glk_put_string("+ 9 = "); } void updateResult(int ourTurn, int strike, int stamina, int boatFlag) { winid_t win = ourTurn ? _G(_battleRight) : _G(_topWindow); g_scott->glk_stream_set_current(g_scott->glk_window_get_stream(win)); g_scott->glk_window_move_cursor(win, 2, 4); if (boatFlag) { SOBPrint(win, "STRIKE : %d\n", strike); g_scott->glk_window_move_cursor(win, 2, 5); SOBPrint(win, "CRW STR : %d", stamina); } else { SOBPrint(win, "SKILL : %d\n", strike); g_scott->glk_window_move_cursor(win, 2, 5); SOBPrint(win, "STAMINA : %d", stamina); } } void clearResult(void) { winid_t win = _G(_topWindow); uint width; for (int j = 0; j < 2; j++) { g_scott->glk_window_get_size(win, &width, 0); g_scott->glk_stream_set_current(g_scott->glk_window_get_stream(win)); g_scott->glk_window_move_cursor(win, 11, 1); for (int i = 0; i < 10; i++) g_scott->glk_put_string(" "); drawBorder(win); win = _G(_battleRight); } } void clearStamina(void) { winid_t win = _G(_topWindow); uint width; for (int j = 0; j < 2; j++) { g_scott->glk_window_get_size(win, &width, 0); g_scott->glk_stream_set_current(g_scott->glk_window_get_stream(win)); g_scott->glk_window_move_cursor(win, 11, 5); for (int i = 0; i < (int)width - 13; i++) g_scott->glk_put_string(" "); drawBorder(win); win = _G(_battleRight); } } static void rearrangeBattleDisplay(int strike, int stamina, int boatFlag) { g_scott->updateSettings(); g_scott->glk_cancel_char_event(_G(_topWindow)); g_scott->closeGraphicsWindow(); g_scott->glk_window_close(_G(_battleRight), nullptr); g_scott->glk_window_close(_G(_leftDiceWin), nullptr); g_scott->glk_window_close(_G(_rightDiceWin), nullptr); seasOfBloodRoomImage(); setupBattleScreen(boatFlag); updateResult(0, strike, stamina, boatFlag); updateResult(1, 9, _G(_counters)[3], boatFlag); drawBorder(_G(_topWindow)); drawBorder(_G(_battleRight)); redrawStaticText(_G(_topWindow), boatFlag); redrawStaticText(_G(_battleRight), boatFlag); g_scott->glk_request_char_event(_G(_topWindow)); } int rollDice(int strike, int stamina, int boatFlag) { clearResult(); redrawStaticText(_G(_battleRight), boatFlag); g_scott->glk_request_timer_events(60); int rolls = 0; int ourTurn = 0; int leftDice = 1 + g_scott->getRandomNumber(100) % 6; int rightDice = 1 + g_scott->getRandomNumber(100) % 6; int ourResult; int theirResult = 0; int theirDiceStopped = 0; event_t event; int enemyRolls = 20 + g_scott->getRandomNumber(100) % 10; g_scott->glk_cancel_char_event(_G(_topWindow)); g_scott->glk_request_char_event(_G(_topWindow)); g_scott->glk_stream_set_current(g_scott->glk_window_get_stream(_G(_bottomWindow))); g_scott->glk_put_string("Their throw"); int delay = 60; while (!g_vm->shouldQuit()) { g_scott->glk_select(&event); if (event.type == evtype_Timer) { if (theirDiceStopped) { g_scott->glk_request_timer_events(60); theirDiceStopped = 0; printSum(ourTurn, theirResult, strike); ourTurn = 1; g_scott->glk_window_clear(_G(_bottomWindow)); g_scott->glk_cancel_char_event(_G(_topWindow)); g_scott->glk_request_char_event(_G(_topWindow)); g_scott->glk_stream_set_current(g_scott->glk_window_get_stream(_G(_bottomWindow))); g_scott->glk_put_string("Your throw\n"); g_scott->glk_put_string(" to stop dice"); if (!boatFlag) g_scott->glk_put_string(" to run"); } else if (ourTurn == 0) { g_scott->glk_request_timer_events(delay); } rolls++; if (rolls % 2) leftDice = 1 + g_scott->getRandomNumber(100) % 6; else rightDice = 1 + g_scott->getRandomNumber(100) % 6; updateDice(ourTurn, leftDice, rightDice); if (ourTurn == 0 && rolls == enemyRolls) { g_scott->glk_window_clear(_G(_bottomWindow)); theirResult = leftDice + rightDice + strike; SOBPrint(_G(_bottomWindow), "Their result: %d + %d + %d = %d\n", leftDice, rightDice, strike, theirResult); g_scott->glk_request_timer_events(1000); theirDiceStopped = 1; } } if (event.type == evtype_CharInput) { if (ourTurn && (event.val1 == keycode_Return)) { updateDice(ourTurn, leftDice, rightDice); ourResult = leftDice + rightDice + 9; printSum(ourTurn, ourResult, 9); if (theirResult > ourResult) { return LOSS; } else if (ourResult > theirResult) { return VICTORY; } else { return DRAW; } } else if (MY_LOC != 1 && (event.val1 == 'X' || event.val1 == 'x')) { MY_LOC = _G(_savedRoom); return FLEE; } else { g_scott->glk_request_char_event(_G(_topWindow)); } } if (event.type == evtype_Arrange) { rearrangeBattleDisplay(strike, stamina, boatFlag); } } return ERROR; } void battleHitEnter(int strike, int stamina, int boatFlag) { g_scott->glk_request_char_event(_G(_bottomWindow)); event_t ev; int result = 0; do { g_scott->glk_select(&ev); if (ev.type == evtype_CharInput) { if (ev.val1 == keycode_Return) { result = 1; } else { g_scott->glk_request_char_event(_G(_bottomWindow)); } } if (ev.type == evtype_Arrange) { rearrangeBattleDisplay(strike, stamina, boatFlag); } } while (result == 0 && !g_vm->shouldQuit()); } void battleLoop(int enemy, int strike, int stamina, int boatFlag) { updateResult(0, strike, stamina, boatFlag); updateResult(1, 9, _G(_counters)[3], boatFlag); do { int result = rollDice(strike, stamina, boatFlag); g_scott->glk_cancel_char_event(_G(_topWindow)); g_scott->glk_window_clear(_G(_bottomWindow)); clearStamina(); g_scott->glk_stream_set_current(g_scott->glk_window_get_stream(_G(_bottomWindow))); if (result == LOSS) { _G(_counters)[3] -= 2; if (_G(_counters)[3] <= 0) { SOBPrint(_G(_bottomWindow), "%s\n", boatFlag ? "THE BANSHEE HAS BEEN SUNK!" : "YOU HAVE BEEN KILLED!"); _G(_counters)[3] = 0; _G(_bitFlags) |= (1 << 6); _G(_counters)[7] = 0; } else { SOBPrint(_G(_bottomWindow), "%s", _G(_battleMessages)[1 + g_scott->getRandomNumber(100) % 5 + 16 * boatFlag]); } } else if (result == VICTORY) { stamina -= 2; if (stamina <= 0) { g_scott->glk_put_string("YOU HAVE WON!\n"); _G(_bitFlags) &= ~(1 << 6); stamina = 0; } else { SOBPrint(_G(_bottomWindow), "%s", _G(_battleMessages)[6 + g_scott->getRandomNumber(100) % 5 + 16 * boatFlag]); } } else if (result == FLEE) { _G(_bitFlags) |= (1 << 6); MY_LOC = _G(_savedRoom); return; } else { SOBPrint(_G(_bottomWindow), "%s", _G(_battleMessages)[11 + g_scott->getRandomNumber(100) % 5 + 16 * boatFlag]); } g_scott->glk_put_string("\n\n"); if (_G(_counters)[3] > 0 && stamina > 0) { g_scott->glk_put_string(" to roll dice"); if (!boatFlag) g_scott->glk_put_string(" to run"); } updateResult(0, strike, stamina, boatFlag); updateResult(1, 9, _G(_counters)[3], boatFlag); battleHitEnter(strike, stamina, boatFlag); g_scott->glk_window_clear(_G(_bottomWindow)); } while (stamina > 0 && _G(_counters)[3] > 0 && !g_vm->shouldQuit()); } void swapStaminaAndCrewStrength(void) { uint8_t temp = _G(_counters)[7]; // Crew strength _G(_counters)[7] = _G(_counters)[3]; // Stamina _G(_counters)[3] = temp; } int loadExtraSeasOfBloodData(void) { _G(_drawToBuffer) = 1; int offset; offset = 0x47b7 + _G(_fileBaselineOffset); uint8_t *ptr = seekToPos(_G(_entireFile), offset); int ct; for (ct = 0; ct < 124; ct++) { _G(_enemyTable)[ct] = *(ptr++); if (_G(_enemyTable)[ct] == 0xff) break; } ptr = seekToPos(_G(_entireFile), 0x71DA + _G(_fileBaselineOffset)); for (int i = 0; i < 32; i++) { _G(_battleMessages)[i] = decompressText(ptr, i); } offset = 0x7af5 - 16357 + _G(_fileBaselineOffset); int data_length = 2010; _G(_bloodImageData) = new uint8_t[data_length]; ptr = seekToPos(_G(_entireFile), offset); for (int i = 0; i < data_length; i++) _G(_bloodImageData)[i] = *(ptr++); for (int i = I_DONT_UNDERSTAND; i <= THATS_BEYOND_MY_POWER; i++) _G(_sys)[i] = _G(_systemMessages)[4 - I_DONT_UNDERSTAND + i]; for (int i = YOU_ARE; i <= HIT_ENTER; i++) _G(_sys)[i] = _G(_systemMessages)[13 - YOU_ARE + i]; _G(_sys)[OK] = _G(_systemMessages)[2]; _G(_sys)[PLAY_AGAIN] = _G(_systemMessages)[3]; _G(_sys)[YOURE_CARRYING_TOO_MUCH] = _G(_systemMessages)[27]; _G(_items)[125]._text = "A loose plank"; _G(_items)[125]._autoGet = "PLAN"; return 0; } int loadExtraSeasOfBlood64Data(void) { _G(_drawToBuffer) = 1; int offset; offset = 0x3fee + _G(_fileBaselineOffset); uint8_t *ptr; ptr = seekToPos(_G(_entireFile), offset); int ct; for (ct = 0; ct < 124; ct++) { _G(_enemyTable)[ct] = *(ptr++); if (_G(_enemyTable)[ct] == 0xff) break; } offset = 0x82f6 + _G(_fileBaselineOffset); ptr = seekToPos(_G(_entireFile), offset); for (int i = 0; i < 32; i++) { _G(_battleMessages)[i] = decompressText(ptr, i); } offset = 0x5299 + _G(_fileBaselineOffset); int data_length = 2010; _G(_bloodImageData) = new uint8_t[data_length]; ptr = seekToPos(_G(_entireFile), offset); for (int i = 0; i < data_length; i++) { _G(_bloodImageData)[i] = *(ptr++); } SysMessageType messagekey[] = { NORTH, SOUTH, EAST, WEST, UP, DOWN, EXITS, YOU_SEE, YOU_ARE, YOU_CANT_GO_THAT_WAY, OK, WHAT_NOW, HUH, YOU_HAVE_IT, YOU_HAVENT_GOT_IT, DROPPED, TAKEN, INVENTORY, YOU_DONT_SEE_IT, THATS_BEYOND_MY_POWER, DIRECTION, YOURE_CARRYING_TOO_MUCH, PLAY_AGAIN, RESUME_A_SAVED_GAME, YOU_CANT_DO_THAT_YET, I_DONT_UNDERSTAND, NOTHING}; for (int i = 0; i < 27; i++) { _G(_sys)[messagekey[i]] = _G(_systemMessages)[i]; } return 0; } } // End of namespace Scott } // End of namespace Glk