From c3b7cc58f09b6eb9f7abce401ced4988d5c93e81 Mon Sep 17 00:00:00 2001 From: Dane Johnson Date: Sat, 1 Jan 2022 19:00:55 -0600 Subject: [PATCH] Some more c++ stuff, add possible lr grammar (glr?) --- spec.txt | 19 ++++++++++++ src/base/storybook.cpp | 70 ++++++++++++++++++++++++++++++++++++++---- src/base/storybook.h | 16 +++++++++- 3 files changed, 98 insertions(+), 7 deletions(-) diff --git a/spec.txt b/spec.txt index ee0abfc..2171e5d 100644 --- a/spec.txt +++ b/spec.txt @@ -38,6 +38,18 @@ BlankLine <- Spacing Newline Spacing <- (' ' / '\t')* Newline <- '\r\n' / '\r' / '\n' +Story language CFG: + +story : pages <> +pages : pages page | <> +page : ID FREETEXT footer +footer : "THE END" | "GOTO" ID | choices +choices : choices choice | choice +choice : INT ')' FREETEXT maybe-skillcheck redirect maybe-skillchange +redirect : '[' ID ']' +maybe-skillcheck : '<' SKILL INT op '>' | <> +maybe-skillchange: '(' op INT SKILL ') | <> + Work log: 12/13/21 @@ -77,3 +89,10 @@ of a bust. The project was very deep, very academic and hard to pick up, especia I'll just keep chugging with what I've got. Next up is integrating with Godot for real this time. For real. This time... + +1/1/22 + +I'm getting pretty frustrated with what I perceive to be bugs in the peg/leg parser. The project seems abandoned and +I don't really feel like maintaining it. And GNU Bison is like right there. If I can write a cfg for my little language +here I'll switch. I also can't shake the feeling that this is over-engineered, and I really don't need a parser for all this, but +oh well. I could probably do it all with just lex actually. Maybe I need to spend some time rethinking this. diff --git a/src/base/storybook.cpp b/src/base/storybook.cpp index 48e34cc..d096c15 100644 --- a/src/base/storybook.cpp +++ b/src/base/storybook.cpp @@ -8,7 +8,29 @@ Storybook::Storybook(FILE* fin) { pages = CyoaParse(fin); } -void Storybook::Find(const char* id) { +void Storybook::UpdateStat(const char *key, int rel) { + auto it = stats.find(key); + if (it == stats.end()) { + // Key not present + stats[key] = 0; + } else { + // Key present, add the rel + stats[key] = it->second + rel; + } +} + +int Storybook::LookupStat(const char *key) { + auto it = stats.find(key); + if (it == stats.end()){ + stats[key] = 0; + return 0; + } else { + return it->second; + } + return 0; +} + +void Storybook::Find(const char *id) { for (Page* page : pages) { if (strcmp(page->id, id) == 0) { current = page; @@ -19,6 +41,41 @@ void Storybook::Find(const char* id) { current = NULL; } +void Storybook::Advance() { + // TODO throw an exception if the ending type is choices + switch(current->footer.type) { + case FooterType::End: + IsEnded = true; + current = NULL; + return; + case FooterType::Goto: + Find(current->footer.link); + return; + } +} + +void Storybook::Advance(int choice_key) { + // TODO throw an exception if the ending type is not choices. + Choice* choice = (*current->footer.choices)[choice_key]; + if (!choice) { + // TODO throw exception? + } + + if (auto ck = choice->statcheck) { + int val = LookupStat(ck->stat); + if (ck->rel == STATCHECK_GT && val < ck->value || + ck->rel == STATCHECK_LT && val > ck->value) { + // TODO throw different exception? + } + } + + if (auto cg = choice->statchange) { + UpdateStat(cg->stat, cg->addend); + } + + Find(choice->id); +} + void print_choice(Choice* c) { printf("%d) %s", c->option, c->flavor); if (c->statcheck) { @@ -32,14 +89,15 @@ void print_choice(Choice* c) { void Storybook::Play() { printf(current->body); + Choice *choice; switch (current->footer.type) { case FooterType::End: printf("The End."); - IsEnded = true; + Advance(); break; case FooterType::Goto: - Find(current->footer.link); + Advance(); printf("Press ENTER to continue..."); std::cin.get(); break; @@ -48,9 +106,9 @@ void Storybook::Play() { print_choice(c.second); } printf("Make a selection: "); - int choice; - std::cin >> choice; - Find((*current->footer.choices)[choice]->id); + int choice_option; + std::cin >> choice_option; + Advance(choice_option); break; default: IsEnded = true; // TODO diff --git a/src/base/storybook.h b/src/base/storybook.h index 80bf5bc..6eb2cc0 100644 --- a/src/base/storybook.h +++ b/src/base/storybook.h @@ -2,18 +2,32 @@ #define STORYBOOK_H #include +#include +#include #include #include "cyoa.h" class Storybook { private: std::vector pages; + std::unordered_map stats; Page *current; public: Storybook(FILE* fin); + + // Functions for looking up and printing stats + void UpdateStat(const char*, int); + int LookupStat(const char*); + std::vector GetDefinedStats(); + + // Functions to change the game state void Find(const char*); - void Play(); + void Advance(); // For Goto and End cases + void Advance(int); // For Choices bool IsEnded = false; + + // This will probably be moved to the cli driver + void Play(); }; #endif /* STORYBOOK_H */