Permalink
Browse files

MUTATIONOFJB: Implement RANDOM command.

  • Loading branch information...
MiroslavR authored and sev- committed Jul 14, 2018
1 parent febff83 commit 3b614f08327441d5252add7c16f4955652e32d0a
@@ -56,7 +56,7 @@ bool EndBlockCommandParser::parse(const Common::String &line, ScriptParseContext
}

const char firstChar = line.firstChar();
if (firstChar != '#' && firstChar != '=' && firstChar != '-') {
if (firstChar != '#' && firstChar != '=' && firstChar != '-' && firstChar != '\\') {
return false;
}

@@ -0,0 +1,110 @@
/* 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 "mutationofjb/commands/randomcommand.h"

#include "mutationofjb/game.h"
#include "mutationofjb/script.h"
#include "common/debug.h"
#include "common/random.h"
#include "common/translation.h"

/*
"RANDOM " <numChoices>
RANDOM command randomly picks one of the command blocks that
follow it and jumps to its start.
These blocks start with "/" and end with "\". The end of a random
block also ends the current section. The number of blocks must
match numChoices.
*/

namespace MutationOfJB {

bool RandomCommandParser::parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) {
if (line.size() < 8 || !line.hasPrefix("RANDOM")) {
return false;
}

int numChoices = atoi(line.c_str() + 7);
if (parseCtx._pendingRandomCommand) {
// Nested RANDOM commands are unused and not properly supported by the original game.
warning(_("Ignoring nested RANDOM command."));
} else if (numChoices >= 1) {
RandomCommand *randomCommand = new RandomCommand(static_cast<uint>(numChoices));
parseCtx._pendingRandomCommand = randomCommand;
command = randomCommand;
} else {
warning(_("Ignoring malformed RANDOM command with %d choices."), numChoices);
}

return true;
}

bool RandomBlockStartParser::parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&) {
if (line != "/") {
return false;
}

if (!parseCtx._pendingRandomCommand) {
warning(_("Unexpected start of RANDOM block"));
}

return true;
}

void RandomBlockStartParser::transition(ScriptParseContext &parseCtx, Command *, Command *newCommand, CommandParser *) {
if (newCommand && parseCtx._pendingRandomCommand) {
parseCtx._pendingRandomCommand->_choices.push_back(newCommand);
}
}

RandomCommand::RandomCommand(uint numChoices)
: _numChoices(numChoices),
_chosenNext(nullptr)
{
_choices.reserve(numChoices);
}

Command::ExecuteResult RandomCommand::execute(ScriptExecutionContext &scriptExecCtx) {
assert(!_choices.empty());

Common::RandomSource &rng = scriptExecCtx.getGame().getRandomSource();
uint choice = rng.getRandomNumber(_choices.size() - 1);
_chosenNext = _choices[choice];
return Finished;
}

Command *RandomCommand::next() const {
return _chosenNext;
}

Common::String RandomCommand::debugString() const {
return Common::String::format("RANDOM %u", _numChoices);
}

const RandomCommand::Choices &RandomCommand::getChoices() const {
return _choices;
}

}
@@ -0,0 +1,70 @@
/* 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.
*
*/

#ifndef MUTATIONOFJB_RANDOMCOMMAND_H
#define MUTATIONOFJB_RANDOMCOMMAND_H

#include "mutationofjb/commands/command.h"
#include "common/array.h"
#include "common/scummsys.h"

namespace MutationOfJB {

class RandomCommandParser : public CommandParser {
public:
RandomCommandParser() {}

virtual bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
};

class RandomBlockStartParser : public CommandParser {
public:
RandomBlockStartParser() {}

virtual bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
virtual void transition(ScriptParseContext &parseCtx, Command *oldCommand, Command *newCommand, CommandParser *newCommandParser) override;
};

class RandomCommand : public Command {
friend class RandomBlockStartParser;

public:
typedef Common::Array<Command *> Choices;

RandomCommand(uint numChoices);

virtual ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
virtual Command *next() const override;

virtual Common::String debugString() const override;

const Choices &getChoices() const;

private:
uint _numChoices;
Choices _choices;
Command *_chosenNext;
};

}

