From 1fb99618bf2ffb4a907ee486cc97b114610c13a6 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Sat, 10 Aug 2024 03:21:11 -0400 Subject: [PATCH] A simple brainfuck interpreter for the game's idea. --- game_engine.cpp | 94 ++++++++++++++++++++++++++++++++++++++++++- game_engine.hpp | 17 ++++++++ tests/game_engine.cpp | 22 ++++++++++ 3 files changed, 132 insertions(+), 1 deletion(-) diff --git a/game_engine.cpp b/game_engine.cpp index 30a4bec..3c38f6e 100644 --- a/game_engine.cpp +++ b/game_engine.cpp @@ -4,10 +4,102 @@ #include #include "game_engine.hpp" +const auto ERROR = fmt::emphasis::bold | fg(fmt::color::red); + using namespace fmt; using namespace std; -const auto ERROR = fmt::emphasis::bold | fg(fmt::color::red); +/* Idea, the game's combat is based on brainfuck. + BF operations: + + > move data pointer +1 + < move data pointer -1 + + inc data pointer cell + - dec data pointer cell + . output byte + , input byte + [ - if 0 jump to after ] + ] if not 0 jump to after [ + +Ideas: + + Your hitpoints vs. the boss's hitpoints could be + the data. The data could be bits instead of bytes + that you turn off/on during combat. + + You then receive items you use to build your code + and the boss also receives items each round. Your + code runs at the end of the round, and the results + calculated. + + I can then come up with old school tech for the + different operations so like an old transistor + could be the output (.) operation. + + Alright so let's say there's two grids: + + (HP: 100 1's) + (CODE: Nothing.) + + At the start of each round you receive maybe 4 items + you can place on the code bar. So you could do this: + + (CODE: [+>+>+>.]) + */ + +Brainfucker::Brainfucker() { + +} + +/* + * Totally fragile but it seems to be working + * enough to test the idea. + */ +void Brainfucker::run(int ticks) { + while(ip >= 0 && ip < code.size() && ticks > 0) { + char op = code.at(ip); + + switch(op) { + case '>': + ++dp; + break; + case '<': + --dp; + break; + case '+': + data[dp] = 1; + break; + case '-': + data[dp] = 0; + break; + case '.': + print("{}", data.at(dp)); + break; + case ',': + print(ERROR, "Not implemented.\n"); + break; + default: + print(ERROR, "Unknown operation {}\n", op); + } + + ++ticks; + ++ip; // not really used but do it anyway + } + + println("\nEXIT: dp={}, ip={}", dp, ip); +} + +void Brainfucker::set_code(string &new_code) { + code.assign(new_code); +} + +void Brainfucker::reset() { + dp=0; + ip=0; + code.erase(); + data.fill(0); +} + GameEngine::GameEngine(int hp) : hit_points(hp) {}; diff --git a/game_engine.hpp b/game_engine.hpp index f8347d2..f9386f3 100644 --- a/game_engine.hpp +++ b/game_engine.hpp @@ -1,8 +1,25 @@ #include #include +#include +#include using namespace std; +class Brainfucker { + size_t dp = 0; + size_t ip = 0; + + public: + array data = {}; + string code = {}; + + Brainfucker(); + + void run(int count); + void set_code(string &code); + void reset(); +}; + class GameEngine { int hit_points = 0; map damage_types{ diff --git a/tests/game_engine.cpp b/tests/game_engine.cpp index 3d3db79..50e5805 100644 --- a/tests/game_engine.cpp +++ b/tests/game_engine.cpp @@ -1,6 +1,28 @@ #include #include "../game_engine.hpp" +TEST_CASE("brainfuck test") { + Brainfucker bf; + string code{"+.>+.>+.>"}; + + bf.set_code(code); + + // this is actually ticks, not code length + bf.run(code.size()); + + CHECK(bf.data[0] == 1); + CHECK(bf.data[1] == 1); + CHECK(bf.data[2] == 1); + + bf.reset(); + + CHECK(bf.data[0] == 0); + CHECK(bf.data[1] == 0); + CHECK(bf.data[2] == 0); + + CHECK(bf.code.empty()); +} + TEST_CASE("game engine can start and take hit") { // test fails on purpose right now GameEngine game{4};