Some more c++ stuff, add possible lr grammar (glr?)

This commit is contained in:
Dane Johnson 2022-01-01 19:00:55 -06:00
parent 6aba0d0227
commit c3b7cc58f0
3 changed files with 98 additions and 7 deletions

View File

@ -38,6 +38,18 @@ BlankLine <- Spacing Newline
Spacing <- (' ' / '\t')*
Newline <- '\r\n' / '\r' / '\n'
Story language CFG:
story : pages <<EOF>>
pages : pages page | <<EPSILON>>
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 '>' | <<EPSILON>>
maybe-skillchange: '(' op INT SKILL ') | <<EPSILON>>
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.

View File

@ -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

View File

@ -2,18 +2,32 @@
#define STORYBOOK_H
#include <vector>
#include <unordered_map>
#include <string>
#include <cstdio>
#include "cyoa.h"
class Storybook {
private:
std::vector<Page*> pages;
std::unordered_map<const char*, int> 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<std::string> 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 */