Writing stories
Story vs script mode, what dogs hear, pronouns, traits from an author angle, debugging.
Bark is a small esoteric language dressed up as short dog stories. It is meant to be ridiculous and fun, not practical or serious. You get assignments, branches, loops, stashes, piles, math, and tricks. That should also be enough for the usual "is this Turing complete?" thing that is apparently part of writing esoteric languages. At least, I think it does! Feel free to tell me I am wrong though. I did not deep dive into that topic, so it might as well not be true as well.
The idea: dogs hear blah name blah blah walk blah blah and only react to the words that they recognise. The rest gets ignored completely. Bark behaves the same. It ignores almost everything that is not a registered name, a keyword, or a value instead of throwing errors. You wrap real commands in filler if you want just so it reads nicer.
Story mode vs script mode
Two ways to write Bark programs.
| Story | Script (no filler) | Same meaning |
|---|---|---|
her cookie jar holds "biscuit", "stick" | cookie_jar holds "biscuit", "stick" | fill a stash |
she whimpers as she wants the first biscuit from her cookie jar | whimper first from cookie_jar | print first stash item |
her cookie jar is empty | cookie_jar empty | clear a stash |
her cookie jar drops first | cookie_jar drops first | remove front slot |
she woof how many toys she has | bark how many toys the labrador has | print toy count |
when she has 2 toys then she woofs "Ready." | when labrador has 2 toys then bark "Ready." | branch |
for each treat from her cookie jar then … | for each treat from cookie_jar then … | loop over stash |
the labrador shares with the golden retriever | labrador shares with golden_retriever | split toys |
the laundry basket holds "shirt", "sock" | laundry_basket holds "shirt", "sock" | fill a pile |
I bark what is on top of the laundry basket | bark top of laundry_basket | peek pile top |
Story: spaces instead of underscores (cookie jar), optional filler (the, as she wants, even stash or pile if you like more technical jargon). None of that changes behaviour.
Script: registry names with underscores, heard keywords only, no filler. Do not write cookie_jar stash. The name cookie_jar is already enough. Use empty to clear a stash (or synonyms like starving). Useful for tests and scratch files.
Full script anti-patterns: Input and edge cases.
What the dogs hear
| Heard | Not heard (filler/glue) |
|---|---|
| Breeds, objects, stashes, piles from the registry files | Basically everything else: is, has, my, the, a, items, stash, pile, etc. |
Keywords: when, bark, holds, shares, bury, … | No separate ignore list. If it is not heard, it is filler. |
| memory / journal (two program-wide variables) | |
| Strings, numbers, traits |
I have a labrador.
She is 2.
She has 2 toys.
Her name is "Bimba".
she woofs how many toys she has
That prints 2. Meaning comes from where words sit on the line (who, what field, what value), not from filler like is or has.
A single breed on a line still registers it:
labrador
I have a labrador.
She is 2. → age = 2
She has 2 toys. → toys = 2
He is 5 years old → age = 5
Her name is "Bimba". → name
my corgi is loud → loud trait
when she has 2 toys then … → branch (when must start the line)
Filler never triggers behaviour by itself.
Debugging: --strict warns on lines that did nothing. --quiet hides the banner when you care about clean stdout.
One line per statement (mostly)
Each line is usually one command. Dogs are simple creatures.
Exceptions:
- Multiline blocks after
when/while/for each/ tricks, closed withbury(orenough,goodnight, etc.) - One-liner branches like
when she has 1 toy then she woofs "Hi" otherwise she woofs "Nope"with nobury
So a block is a bunch of lines between then and bury, not a free-form paragraph.
List slots: first, second, last
These are heard keywords. They pick a stash slot.
They only do something useful in stash/pile context (drops first, first from cookie jar, etc.). On a random story line they are just words that happen to be heard.
Not heard globally: spelled-out numbers used as slots (one, two, twenty third). Those still work in stash lines via the parser, but stay filler elsewhere so they do not collide with normal prose.
Dog fields (nine stored, many story words)
When you mention a breed (labrador, I have a beagle), you are registering a dog. The breed name is the handle from breeds.txt. It is not one of the nine stored fields. There is no breed counter.
Each dog keeps nine values. Story words are aliases. The parser maps toys → items, treats → food, and so on.
| Stored field | Type | Story aliases (examples) |
|---|---|---|
food | number | treat, snacks, cookie, biscuit. she steals a treat |
items | number | toy, toys, walk, nap, friend, squirrel. She has 2 toys |
inventory | text | belongings, comma list (ball, stick) |
age | number | She is 2, labrador 5, years old |
name | text | name, nickname |
description | text | owner, collar, tag, family |
color | text | color, species, gender |
happy | yes/no | goodboy, happy, trained, etc. |
fed | yes/no | fed, groomed, washed |
Full field table and every alias: Dog fields.
Treats vs toys
Dogs track food and items separately.
- Food: treats, snacks, biscuits.
she steals a treatadds to food. - Items: toys, walks, naps, squirrels, friends.
She has 2 toysandshe finds a toytouch items.
Greedy-trait logic only cares about food in some cases. See Traits.
World objects (ball, bone, etc.)
Names in objects.txt are world counters, not dog fields.
ball 5
I bark ball
Separate from a dog's inventory (comma list of what they carry). See Registries.
Comparisons in conditions
Less-than: sniffs + less. Greater-than: has more than.
| You want | Write |
|---|---|
| loop while toys < 8 | while she sniffs less toys than 8 then |
| branch when toys > 2 | when she has more than 2 toys then |
Full grammar: Conditions.
Branches (when / if)
when is a real keyword, but only when it starts the line:
when she has 2 toys then she woofs "Ready." → branch
bark "They left when the jar was empty." → print only
The sun set when they reached the gate. → story-only (--strict warns)
Where when is | Effect |
|---|---|
| First word on the line | Branch |
After otherwise | Next branch: otherwise when she has 1 toy then … |
Inside "quotes" | Printed text |
| Anywhere else | Ignored for control flow |
Loops work the same: while, until, for each must lead the line. See Control flow.
Pronouns
| Word | Resolves to |
|---|---|
she / her | Last dog you spoke about as she/her |
he / him / his | Last dog as he/him/his |
it | Last stash, pile, or object |
they / them | Filler |
I have a labrador.
She is 2.
I have a beagle.
she passes a toy to the beagle → labrador gives, not beagle
Introducing another breed does not rebind she from the first dog. Full rules: Registering and pronouns.
Stash vs pile
Stash = ordered jar. Slots matter (first, second, last).
Story: her cookie jar holds "a", "b", "c", for each treat from her cookie jar then … bury
Script: cookie_jar holds "a", "b", "c", whimper first from cookie_jar, cookie_jar empty
Pile = stack (last in, first out).
Story: the laundry basket holds "a", I bark what is on top of the laundry basket
Script: laundry_basket holds "a", bark top of laundry_basket
Full grammar: Stashes and piles.
Synonyms
Learn one phrase, swap words when it sounds better.
| Idea | Start here | Also works |
|---|---|---|
| Equals | matches | has, is, are (assign) |
| Greater | growls louder than | bigger, more |
| End block | bury | enough, goodnight, done |
| Add toy | finds a toy | gets, fetches, collects |
| Add treat | feeds a treat | food verbs, not toy verbs |
| Lose toy | misplaces a toy | tosses, hides |
| Eat treat | gulps a treat | not toy verbs |
Shortcuts
| Line | Meaning |
|---|---|
the labrador shares with the beagle and husky | Split toys. Remainder stays with giver |
the labrador passes a toy to the beagle | One toy, one friend |
her cookie jar is empty | Clear stash |
bark bark bark | Paw print easter egg |
Traits (personality, not fields)
Traits are optional flags on a dog. Not part of the nine fields. They change interpreter behaviour.
Defaults in traits.json (60 breeds). You can set or clear in stories:
my corgi is loud
my beagle is greedy
my labrador is not greedy
| Trait | What it does |
|---|---|
loud | Dog speaks → UPPERCASE. Narrator bark "…" stays normal. |
greedy | After 3 feed/gulp/share actions in a row, lose 1 treat from food. Counter resets after penalty. |
lazy | wait sleeps twice as long. |
wet | whine / whimper output doubled. |
fetchy | Same print twice → proud fetch line on stdout, then prints again. |
chaser | Each loop tick adds +1 toy to items. Story word squirrels is the same field. |
playful | Dog speaks → characters reversed before formatting. Narrator unchanged. |
Mood (no trait required):
- Dog speaks (
she barks,labrador woofs "…"): 0 toys → lowercase output.loud→ uppercase. - Narrator (
bark "…",I bark "…"): prints as written.
Full runtime detail: Traits and Runtime semantics.
Comments
// scene note
# act two
Debugging checklist
bark --list-breedsandbark --list-objects- Typos get fuzzy hints (Did you mean cookie jar?)
- Errors are dog-themed and prefer dog themed over usefulness. Sorry, not sorry.
- Short branches can live on one line. Longer scenes use
bury - Compare with
tutorial.woofin the repo examples
Example to run
./bark examples/woof/tutorial.woof
./gradlew run --args="examples/woof/tutorial.woof"
tutorial.woof: Bimba at the park. Scratch work goes in examples/scratch/ (gitignored).
