Skip to content

Instantly share code, notes, and snippets.

@zarutian
Last active June 28, 2023 00:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zarutian/ec15de4eb4780ae6e6c8f7ad1d2d49f6 to your computer and use it in GitHub Desktop.
Save zarutian/ec15de4eb4780ae6e6c8f7ad1d2d49f6 to your computer and use it in GitHub Desktop.
A bit of a fiddling on an idea I had.
// ink interactive narrative syntax&semantics
/*
https://github.com/y-lohse/inkjs
https://github.com/inkle/ink/blob/master/Documentation/WritingWithInk.md
*/
EXTERNAL urlfetch(url)
EXTERNAL urlpost(url, payload)
EXTERNAL json_subscript(jsonstr, path)
EXTERNAL json_set_subscript(jsonstr, path, value)
EXTERNAL json_array_length(jsonstr)
EXTERNAL str_concat(strA, strB)
EXTERNAL parseInt(str)
EXTERNAL query(prompt, default)
EXTERNAL italics_on()
EXTERNAL italics_off()
EXTERNAL bold_on()
EXTERNAL bold_off()
EXTERNAL underline_on()
EXTERNAL underline_off()
EXTERNAL strikethrough_on()
EXTERNAL strikethrough_off()
EXTERNAL ahref_on(destination_url)
EXTERNAL ahref_off()
EXTERNAL print_delay(milliseconds)
VAR textStylingFallbackOption = "html"
VAR lastQuery = ""
VAR visitor_info = ""
VAR visitor_counter = 0
VAR visitor_since_last = 0
VAR visitor_moniker = "Anonymous Rando"
VAR visitor_info_url = ""
VAR page_nr = 0
VAR max_page_nr = 0
VAR story_version = 198
// off by one
~ visitor_info_url = str_concat("https:/", "/zarutian-ocaps_ink_visitors.express.val.run/")
~ story_version = story_version + 1
// ~ visitor_info = urlfetch(visitor_info_url)
~ visitor_counter = parseInt(json_subscript(visitor_info, "counter"))
~ visitor_since_last = parseInt(json_subscript(visitor_info, "since_last"))
v{story_version}
-> very_start
=== very_start ===
/*
Hér er hellingur af texta til að
sjá hvort skrunun virkar eða gerir það ekki.
Hafið eigi áhyggjur ef þér skiljið eigi
hvar hér stendur því að það skiftir ekki það
miklu máli.
Það var ekki vandamálið.
*/
You find yourself in a dark tunnel. There is light ahead.
* [ Go towards the light ]
You walk towards the light.
-> enter_chamber
* [ Stay in the darkness. ]
What, you like the dark?
To each of their own I suppose.
Farewell!
-> END
=== enter_chamber ===
You exit the tunnel into a rather spartan but cozy chamber.
As your eyes grow accustomed to the light you see a man at a desk in front of you.
He is hunched over documents and books, clearly writing as he hunts to and fro.
It is peckuliar that he is writing with a quill on parchment yet being clad in a sweat suit.
-> choices
= choices
* [ Clear your throat to indicate your presence. ]
{~ -> softly_clear_throat | -> drama_clear_throat }
* [ Try to read the parchment he is writing on. ]
Well, that is a rather rude thing to do you know?
-> choices
+ [ Wait stolidly. ]
{~|You just stand there{~| like {~an artifact|something} badly manifactured}.}
{~||||The {~||||occasational} {~scribbl|scratch}ing of the quill is audiable.}
{~||||||The man shifts a document out from underneath the pile.}
{(TURNS_SINCE(-> enter_chamber) == 50): Wow, you are rather patient one are you not? }
{(TURNS_SINCE(-> enter_chamber) > 90): The man finally looks up. -> oh_a_visitor }
-> choices
* {TURNS_SINCE(-> enter_chamber) > 10} [Scratch an itch]
Yeah, that feels a bit nice, does it not?
-> choices
= softly_clear_throat
You clear your throat softly.
The man looks up a bit puzzled.
-> oh_a_visitor
= drama_clear_throat_ending
You are unable to draw another breath, and regretfully expire.
Well, that is that then.
Lets start again then.
-> very_start
= drama_clear_throat
You clear your throat a bit too dramatically and nearly choke on your own spittle.
The man looks at you alarmed, stands up, hurries around the desk and thwacks you on your back repeatily.
{~ -> drama_clear_throat_ending | -> drama_clear_throat_saved }
= drama_clear_throat_saved
You barely manage to draw another breath, but soon you are able to breath somewhat normally again.
The man says "You alright?"
* You {~nod your head.|answer {~in the affirmitive|"Yes."}}
* You just heave air for a minute.
- "Would you like some water?"
*\ {~"Yes, please."|"If you could be so kind."}
He goes to a side table, poors a glass of water.
Turns around and hands you the glass.
You cautusly take a sip.
*\ {~"No, but thank you."|"I do not think so but thank you all the same."}
- The man takes his seat again.
-> oh_a_visitor.s1
=== oh_a_visitor ===
"Oh! A visitor!" the man says.
"Number {print_num(visitor_counter)} to be precise!"
"It is only been {print_duration(visitor_since_last)} since last one."
-> s1
= s1
"Welcome to my humble chamber."
-> s2
= s2
"Please, have a seat {~.|, make yourself {~at home.|comfy.}}"
You sit on a chair in front of the desk.
-> s3
= s3
"I take you have some questions."
-> choices
= choices
* "Yes, what is this place?" -> s4
* "No[."], I am quite content in my ignorance."
"You sure you have no questions?" the man asks incredusly.
* * "Now you mention it, I do have a question."
"Oh, what could it be?"
* * * "Yeah, what is this place?" -> s4
* * * "Do wild pet rocks exist?"
"I suppose so but you will have to ask a geologist, mineralist, or crystalhealer"
-> choices
TODO: add another flippant question.
* * "Naah, I am fine."
"Then why are you here?"
* * * "To be honest, I do not know."
"Then who does?" {spokesman_named: Carl | the man} asks a bit bewildered.
-> choices
* * * "Just wanted to check out the ambience."
"Well," {spokesman_named: Carl | the man} says looking around "it is rather spartan but still quite homey place."
-> choices
TODO: flesh this out some more
* You stare at the man.
Feeling ackward, he hesently starts.
-> s4
= s4
"This place is a fictional construct that exists in an interactive narrative.
This interactive narrative is written to {~educate|inform|iluminate} folks that are
curious about a branch of computer science called object capabilities."
-> s4_choices
= s4_choices
* "Interactive narrative?" -> s5
* "Computer science?" -> s6
* "Object capabilities?" -> ocaps_explained(-> s4)
* "Who wrote this narrative?" -> author_named
+ {CHOICE_COUNT() <= 2} "I think that is all the questions I have." -> bidding_bye
* {CHOICE_COUNT() <= 3} "And who are you?" -> s10
- -> s4_choices
= s5
"{~Yeah, i|I}t is a kind of a computerized version of a Choose Your Own Adventure book.
The foremost makers of interactive narratives are the folks at Inkle Studios.
Folks that by the way wrote and open sourced a kind of scripting language called Ink in which this interactive narrative is incidently authored in."
-> s5_choices
= s5_choices
* "Choose Your Own Adventure books?"
"A book where you start at the first paragraph on the first page.
The paragraph gives some colour. Then following it are a few choices
on where to continue reading depending on what you want to proceed.
Usually each choice directs you to a page and paragraph on that page.
The paragraphs are usually numbered."
-> s5_choices
* "Ink?"
"A sort of scripting language to write interactive narratives in.
In is a tiny bit similiar in spirit to HyperCard in the sense it is
mostly data/text/content but with logic interspersed through out."
-> s5_choices
* "Inkle Studios?"
"An independent game producing company in the UK.
The made games such as Sorcery, 80 days, Overboard, and not least Heavens Vault.
Their website is at {ahref_on(str_concat("https:/", "/inklestudios.com/"))}inklestudios.com{ahref_off()}.
Rather clever bunch."
-> s5_choices
+ {CHOICE_COUNT() <= 0} ...[] -> s4_choices
- -> s4_choices
= s6
"Computer science is a branch of engineering and academia whose origins lie both
in applied mathematics and electronics engineering."
-> s4_choices
= s10
The man looks up and scratches his chin before answering.
"Just a fictional man that the author ginnied up to act as his spokesperson in this interactive narrative."
-> s10_choices
= s10_choices
* "Do you have a name?" -> spokesman_named
* "Why the sweat suit?"
"Well it is comfy."
-> s10_choices
* "Do you feel lonely here?"
"No, because I have my research materials and from time to time someone curious comes a long to chat. You know, like you."
-> s10_choices
+ {CHOICE_COUNT() <= 1} ...[]
"Alright," says the man, "we shall continue."
-> s4_choices
=== ocaps_explained(-> done_here) ===
"Object capabilities, or ocaps for short, is a paradigm of access control in computer systems."
-> choices(done_here)
= choices(-> done_here)
* "paradigm?"
"A methodology on how to aproach designing or studying things."
-> choices(done_here)
+ "access control?"
"Basically who or what can access or directly affect something specfic."
* * "Can you give me an example?" []you ask.
"Sure, " {spokesman_named: Carl | the man} says.
"Say you have an text file with a recipie you are trying to improve."
"Go on."
"And you want your friend to be able to read it whenever but not change the file."
"Sounds reasonable. Oh, I see, I want to control their access to the file somehow! I get it."
-> choices(done_here)
* * "Like Access Control Lists?" []you enquire.
"Serves similiar function yes but is more flexible than ACLs."
TODO: perhaps link to Tyler Close paper ACLs dont ?
-> choices(done_here)
* "computer system?"
"You know, a device like this interactive narrative is running on.
Unless you are keeping track on paper, in that case well done."
-> choices(done_here)
* "why the shortening[?"] to ocaps?"
"Easier to say when object capabilities are being discussed." {spokesman_named: Carl|the man} answers.
-> choices(done_here)
+ "can you tell me more about these ocaps?" []you ask, intregued.
"Sure, but there are various similies I could use.
Which one would you like?"
* * UNIX file descriptors.
-> ocaps_file_descriptors_example(done_here)
* * Object references in memory safe programming languages, like EcmaScript or Java.
* * Secret bearing URLs, like those sharing a Google Doc. -> ocaps_url_examples(done_here)
TODO: mention KeyKOS and ilk?
-> choices(done_here)
=== ocaps_passing(-> done_here) ===
How an object (or an actor) comes to have an ocap to another object is only via
these three ways:
1. being endowed with it at {~construction|birth|creation}.
2. constructing the object the ocap will be to and getting that ocap.
3. getting it passed as an argument in an invocation (or as a return value from such it made)
-> done_here
=== ocap_definition ===
An ocap is an unforgable token giving access to, in spefic ways, and designating a spefic thing.
That is, you use the ocap to an object in an invocation as the target.
You also use other ocaps to other objects iff you are passing access to them along to that invoked object.
TODO: work in 'do not seperate designation and permission'. 1st attempt.
=== cert_style_ocapssystem (-> done_here)
* ActiveCapCerts -> ActiveCapCerts (done_here)
* SPKI -> SPKI (done_here)
* The one in the Zebra Copy paper using SAML
// * UCAN
// * Bisquit
// * Macaroons
-> done_here
=== ActiveCapCerts (-> done_here) ===
TODO: add a link to certcheque.js or anyother newer implementation.
TODO: add a link to Nikita's paper
TODO: add an choice-link to E's thirdparty handoff table mechanism explanation.
TODO: ditto, seqBlock
ActiveCapCerts is something that {author_named:Zarutian} the author of this interactive narrative has been working on, on and of, for a long while now.
// * CapCert
// * SPKI
-> done_here
=== SPKI (-> done_here) ===
{ahref_on(str_concat("https:/", "/theworld.com/~cme/html/spki.html"))}SPKI{ahref_off()} stands for Simple Public Key Infrastructure and is pronounced "spooky".
-> done_here
=== ocaps_url_examples (-> done_here ) ===
~ temp prefix = str_concat("https:/", "/www.w3.org/TR/capability-urls/")
The {ahref_on(prefix)}capability URL{ahref_off()} pattern is reasonably common:
{ahref_on(str_concat(prefix, "\#examples"))}Example Capability URLs{ahref_off()}:
{ahref_on(str_concat(prefix, "\#password-resets"))}2.1 Password Resets{ahref_off()}
{ahref_on(str_concat(prefix, "\#second-life"))}2.2 Second Life{ahref_off()}
{ahref_on(str_concat(prefix, "\#google-calendar"))}2.3 Google Calendar{ahref_off()}
{ahref_on(str_concat(prefix, "\#github-gists"))}2.4 Github Gists{ahref_off()}
{ahref_on(str_concat(prefix, "\#doodle-polls"))}2.5 Doodle polls{ahref_off()}
{ahref_on(str_concat(prefix, "\#flickr-images"))}2.6 Flickr images{ahref_off()}
-> done_here
=== ocaps_file_descriptors_example(-> done_here) ===
"You know how each proccess, in a UNIX/POSIX/Linux/BSD system, can open files,
sockets, and have stdin, stdout, and stderr?"
* "Yes, do go on."
"The <>
-> s1(done_here)
* "No["], but that is fascinating. How does it work?"
"Via <>
-> s1(done_here)
= s1(-> done_here)
<>system calls into the kernel that setup in kernel memory
a datastructure associated with the process doing the system call
that keep track of which files or such are open, where in the buffered
bytestream the process has consumed or produced so far and so on."
MERKILL
-> done_here
TODO: flesh it out more
=== bidding_bye ===
"Then on behalf of {author_named: Zarutian} the author of this interactive narrative I thank you for your time and hope I quenched your {~curiousity|thirst for knowledge} on the topic of object capabilities somewhat."
{spokesman_named: Carl|The man} bows his head and the scene fades to black.
~ add_visitor_to_guestbook()
-> END
=== spokesman_named ===
"Yes, you can call me Carl."
{author_named: Zarutian|Author} here, the spokesman is named after late Carl Hewitt, who we in the ocap community dearly miss and will be remembered by.
"And may ask what I should call you?"
* "No, I prefer to remain nameless."
"That is perfectly alright!"
-> oh_a_visitor.s10_choices
* "Yes, {~call me|I go by}..." -> visitor_named(-> oh_a_visitor.s10_choices)
-> oh_a_visitor.s10_choices
=== author_named ===
"A person that calls himself Zarutian on the wide 'net.
He wanted to try out writing an {~educational|informative|illuminating} interactive narrative on the topic of object capabilities."
-> choices
= choices
* "That is an unusual moniker."
"Chosen by him to be globally unique and it looked kewl way back when."
* * "When?"
"You know, back {~when {~the devil was in the cradle|landlines were the rage|{~mobies|mobile phones} had physical keypads|trilobites were still relatively new thamg.}|before Twitter, Tiktok, Myface, and Instapix existed}."
-> choices
* * "Really?"
"Yes, really."
-> choices
* "Where can I contact him."
"He frequents the IRC channels \#spritely and \#erights on libera.chat and
occasationally checks the cap-talk mailing list.
You might also reach him via email but with a g."
// how is that for an obscure clue, eh?
-> choices
* "Why write an interactive narrative?"
"Why not?" countered {spokesman_named: Carl|the man}.
"Besides it is a good excercise in writing as I am written to tell."
-> choices
+ {CHOICE_COUNT() <= 0} ... -> oh_a_visitor.s4_choices
=== visitor_named(-> done_here) ===
-> do_it_again(done_here)
= do_it_again(-> done_here)
~ visitor_moniker = query("your moniker", visitor_moniker)
"So you go by {visitor_moniker}, correct?"
+ "Yes, that is correct."
"Nice to meet you, {visitor_moniker}."
-> done_here
+ "No, I think you misheard me[.]. {~I go by|Call me}..." -> do_it_again(done_here)
=== function add_visitor_to_guestbook() ===
~ temp visitor_dat = "\{\}"
~ visitor_dat = json_set_subscript(visitor_dat, "moniker", visitor_moniker)
~ visitor_dat = json_set_subscript(visitor_dat, "turns", TURNS())
~ visitor_dat = json_set_subscript(visitor_dat, "story_version", story_version)
~ urlpost(visitor_info_url, visitor_dat)
=== peruse_the_guestbook(-> done_here) ===
~ page_nr = 1
~ max_page_nr = json_array_length(json_subscript(visitor_info, "guestbook")) / 10
You open the guest book.
-> look_at_page(done_here)
= look_at_page(-> done_here)
Page number {print_num(page_nr)}.
{print_guestbookentry(page_nr + 0)}
{print_guestbookentry(page_nr + 1)}
{print_guestbookentry(page_nr + 2)}
{print_guestbookentry(page_nr + 3)}
{print_guestbookentry(page_nr + 4)}
{print_guestbookentry(page_nr + 5)}
{print_guestbookentry(page_nr + 6)}
{print_guestbookentry(page_nr + 7)}
{print_guestbookentry(page_nr + 8)}
{print_guestbookentry(page_nr + 9)}
+ [Close the guestbook.]You close the guestbook.
-> done_here
+ {page_nr > 1} [Turn to the previous page.]
You turn the page back.
~ page_nr = page_nr - 1
-> look_at_page(done_here)
+ {page_nr < max_page_nr} [Turn to the next page.]
You turn the page.
~ page_nr = page_nr + 1
-> look_at_page(done_here)
+ [Turn to page number...]
~ page_nr = query("Page number", page_nr)
You turn to page number {print_num(page_nr)}.
-> look_at_page(done_here)
=== function print_guestbookentry(nr) ===
~ temp guestbook = json_subscript(visitor_info, "guestbook")
~ temp entry = json_subscript(guestbook, nr)
Visitor number {print_num(json_subscript(entry, "nr"))} was {json_subscript(entry, "moniker")}.
// That visitor
=== function gnome_jargon_gen (sel) ===
// CM4 - Earthshaker! gnome jargon generator
// Whenever a player character asks a gnome what he is doing or
// how something works.
// source: https://imgur.io/gallery/a5leij9
// codepen: https://codepen.io/jtsouth/pen/eYjgYBP
{ sel:
- 1: "Well, this {gnome_jargon_gen_l1()} connects to the {gnome_jargon_gen_l1()}, by which I {gnome_jargon_gen_l2()} the {gnome_jargon_gen_l3()} before it gets to the {gnome_jargon_gen_l1()}."
- 2: "I {gnome_jargon_gen_l2()} this {gnome_jargon_gen_l1()} so that when we {gnome_jargon_gen_l4()} the {gnome_jargon_gen_l1()} will stay within proper limits."
- 3: "Each time he {gnome_jargon_gen_l2()} the {gnome_jargon_gen_l1()}, I {gnome_jargon_gen_l2()} the {gnome_jargon_gen_l1()} so that the {gnome_jargon_gen_l1()} will {gnome_jargon_gen_l2()} the {gnome_jargon_gen_l3()} when we {gnome_jargon_gen_l4()}."
}
=== function gnome_jargon_gen_l1 () ===
<>{~valve|pressure feed|furnace|piston|coolant line|governor|gearbox|cable|take-up drum|safety valve|intake fan|bellows|pump|bleeder|drain port}<>
=== function gnome_jargon_gen_l2 () ===
<>{~regulate|watch|open|close|balance|cut-in|override|haul up|shut off|adjust|increase|pump|prime|pump}<>
=== function gnome_jargon_gen_l3 () ===
<>{~{~water|steam} pressure|temperature|gear ratios|torque speed|coolant|forward impetus|energy constant|airflow|kinetic thrust|internal tension|density}<>
=== function gnome_jargon_gen_l4 () ===
<>{~bend|take a step|reach|stop|twist|speak|move a finger|kneel|nod|run|raise an arm}<>
=== epicurean_paradox (-> done_here) ===
// Taken from https://9gag.com/gag/aegyj8O and translated to Ink.
Epicurio (341 a.C. — 271 a.C), a greek philosopher put forth this paradox:
-> s0(done_here)
= s0(-> done_here)
Evil Exists
+ Yes -> s1(done_here)
+ No -> done_here
= s1(-> done_here)
Can God Prevent Evil?
+ Yes -> s2(done_here)
+ No -> s7(done_here)
= s2(-> done_here)
Does God know about all the Evil?
+ Yes -> s3(done_here)
+ No []
Then God is not all knowing.
-> done_here
= s3(-> done_here)
Does God want to prevent Evil?
+ Yes -> s4(done_here)
+ No []
Then God is not {~good|loving}.
-> done_here
= s4(-> done_here)
Then why is there Evil?
+ To test us [] -> s5(done_here)
+ Satan []
An all-powerfull, all-knowing, all-good God could and would destroy Satan.
-> done_here
+ It is necessary for the universe to exists -> s6(done_here)
+ Other reason -> s6(done_here)
= s5(-> done_here)
If God is all knowing, he would know what we would do if we were tested,
therefore no need to test us.
-> done_here
= s6(-> done_here)
Could God have created a universe without these?
+ Yes -> s8(done_here)
+ No -> s7(done_here)
+ No, because of free-will -> s9(done_here)
= s7(-> done_here)
Then God is not all powerful.
-> done_here
= s8(-> done_here)
Then why didnt he?
+ To test us -> s5(done_here)
+ because of free-will -> s9(done_here)
= s9(-> done_here)
Could God have created a universe with free-will but without evil?
+ Yes -> s8(done_here)
+ No -> s10(done_here)
= s10(-> done_here)
Why not?
\— Because if there is no way to actually choose to be evil and the universe/world
to bear the consequences of that then choosing to be good is pretty meaningless.
And we might as well be like clockwork automatons.
But then God is not powerfull.
\- I suppose so. But that is a choice he made precisely to give us the choice to be able to be evil.
-> done_here
=== function print_duration(milliseconds) ===
~ temp MILLISECOND = 1
~ temp SECOND = 1000 * MILLISECOND
~ temp MINUTE = 60 * SECOND
~ temp FIVE_MINUTES = 5 * MINUTE
~ temp QUARTER_OF_HOUR = 3 * FIVE_MINUTES
~ temp HALF_HOUR = 2 * QUARTER_OF_HOUR
~ temp HOUR = 2 * HALF_HOUR
~ temp EIGHTH_OF_DAY = 3 * HOUR
~ temp QUARTER_OF_DAY = 2 * EIGHTH_OF_DAY
~ temp HALF_DAY = 2 * QUARTER_OF_DAY
~ temp TRIQUART_OF_DAY = 3 * QUARTER_OF_DAY
~ temp DAY = 2 * HALF_DAY
~ temp WEEK = 7 * DAY
~ temp FORTHNIGHT = 2 * WEEK
~ temp MONTH = 2 * FORTHNIGHT
~ temp YEAR = 365 * DAY
~ temp DECADE = 10 * YEAR
~ temp CENTURY = 10 * DECADE
~ temp MILLENIA = 10 * CENTURY
~ temp seconds = milliseconds / 1000
{
- seconds >= MILLENIA:
{print_duration_helper(seconds, MILLENIA, "millenia", "s", "")}
- seconds >= CENTURY:
{print_duration_helper(seconds, CENTURY, "centur", "ies", "y")}
- seconds >= DECADE:
{print_duration_helper(seconds, DECADE, "decade", "s", "")}
- seconds >= YEAR:
{print_duration_helper(seconds, YEAR, "year", "s", "")}
- seconds >= MONTH:
{print_duration_helper(seconds, MONTH, "month", "s", "")}
- seconds >= FORTHNIGHT:
{print_duration_helper(seconds, FORTHNIGHT, "forthnight", "ies", "")}
- seconds >= WEEK:
{print_duration_helper(seconds, WEEK, "week", "s", "")}
- seconds >= DAY:
{print_duration_helper(seconds, DAY, "day", "s", "")}
- seconds >= HOUR:
{print_duration_helper(seconds, HOUR, "hour", "s", "")}
- seconds >= MINUTE:
{print_duration_helper(seconds, MINUTE, "minute", "s", "")}
- else:
{print_num(seconds)} second{seconds > 1:s}
}
=== function print_duration_helper(seconds, intervalUnit, prefix, plural, singular) ===
~ temp quotent = seconds / intervalUnit
~ temp reminder = seconds / intervalUnit
{print_num(quotent)} {prefix}{quotent > 1:{plural}|{quotent == 0:{plural}|{singular}}} {reminder > 0:{print_duration(reminder)}}
=== function print_num(x) ===
{
- x >= 1000000000000:
{print_num(x / 1000000000000)} trillion { x mod 1000000000000 > 0:{print_num(x mod 1000000000000)}}
- x >= 1000000000:
{print_num(x / 1000000000)} billion { x mod 1000000000 > 0:{print_num(x mod 1000000000)}}
- x >= 1000000:
{print_num(x / 1000000)} million { x mod 1000000 > 0:{print_num(x mod 1000000)}}
- x >= 1000:
{print_num(x / 1000)} thousand { x mod 1000 > 0:{print_num(x mod 1000)}}
- x >= 100:
{print_num(x / 100)} hundred { x mod 100 > 0:and {print_num(x mod 100)}}
- x == 0:
zero
- else:
{ x >= 20:
{ x / 10:
- 2: twenty
- 3: thirty
- 4: forty
- 5: fifty
- 6: sixty
- 7: seventy
- 8: eighty
- 9: ninety
}
{ x mod 10 > 0:<>-<>}
}
{ x < 10 || x > 20:
{ x mod 10:
- 1: one
- 2: two
- 3: three
- 4: four
- 5: five
- 6: six
- 7: seven
- 8: eight
- 9: nine
}
- else:
{ x:
- 10: ten
- 11: eleven
- 12: twelve
- 13: thirteen
- 14: fourteen
- 15: fifteen
- 16: sixteen
- 17: seventeen
- 18: eighteen
- 19: nineteen
}
}
}
// fallback function implementations:
=== function str_concat(strA, strB) ===
~ return "{strA}{strB}"
/*
=== function query(prompt, default) ===
~ temp result = ""
{ textStylingFallbackOption:
- "html":
\<script type=\"text/javascript\"\>\<!--
_inkStory.variablesState.$(\"lastQuery\", window.prompt(\"{prompt}\", \"{default}\"));
--\>\</script\>
}
~ result = lastQuery
~ lastQuery = ""
~ return result
*/
=== function query(prompt, default) ===
~ temp result = ""
{ textStylingFallbackOption:
- "html":
\<form id=\"theForm\"\>
\<label for=\"theText\"\>{prompt}\</label\>
\<input id=\"theText\" name=\"theText\" value=\"{default}\" type=\"text\" size=\"15\" />
\<button type=\"submit\"\>Enter\</button\>
\</form\>
\<script type=\"text/javascript\"\>\<!--
_inkStory.canContinue = false;
document.getElementById(\"theForm\").addEventListener(\"submit\", function (event) \{
event.preventDefault();
_inkStory.canContinue = true;
_inkStory.variablesState.$(\"lastQuery\", document.getElementById(\"theForm\").elements[\"theText\"].value);
\};
\-\-\>\</script\>
}
~ result = lastQuery
~ lastQuery = ""
~ return result
=== function italics_on() ===
{ textStylingFallbackOption:
- "html": <>\<i\><>
}
=== function italics_off() ===
{ textStylingFallbackOption:
- "html": <>\</i\><>
}
=== function bold_on() ===
{ textStylingFallbackOption:
- "html": <>\<b\><>
}
=== function bold_off() ===
{ textStylingFallbackOption:
- "html": <>\</b\><>
}
=== function underline_on() ===
{ textStylingFallbackOption:
- "html": <>\<u\><>
}
=== function underline_off() ===
{ textStylingFallbackOption:
- "html": <>\</u\><>
}
=== function strikethrough_on() ===
{ textStylingFallbackOption:
- "html": <>\<s\><>
}
=== function strikethrough_off() ===
{ textStylingFallbackOption:
- "html": <>\</s\><>
}
=== function ahref_on(destination_url) ===
{ textStylingFallbackOption:
- "html": <>\<a href=\"{destination_url}\"\><>
}
=== function ahref_off() ===
{ textStylingFallbackOption:
- "html": <>\</a\><>
}
TODO: impl fallback function for EXTERNAL print_delay(milliseconds)
// END-OF-INK-FILE
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment