storybook/spec.txt

152 lines
9.4 KiB
Plaintext
Raw Normal View History

2021-12-17 13:54:05 -06:00
###################################
# Untitled Storybook Game Project #
###################################
This will be a project to create a system whereby "Choose Your Own Adventure" (CYOA) style stories can be easily written.
Each page will read out story elements, and then prompt the user to select a new page based on a decision
they would like to make.
Making certain choices will also award ad-hoc stat bonuses i.e. +1 Knowledge or something, all
stats are presumed to be 0 until points are awarded. This stat system also includes the ability
to make checks when certain choices become available, or once they are selected.
Requirements:
1. A language description and recognizer for creating CYOA-style stories.
2. An interpreter and interface for interacting with these stories.
3. Both story-writing and story-interaction tools need to be cross platform and relatively straightforwards for
a non technical user to operate.
Story language PEG: (with apologies, this is my first PEG)
Story <- BlankLine* Page+ EndOfFile
Page <- Header Body BlankLine*
Header <- Identifier Newline BlankLine*
Identifier <- [A-Z][A-Z0-9_]*
Body <- Footer / TextLine Body
TextLine <- (!Newline .)+ Newline
Footer <- Ending / Goto / Choice+
Goto <- 'GOTO' Spacing Identifier Newline
Ending <- 'THE END' Newline
Choice <- [0-9]+ ')' Spacing (!Redirect .)+ Redirect
Redirect <- StatCheck? Spacing '[' Identifier ']' Spacing StatChange? Newline
StatCheck <- '<' StatName Spacing [0-9]+ ('+' / '-')? '>'
StatChange <- '(' ('+' / '-') [0-9]+ Spacing StatName ')'
StatName <- [A-Za-z]+
EndOfFile <- !.
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>>
2021-12-17 13:54:05 -06:00
Work log:
12/13/21
Right now I need to make a decision before any of the work has started on how the user would interact with the system.
I think for a MVP it would be okay to just write a console application, but I think for the long term there needs to
be a decision made on how this will work. I'm leaning towards one of three options.
1) We put the whole thing on the JVM and make it a library or something.
Maybe in the future we can make a frontend for making and playing stories
as a web interface, but we could make the interface pluggable as far as the backend is concerned.
2) I build this non-traditional game in a traditional game engine (Godot probably). This ensures cross-platform
2022-01-24 11:24:04 -06:00
availability. I'm not 100% sure about my ability to use parsers in Godot, but this looks like a good option.
2021-12-17 13:54:05 -06:00
3) I build this as a reactive web page. I know this sounds like a terrible idea, but there are actually a lot
of cool image and text transition libraries out there. It does mean setting up something like React tho, which
like, just kill me now
Out of the three of these I think the Java thing would be the easiest and I think the Godot thing would be the best.
2021-12-26 15:55:03 -06:00
12/26/21
Merry Christmas! Forgot to update this for a bit, but let's talk turkey about what's been done so far. I decided to
2022-01-24 11:24:04 -06:00
implement this as a C++ project for portability. I know Java might have technically been more portable, but I'm
2021-12-26 15:55:03 -06:00
thinking Godot is in the near future for this and Javascript has something like a FFI so I went for a C project
called "peg/leg" (`man peg` weirdly...) to implement the language. I can't recommend the project, it is not copyleft
and although the "leg" tool provides a lex/yacc-like interface but it does a terrible job of documenting the peg semantic
actions, (like how the fuck the * operator works or how to properly use the predicates), and a lot of stuff is straight
up missing (%nterm, $1, yyin). I like PEGs, but if I could do this again I'd just use flex/bison.
Where to go from here? I could just start integrating this into a Godot project. Right now I'm making a little command
2022-01-24 11:24:04 -06:00
line driver to test it out. Portability? This project is gonna be small and I could just use submodules, or just little
2021-12-26 15:55:03 -06:00
subprojects in the same project for each interface (Web/Godot/Whatever else). At this point I've written so little code
that I think I could just port it to each project as well. For Godot I'm pretty sure I'll have to integrate it with
the SCons build that they provide on their website, so I probably can't link to a .so file.
2021-12-30 11:37:51 -06:00
12/30/21
2022-01-24 11:24:04 -06:00
I tried to migrate to a library "pegtl", which is pegs implemented using the C++ standard template library. It was a bit
2021-12-30 11:37:51 -06:00
of a bust. The project was very deep, very academic and hard to pick up, especially since I'm not really a C++ guy. Guess
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.
2022-01-02 17:50:40 -06:00
1/2/22
Okay I decided to just power through, and I finished the CLI version, which I'll be committing with this update. I did write a CFG
however I realized that since this isn't a programming language an LR parser isn't exactly right. I made the right choice with the
PEG, I just need better tooling. Anyway the immediate problem that I was having was that I assumed that semantic actions following
an optional term in leg would be run with a null pointer or not be run at all, but it turns out you need to wrap the semantic
action in the optional as well. Oh well lesson learned. Maybe some day I'll write my own.
Next up is definitely the Godot Native module. I've already read a bit about how to do it, but I know there will be a few hitches
here and there. Also I want to convert the base module to use entirely c++ semantics, with the exception of printf since I'm not
sure if there is a c++ parallel, which is a bit odd. C++ is weird, no wonder I've avoided using it until now. It seems like c++
2022-01-24 11:24:04 -06:00
developers spend a lot of time coming up with new ways to do things, then declaring them unidiomatic and banning them. I guess
2022-01-02 17:50:40 -06:00
that's kind of a trend with higher level languages as they get older cough Java cough. Regardless, I need to learn it and this
is as good of a project as any.
Also I still haven't mentioned to Pam I was doing this. Hope that's not a problem...
2022-01-02 19:40:14 -06:00
1/2/22 cont.
Okay I've got the skeleton of a Godot Native module there, but I'm realizing cross-platform builds are limited by the compiler I'm using for
the base module. I think I'll need to either compile from source for the Godot thing, or port the whole project over to the SConstruct build
system, which shouldn't be too hard considering the size of the project. Still, yet another thing I have to learn, not too happy about that.
1/11/22
Well I found a library that's got good promise, but there was a catch, it's a Rust module. Fortunately Rust is like the coolest darn
language I've ever seen. Guess I'm a Rust person now, ain't never gonna learn C++. Darn. Anyways I'm porting the whole library over
on the rust branch, getting the parser working was easy as pie. Rust (despite having closures and algebraic data types) can just
compile down to a static library so I'm going to do that instead of the peg/leg mess. If nothing else, finding this library and
Rust itself just made this whole project worth it.
2022-01-20 11:00:50 -06:00
1/20/22
Okay this project is taking a really long time. At this point it was really just an excuse to learn Rust but now it's finally time
to make this into a game! Up next is GODOT, it's that time now. Really got to take care of business. Rust stuff is done and somewhat
in, I've left the old library for now. Also the "rust-ffi-demo" should really just be the CLI program now, but it's missing the game
logic. I've decided the library won't handle that anyway, I'll try and make the library just read the stories and handle the pages.
2022-01-24 11:24:04 -06:00
1/24/22
So putting the whole project into a C-ABI compatible library was pretty exhausting but it's done now, and I was about half way
through translating that into a Godot Nativescript module when I found the Rust "gdnative" package. It just does almost
everything for you. On one hand I'm upset that I spent so much time on the C stuff but whatever. Rust apparently lets you
add submodules right into your project, so that's all done.
Do we want to call it a day? Nope. Here's a list of changes
1. Titles and authorship should be in the file. This means that a book is no longer a list of pages. Good thing I changed to
a more flexible peg parser.
2. Options with stat checks and changes should only happen the first time. That or ban circular stories altogether. (Let's hold off on this for now...)
3. Multiple stat check and change blocks per option should be permitted.
I should really show this to Pam soon, I just want to get one example working that isn't totally embarrassing.