~nromdotcom/gemif

bd561acf925a784d92dbbad845e6f5debf1e014e — Norm MacLennan 11 months ago 0bc459d 0.1.1
Update on-site docs in static files
M pkg/gemserver/banners.go => pkg/gemserver/banners.go +1 -1
@@ 30,7 30,7 @@ func getRandomBanner() string {
▀▄▄▄▄▄▀▄▄▄▄▄▀▄▄▄▀▄▄▄▀▄▄▄▀▄▄▄▀▀▀
`,
		`
..|'''.|                     '||' '||''''|
..|'''.|                      '||' '||''''|
.|'     '    ....  .. .. ..    ||   ||  .  
||    .... .|...||  || || ||   ||   ||''|  
'|.    ||  ||       || || ||   ||   ||     

M pkg/gemserver/serverconfig.go => pkg/gemserver/serverconfig.go +1 -0
@@ 1,5 1,6 @@
package gemserver

// ServerConfig contains basic server config settings.
type ServerConfig struct {
	Domain   string
	Port     int64

D static/docs/api.gmi => static/docs/api.gmi +0 -8
@@ 1,8 0,0 @@
# GemIF Docs / API
=> /docs/ Back

So how does this work in the confines of the Gemini protocol?

Making a call to `/start` creates you a new instance of the game, serializes via protobuf it, and encodes it to base64. This is your `state token`. You are redirected to `/game/[state token]`.

`/game/[state token]` renders your current scene. A "speculative state" is calculated for each exit in the current scene and each exit link is rendered as a link to `/game/[speculative state token]`.

M static/docs/config.gmi => static/docs/config.gmi +91 -4
@@ 1,7 1,7 @@
# GemIF Docs / Config
=> /docs/ Back

GemIF is (currently, anyway) configured with a simple YAML file that describes the scenes/rooms and how they hook into each other.
GemIF stories are stored as a simple YAML file that describes the scenes/rooms and how they hook into each other.

```
rooms:


@@ 21,8 21,95 @@ rooms:
    THE END
```

This is a very simple configuration, but you can see how it can help you make very simple linear or branching narratives.
## .gemif files and gemifc
But YAML isn't very nice to write, so there's a (minorly) more friendly alternative in the form of `.gemif` files. `.gemif` files are a _slight_ improvement over YAML files. A story can be made up of an arbitrary number of `.gemif` files plus a `metadata.yml` files.

In future versions I intend to add in conditions as essentially tags attached to your gamestate that you can check when rendering descriptions or allowing exits.
The `metadata.yml` file contains basic information about a story.

I'm not certain I want it any more complicated with that, though.
\ No newline at end of file
```
---
id: my_story
name: My Story
description: The greatest story in the world!
author: Norm MacLennan
```

Then the `.gemif` files describe each room and exit. Each file can contain an arbitrary number of rooms. Room metadata and exits are written as YAML frontmatter, while room descriptions and template are just written as plaintext.

```
# my_story.gemif

---
room_id: the_beginning
room_name: The Beginning
exits:
- exit_description: This is boring, flip to the end
  destination_id: the_end
  exit_id: exit_a
---
This is the beginning of the story!

---
room_id: the_end
room_name: The End
---
And they lived happily ever after.

THE END
```

In this case, a single `.gemif` file contains both rooms, but they could have been put into separate files. When you're ready to test your story, you can use `gemifc` to compile your story to YAML and run it in `gemif`.

```
$ gemifc ./stories/src/my_story ./stories/compiled
Compiling story ./stories/src/my_story/ to ./stories/compiled/

Finished loading story:
  Name: My Story
  Author: Norm MacLennan
  Descriptions: The greatest story in the world!
  Number of Rooms: 2

Serializing and writing to disk...
Done!
```

Then `./stories/compiles/my_story.yml` will contain your compiled story.

## Advanced Storytelling with Conditions
GemIF stories can contain conditions. Little text tags attached to a user's gamestate to keep track of things.

These conditions can be used for conditional rendering and disallowing the use of certain actions.

```
# conditions.gemif

---
room_id: inside
room_name: Inside
exits:
- exit_id: find_key
  exit_description: Oh, there's the key!
  destination_id: inside
  set_condition: has_key
- exit_id: leave
  exit_description: Alright, let's get out of here.
  destination_id: outside
  if_condition: has_key
---
You are locked inside a room. Weird that the door locks from the outside, but it turns out it's a thing.

{{if .ConditionMet "has_key"}}
You've got the key in your hand.
{{else}}
Better find the key. It's probably around here somewhere.
{{end}}

---
room_id: outside
room_name: Outside
---
You made it outside. Now you can get on with your life.

THE END
```
\ No newline at end of file

M static/docs/index.gmi => static/docs/index.gmi +4 -3
@@ 5,6 5,7 @@ GemIF is a simple Interactive Fiction engine that runs as a Gemini server.

The goal is to allow users to create simple linear or branching text-based narratives via a YAML file and have it rendered as interactive fiction, served over Gemini.

=> /docs/why.gmi But why?
=> /docs/config.gmi Configuration spec
=> /docs/api.gmi What's the, uhm, API(?) look like?
\ No newline at end of file
Authors can write their stories either directly as YAML files. Or they can break their stories up into an arbitrary number of `.gemif` files then use the `gemifc` command to "compile" their story into a YAML file.

=> /docs/why.gmi Why GemIF?
=> /docs/config.gmi Writing Stories
\ No newline at end of file

M static/docs/why.gmi => static/docs/why.gmi +4 -4
@@ 5,8 5,8 @@ My reason for developing GemIF is very simple: I've always been fascinated by In

I spent a huge amount of time with MUDs and Z-Machine text-based adventure games back in the 90s and early 2000s.

=> https://en.wikipedia.org/wiki/MUD [http] Wikipedia - MUDs
=> https://en.wikipedia.org/wiki/Z-machine [http] Wikipedia - Z-Machine
=> https://en.wikipedia.org/wiki/MUD [https] Wikipedia - MUDs
=> https://en.wikipedia.org/wiki/Z-machine [https] Wikipedia - Z-Machine

The same way lots of people dream about writing novels, I've always dreamt about writing interactive fiction. I figure it sits halfway between two of my pipedreams: making a game and writing a novel.



@@ 14,8 14,8 @@ I spent a lot of time with Twine and it's awesome. It starts so simple, but can 

But I always got carried away with my ideas that I couldn't execute just a simple story without getting massively side-tracked.

=> https://twinery.org/ [http] Twine
=> https://itch.io/games/tag-twine [http] Twine games on Itch.io
=> https://twinery.org/ [https] Twine
=> https://itch.io/games/tag-twine [https] Twine games on Itch.io

I never did finish any Twine game to my satisfaction and they're all long-gone now.


M static/templates/index.gmi.tmpl => static/templates/index.gmi.tmpl +9 -3
@@ 3,9 3,9 @@ GemIF is a simple Interactive Fiction engine for Gemini (think: twine but with f

Each story below is represented as a (relatively-) simple YAML file describing the scenes and transitions.

Starting one of the stories puts you into a unique instance of the story, which doesn't mean much now but will once simple game state (for example conditional exits) have been added.
Stories allow users to make choices, moving from scene to scene. Simple logic can be added in the form of "condition" tags attached to the game state. Making choices can apply those transitions, which allow for conditional text rendering and conditionally allowing use of transitions later in the story.

If you want to run your own instance, check out the repo [4]. Once the binary is compiled, all you need are stories and TLS certificates.
If you want to run your own instance, check out the repo [4]. There are instructions in the README.

Wanna try it out?



@@ 15,4 15,10 @@ Wanna try it out?

Or learn more?
=> /docs/ Yeah, tell me more!
=> https://git.sr.ht/~nromdotcom/gemif [https] source at sr.ht
\ No newline at end of file
=> https://git.sr.ht/~nromdotcom/gemif [https] source at sr.ht

Want me to host your story for you?
=> /docs/config.gmi Learn to write stories
=> mailto:~nromdotcom/gemif@lists.sr.ht [mailto] Send it to the project mailing list

For anything else, feel free to email the project mailing list `~nromdotcom/gemif@lists.sr.ht` or me personally at `norm@iwritethe.codes`.
\ No newline at end of file

A stories/compiled/conditions.yml => stories/compiled/conditions.yml +34 -0
@@ 0,0 1,34 @@
metadata:
  id: conditions
  name: Conditions Demo
  description: A simple demo of using conditions
  author: Norm MacLennan
rooms:
- room_id: inside
  room_name: Inside
  room_description: |2+

    You are locked inside a room. Weird that the door locks from the outside, but it turns out it's a thing.

    {{if .ConditionMet "has_key"}}
    You've got the key in your hand.
    {{else}}
    Better find the key. It's probably around here somewhere.
    {{end}}

  exits:
  - exit_id: find_key
    exit_description: Oh, there's the key!
    destination_id: inside
    set_condition: has_key
  - exit_id: leave
    exit_description: Alright, let's get out of here.
    destination_id: outside
    if_condition: has_key
- room_id: outside
  room_name: Outside
  room_description: |2-

    You made it outside. Now you can get on with your life.

    THE END

A stories/src/conditions/conditions.gemif => stories/src/conditions/conditions.gemif +28 -0
@@ 0,0 1,28 @@
---
room_id: inside
room_name: Inside
exits:
- exit_id: find_key
  exit_description: Oh, there's the key!
  destination_id: inside
  set_condition: has_key
- exit_id: leave
  exit_description: Alright, let's get out of here.
  destination_id: outside
  if_condition: has_key
---
You are locked inside a room. Weird that the door locks from the outside, but it turns out it's a thing.

{{if .ConditionMet "has_key"}}
You've got the key in your hand.
{{else}}
Better find the key. It's probably around here somewhere.
{{end}}

---
room_id: outside
room_name: Outside
---
You made it outside. Now you can get on with your life.

THE END
\ No newline at end of file

A stories/src/conditions/metadata.yml => stories/src/conditions/metadata.yml +5 -0
@@ 0,0 1,5 @@
---
id: conditions
name: Conditions Demo
description: A simple demo of using conditions
author: Norm MacLennan
\ No newline at end of file