diff --git a/game_engine.cpp b/game_engine.cpp index 3cc706f..16a296c 100644 --- a/game_engine.cpp +++ b/game_engine.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include "game_engine.hpp" @@ -51,6 +52,53 @@ Brainfucker::Brainfucker() { } +/* + * Just a jank way to use a counter to find + * the previous matching brace rather than + * using a stack. Should work for now. + */ +void Brainfucker::jump_forward() { + int counter = 1; + + for(++ip; // when counter hits 0 we found it + counter > 0 && ip < code.size(); + ++ip) + { + char op = code.at(ip); + if(op == '[') { + // new branch so increment + ++counter; + } else if(op == ']') { + // close branch so decrement + --counter; + } + } + + ++ip; // need to go 1 after +} + +/* + * Same jank style of using a counter to + * jump back. + */ +void Brainfucker::jump_backward() { + int counter = 1; + + for(--ip; // when counter hits 0 we found it + counter > 0 && ip > 0; + --ip) + { + char op = code.at(ip); + if(op == '[') { + // close branch so decrement + --counter; + } else if(op == ']') { + // new branch so increment + ++counter; + } + } +} + /* * Totally fragile but it seems to be working * enough to test the idea. @@ -67,17 +115,31 @@ void Brainfucker::run(int ticks) { --dp; break; case '+': - data[dp] = 1; + data[dp] = data[dp] + 1; break; case '-': - data[dp] = 0; + data[dp] = data[dp] - 1; break; case '.': - print("{}", data.at(dp)); + cout << (char)data.at(dp); break; case ',': print(ERROR, "Not implemented.\n"); break; + case '[': { + // [ - if 0 jump to after ] + if(data.at(dp) == 0) { + jump_forward(); + } + } + break; + case ']': { + // ] if not 0 jump to after [ + if(data.at(dp) != 0) { + jump_backward(); + } + } + break; default: print(ERROR, "Unknown operation {}\n", op); } diff --git a/game_engine.hpp b/game_engine.hpp index f9386f3..d33101f 100644 --- a/game_engine.hpp +++ b/game_engine.hpp @@ -18,6 +18,8 @@ class Brainfucker { void run(int count); void set_code(string &code); void reset(); + void jump_backward(); + void jump_forward(); }; class GameEngine { diff --git a/tests/game_engine.cpp b/tests/game_engine.cpp index e39f786..76480e0 100644 --- a/tests/game_engine.cpp +++ b/tests/game_engine.cpp @@ -1,7 +1,7 @@ #include #include "../game_engine.hpp" -TEST_CASE("brainfuck test", "[brainfuck]") { +TEST_CASE("basic brainfuck test", "[brainfuck]") { Brainfucker bf; string code{"+.>+.>+.>"}; @@ -23,6 +23,16 @@ TEST_CASE("brainfuck test", "[brainfuck]") { REQUIRE(bf.code.empty()); } + +TEST_CASE("brainfuck loop test", "[brainfuck]") { + Brainfucker bf; + // this is a hello world program from wikipedia + string code{"++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."}; + + bf.set_code(code); + bf.run(code.size()); +} + TEST_CASE("game engine can start and take hit", "[brainfuck]") { // test fails on purpose right now GameEngine game{4};