Skip to content

Commit

Permalink
Merge pull request #1742 from fmatthew5876/event_cond
Browse files Browse the repository at this point in the history
Refactor interpreter control flow
  • Loading branch information
Ghabry authored Sep 18, 2019
2 parents 0e05729 + 62e286b commit 4b1f949
Show file tree
Hide file tree
Showing 8 changed files with 356 additions and 183 deletions.
263 changes: 170 additions & 93 deletions src/game_interpreter.cpp

Large diffs are not rendered by default.

25 changes: 23 additions & 2 deletions src/game_interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class Game_Interpreter
void Push(Game_CommonEvent* ev);

void InputButton();
void SetupChoices(const std::vector<std::string>& choices);
void SetupChoices(const std::vector<std::string>& choices, int indent);

virtual bool ExecuteCommand();

Expand Down Expand Up @@ -107,6 +107,7 @@ class Game_Interpreter
protected:
static constexpr int loop_limit = 10000;
static constexpr int call_stack_limit = 1000;
static constexpr int subcommand_sentinel = 255;

static bool to_title;
static bool exit_game;
Expand Down Expand Up @@ -141,7 +142,17 @@ class Game_Interpreter
int OperateValue(int operation, int operand_type, int operand);
Game_Character* GetCharacter(int character_id) const;

bool SkipTo(int code, int code2 = -1, int min_indent = -1, int max_indent = -1, bool otherwise_end = false);
/**
* Skips to the next option in a chain of conditional commands.
* Works by skipping until we hit the end or the next command
* with com.indent <= indent.
* The <= protects against broken game code which terminates without
* a proper conditional.
*
* @param codes which codes to check.
* @param indent the indentation level to check
*/
void SkipToNextConditional(std::initializer_list<int> codes, int indent);
void SetContinuation(ContinuationFunction func);

/**
Expand All @@ -168,10 +179,14 @@ class Game_Interpreter
*/
void CheckGameOver();

bool CommandOptionGeneric(RPG::EventCommand const& com, int option_sub_idx, std::initializer_list<int> next);

bool CommandShowMessage(RPG::EventCommand const& com);
bool CommandMessageOptions(RPG::EventCommand const& com);
bool CommandChangeFaceGraphic(RPG::EventCommand const& com);
bool CommandShowChoices(RPG::EventCommand const& com);
bool CommandShowChoiceOption(RPG::EventCommand const& com);
bool CommandShowChoiceEnd(RPG::EventCommand const& com);
bool CommandInputNumber(RPG::EventCommand const& com);
bool CommandControlSwitches(RPG::EventCommand const& com);
bool CommandControlVariables(RPG::EventCommand const& com);
Expand Down Expand Up @@ -235,6 +250,8 @@ class Game_Interpreter
bool CommandChangeSaveAccess(RPG::EventCommand const& com);
bool CommandChangeMainMenuAccess(RPG::EventCommand const& com);
bool CommandConditionalBranch(RPG::EventCommand const& com);
bool CommandElseBranch(RPG::EventCommand const& com);
bool CommandEndBranch(RPG::EventCommand const& com);
bool CommandJumpToLabel(RPG::EventCommand const& com);
bool CommandBreakLoop(RPG::EventCommand const& com);
bool CommandEndLoop(RPG::EventCommand const& com);
Expand All @@ -257,6 +274,10 @@ class Game_Interpreter
const std::string DecodeString(std::vector<int32_t>::const_iterator& it);
RPG::MoveCommand DecodeMove(std::vector<int32_t>::const_iterator& it);

void SetSubcommandIndex(int indent, int idx);
uint8_t& ReserveSubcommandIndex(int indent);
int GetSubcommandIndex(int indent) const;

FileRequestBinding request_id;
enum class Keys {
eDown,
Expand Down
37 changes: 29 additions & 8 deletions src/game_interpreter_battle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
#include "spriteset_battle.h"
#include <cassert>

enum BranchBattleSubcommand {
eOptionBranchBattleElse = 1
};

Game_Interpreter_Battle::Game_Interpreter_Battle()
: Game_Interpreter(true) {}

Expand Down Expand Up @@ -70,9 +74,9 @@ bool Game_Interpreter_Battle::ExecuteCommand() {
case Cmd::ConditionalBranch_B:
return CommandConditionalBranchBattle(com);
case Cmd::ElseBranch_B:
return SkipTo(Cmd::EndBranch_B);
return CommandElseBranchBattle(com);
case Cmd::EndBranch_B:
return true;
return CommandEndBranchBattle(com);
default:
return Game_Interpreter::ExecuteCommand();
}
Expand Down Expand Up @@ -357,8 +361,10 @@ bool Game_Interpreter_Battle::CommandConditionalBranchBattle(RPG::EventCommand c

if (!actor) {
Output::Warning("ConditionalBranchBattle: Invalid actor ID %d", com.parameters[1]);
// Use Else branch
return SkipTo(Cmd::ElseBranch_B, Cmd::EndBranch_B);
// Use Else Branch
SetSubcommandIndex(com.indent, 1);
SkipToNextConditional({Cmd::ElseBranch_B, Cmd::EndBranch_B}, com.indent);
return true;
}

result = actor->CanAct();
Expand All @@ -381,16 +387,31 @@ bool Game_Interpreter_Battle::CommandConditionalBranchBattle(RPG::EventCommand c
if (!actor) {
Output::Warning("ConditionalBranchBattle: Invalid actor ID %d", com.parameters[1]);
// Use Else branch
return SkipTo(Cmd::ElseBranch_B, Cmd::EndBranch_B);
SetSubcommandIndex(com.indent, 1);
SkipToNextConditional({Cmd::ElseBranch_B, Cmd::EndBranch_B}, com.indent);
return true;
}

result = actor->GetLastBattleAction() == com.parameters[2];
break;
}
}

if (result)
return true;
int sub_idx = subcommand_sentinel;
if (!result) {
sub_idx = eOptionBranchBattleElse;
SkipToNextConditional({Cmd::ElseBranch_B, Cmd::EndBranch_B}, com.indent);
}

return SkipTo(Cmd::ElseBranch_B, Cmd::EndBranch_B);
SetSubcommandIndex(com.indent, sub_idx);
return true;
}

bool Game_Interpreter_Battle::CommandElseBranchBattle(RPG::EventCommand const& com) { //code 23310
return CommandOptionGeneric(com, eOptionBranchBattleElse, {Cmd::EndBranch_B});
}

bool Game_Interpreter_Battle::CommandEndBranchBattle(RPG::EventCommand const& com) { //code 23311
return true;
}

2 changes: 2 additions & 0 deletions src/game_interpreter_battle.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ class Game_Interpreter_Battle : public Game_Interpreter
bool CommandShowBattleAnimation(RPG::EventCommand const& com);
bool CommandTerminateBattle(RPG::EventCommand const& com);
bool CommandConditionalBranchBattle(RPG::EventCommand const& com);
bool CommandElseBranchBattle(RPG::EventCommand const& com);
bool CommandEndBranchBattle(RPG::EventCommand const& com);
};

#endif
Loading

0 comments on commit 4b1f949

Please sign in to comment.