#endif
@@ -30,6 +30,7 @@
#include "mutationofjb/commands/seqcommand.h"
#include "mutationofjb/commands/conditionalcommand.h"
#include "mutationofjb/commands/callmacrocommand.h"
#include "mutationofjb/commands/randomcommand.h"
#include "common/debug-channels.h"
#include "common/translation.h"
#include "common/scummsys.h"
@@ -152,6 +153,14 @@ void Console::showCommands(Command *command, int indentLevel) {
command = nullptr;
} else if (CallMacroCommand* const callMacroCmd = dynamic_cast<CallMacroCommand *>(command)) {
command = callMacroCmd->getReturnCommand();
} else if (RandomCommand* const randomCmd = dynamic_cast<RandomCommand *>(command)) {
const RandomCommand::Choices &choices = randomCmd->getChoices();
for (RandomCommand::Choices::size_type i = 0; i < choices.size(); ++i) {
showIndent(indentLevel + 1);
debugPrintf("CASE %u\n", i);
showCommands(choices[i], indentLevel + 2);
}
command = nullptr;
} else {
command = nullptr;
}
@@ -36,6 +36,7 @@ namespace MutationOfJB {

Game::Game(MutationOfJBEngine *vm)
: _vm(vm),
_randomSource("mutationofjb"),
_delayedLocalScript(nullptr),
_gui(*this, _vm->getScreen()),
_scriptExecCtx(*this),
@@ -60,6 +61,10 @@ Game::Game(MutationOfJBEngine *vm)
changeScene(13, false); // Initial scene.
}

Common::RandomSource &Game::getRandomSource() {
return _randomSource;
}

GameData &Game::getGameData() {
return *_gameData;
}
@@ -222,11 +227,11 @@ uint8 Game::colorFromString(const char *colorStr) {
return 0x00;
}

TaskManager& Game::getTaskManager() {
TaskManager &Game::getTaskManager() {
return _taskManager;
}

Assets& Game::getAssets() {
Assets &Game::getAssets() {
return _assets;
}

@@ -23,6 +23,7 @@
#ifndef MUTATIONOFJB_GAME_H
#define MUTATIONOFJB_GAME_H

#include "common/random.h"
#include "common/scummsys.h"
#include "mutationofjb/assets.h"
#include "mutationofjb/gui.h"
@@ -47,6 +48,7 @@ class Bitmap;
class Game {
public:
Game(MutationOfJBEngine *vm);
Common::RandomSource &getRandomSource();
GameData &getGameData();
Room &getRoom();
Script *getGlobalScript() const;
@@ -68,7 +70,7 @@ class Game {

static uint8 colorFromString(const char *colorStr);

TaskManager& getTaskManager();
TaskManager &getTaskManager();
Assets &getAssets();

Graphics::Screen &getScreen();
@@ -80,6 +82,7 @@ class Game {
Script *changeSceneLoadScript(uint8 sceneId, bool partB);

MutationOfJBEngine *_vm;
Common::RandomSource _randomSource;

GameData *_gameData;
Script *_globalScript;
@@ -21,6 +21,7 @@ MODULE_OBJS := \
commands/saycommand.o \
commands/seqcommand.o \
commands/talkcommand.o \
commands/randomcommand.o \
tasks/conversationtask.o \
tasks/saytask.o \
tasks/taskmanager.o \
@@ -45,6 +45,7 @@
#include "mutationofjb/commands/renamecommand.h"
#include "mutationofjb/commands/definestructcommand.h"
#include "mutationofjb/commands/talkcommand.h"
#include "mutationofjb/commands/randomcommand.h"
#include "mutationofjb/game.h"

namespace MutationOfJB {
@@ -71,6 +72,8 @@ static CommandParser **getParsers() {
new NewRoomCommandParser,
new GotoCommandParser,
new LabelCommandParser,
new RandomCommandParser,
new RandomBlockStartParser,
nullptr
};

@@ -81,7 +84,8 @@ static CommandParser **getParsers() {
ScriptParseContext::ScriptParseContext(Common::SeekableReadStream &stream) :
_stream(stream),
_currentCommand(nullptr),
_lastCommand(nullptr)
_lastCommand(nullptr),
_pendingRandomCommand(nullptr)
{}

bool ScriptParseContext::readLine(Common::String &line) {
@@ -43,6 +43,7 @@ class GameData;
class GotoCommand;
class ConditionalCommand;
class Script;
class RandomCommand;
typedef Common::Array<Command *> Commands;


@@ -92,6 +93,8 @@ class ScriptParseContext {
typedef Common::HashMap<Common::String, GotoCommands> PendingGotoMap;
PendingGotoMap _pendingGotos;

RandomCommand *_pendingRandomCommand;

ActionInfos _actionInfos;
Macros _macros;
Startups _startups;

0 comments on commit 3b614f0

Please sign in to comment.