138 lines
2.8 KiB
C++
138 lines
2.8 KiB
C++
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <iostream>
|
|
|
|
#include "storybook.h"
|
|
|
|
Storybook::Storybook() {
|
|
// TODO
|
|
}
|
|
|
|
Storybook::Storybook(FILE* fin) {
|
|
pages = CyoaParse(fin);
|
|
}
|
|
|
|
void Storybook::UpdateStat(const char *ckey, int rel) {
|
|
std::string key(ckey);
|
|
auto it = stats.find(key);
|
|
if (it == stats.end()) {
|
|
// Key not present
|
|
stats[key] = rel;
|
|
} else {
|
|
// Key present, add the rel
|
|
stats[key] = it->second + rel;
|
|
}
|
|
}
|
|
|
|
int Storybook::LookupStat(const char *ckey) {
|
|
std::string key(ckey);
|
|
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;
|
|
return;
|
|
}
|
|
}
|
|
// If not found
|
|
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_option) {
|
|
if (!IsChoiceAvailable(choice_option)) {
|
|
throw IllegalChoiceException();
|
|
}
|
|
|
|
Choice* choice = (*current->footer.choices)[choice_option];
|
|
|
|
if (statchange_t *cg = choice->statchange)
|
|
UpdateStat(cg->stat, cg->addend);
|
|
|
|
Find(choice->id);
|
|
}
|
|
|
|
bool Storybook::IsChoiceAvailable(int choice_option) {
|
|
Choice* choice = (*current->footer.choices)[choice_option];
|
|
if (!choice)
|
|
return false;
|
|
|
|
statcheck_t *ck = choice->statcheck;
|
|
if (ck) {
|
|
int val = LookupStat(ck->stat);
|
|
if (ck->rel == STATCHECK_GT && val < ck->value ||
|
|
ck->rel == STATCHECK_LT && val > ck->value)
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void Storybook::print_choice(Choice* c) {
|
|
if (!IsChoiceAvailable(c->option))
|
|
printf("\033[;31m"); // Red background
|
|
|
|
printf("%d) %s", c->option, c->flavor);
|
|
if (c->statchange) {
|
|
printf("(%s %+d)",
|
|
c->statchange->stat,
|
|
c->statchange->addend);
|
|
}
|
|
if (!IsChoiceAvailable(c->option))
|
|
printf("\033[;0m");
|
|
printf("\n");
|
|
}
|
|
|
|
void Storybook::Play() {
|
|
printf(current->body);
|
|
Choice *choice;
|
|
|
|
switch (current->footer.type) {
|
|
case FooterType::End:
|
|
printf("The End.");
|
|
Advance();
|
|
break;
|
|
case FooterType::Goto:
|
|
Advance();
|
|
printf("Press ENTER to continue...");
|
|
std::cin.get();
|
|
break;
|
|
case FooterType::Choices:
|
|
for (auto c : *current->footer.choices) {
|
|
print_choice(c.second);
|
|
}
|
|
printf("Make a selection: ");
|
|
int choice_option;
|
|
std::cin >> choice_option;
|
|
try {
|
|
Advance(choice_option);
|
|
} catch (IllegalChoiceException e) {
|
|
printf("You can't do that!\n\n");
|
|
}
|
|
break;
|
|
default:
|
|
IsEnded = true;
|
|
}
|
|
}
|