Add giraffe script, deprecate old scripts

main
mio 2023-09-04 02:40:47 +00:00
parent 802412ba22
commit 961d89d11b
29 changed files with 437 additions and 1 deletions

BIN
thirdparty/our/coffee vendored

Binary file not shown.

View File

@ -0,0 +1,7 @@
{
"giraffe": 3,
"leaves": 0,
"hasEntEnc": false,
"lastEnc": "",
"gameEnded": false
}

View File

@ -0,0 +1,289 @@
import std/[json, jsonutils, os, parseopt, random, strutils, unicode]
type
GiraffeNames = tuple
adjs: seq[string]
names: seq[string]
nouns: seq[string]
Entities = tuple
names: seq[string]
statuses: seq[string]
comps: seq[string]
Trees = tuple
names: seq[string]
maxLeaves: int
Verbs = tuple
ents: seq[string]
trees: seq[string]
eats: seq[string]
Data = tuple
giraffeNames: GiraffeNames
entities: Entities
trees: Trees
verbs: Verbs
Chara = tuple
giraffe: int
leaves: int
hasEntEnc: bool
lastEnc: string
gameEnded: bool
Outcome = tuple
eval: string
like: string
evolve: int
const
env = (
modName: "giraffe",
modVer: "0.1",
modDesc: "a minigame based on d o z e n s ' giraffe ttrpg",
our: (on: true, pathData: "/town/our/data/"),
fileData: "giraffeData.json",
fileChara: "giraffe.json"
)
var
chara: Chara
data: Data
proc resetChara(): void =
chara = (
giraffe: 3,
leaves: 0,
hasEntEnc: false,
lastEnc: "",
gameEnded: false
)
proc saveChara(): void =
var node = pretty(toJson(chara))
if env.our.on:
writeFile(unixToNativePath(env.our.pathData & env.fileChara), node)
else:
writeFile(unixToNativePath(env.fileChara), node)
proc loadData(): void =
if env.our.on:
data = to(parseFile(unixToNativePath(env.our.pathData & env.fileData)),
Data)
if not fileExists(unixToNativePath(env.our.pathData & env.fileChara)):
resetChara()
saveChara()
else:
chara = to(parseFile(unixToNativePath(env.our.pathData & env.fileChara)),
Chara)
else:
data = to(parseFile(unixToNativePath(env.fileData)), Data)
if fileExists(unixToNativePath(env.fileChara)):
chara = to(parseFile(unixToNativePath(env.fileChara)), Chara)
else:
resetChara()
saveChara()
proc getGiraffe(showStatus = false): string =
var gStatus: string
if showStatus:
gStatus = " (giraffe)"
if chara.giraffe == 1:
gStatus = " (human)"
return "GIRAFFE: " & intToStr(chara.giraffe) & gStatus
proc randName(): string =
randomize()
return join(@[
capitalize(sample(data.giraffeNames.adjs)), " ",
capitalize(sample(data.giraffeNames.names)), " ",
capitalize(sample(data.giraffeNames.adjs)), " ",
capitalize(sample(data.giraffeNames.nouns))
])
proc randEncounter(ty = "any"): string =
randomize()
var
encTy = ty
roll = rand(1..100)
if ty == "any":
case roll
# Probability of showing yearning message: 5%
of 1, 10, 50, 90, 100:
encTy = "tree"
else:
encTy = "ent"
case encTy
# Meet entities
of "ent":
chara.hasEntEnc = true
chara.lastEnc = join(["You ", sample(data.verbs.ents), " ",
sample(data.entities.names), " ", sample(data.entities.statuses),
sample(data.entities.comps)])
return join([chara.lastEnc, getGiraffe()], " ")
# Get/eat leaves
else:
if chara.giraffe == 6:
var
leaves = rand(1..data.trees.maxLeaves)
leavesEaten = sample([true, false])
leavesDiff = ""
# Don't eat leaves if there are none
if leavesEaten and chara.leaves == 0:
leavesEaten = false
# Eat leaves
if leavesEaten:
if chara.leaves >= leaves:
chara.leaves -= leaves
leavesDiff = join([" (-", intToStr(leaves), ")"])
return join(["You ", sample(data.verbs.eats),
" some of the best leaves. Yum! Leaves: ", intToStr(chara.leaves),
leavesDiff])
else:
chara.leaves = 0
return join(["You ", sample(data.verbs.eats),
" all the best leaves. Yum! Leaves: ", intToStr(chara.leaves)])
else:
chara.leaves += leaves
return join(["You ", sample(data.verbs.trees), " ",
sample(data.trees.names), ". Leaves: ", intToStr(chara.leaves),
" (+", intToStr(leaves), ")"])
else:
return join(["You ", sample(data.verbs.trees), " ",
sample(data.trees.names), " with the best leaves, but your neck ",
"is too short and you cannot reach them. Sorrow! Hunger! Yearning!"])
proc randOutcome(): Outcome =
randomize()
var
roll = rand(1..6)
eval = "a failure."
evolve = 0
isLikeGir = sample([true, false])
like = "giraffe"
if not isLikeGir:
like = "human"
if roll == chara.giraffe:
eval = "… GIRAFFE?!! You have an epiphany."
elif (isLikeGir and roll == 1) or
(not isLikeGir and roll == 6):
eval = "an exceptional success! (+1 G)"
evolve = 1
elif (isLikeGir and roll < chara.giraffe) or
(not isLikeGir and roll > chara.giraffe):
eval = "a success."
elif (isLikeGir and roll == 6) or
(not isLikeGir and roll == 1):
eval = "an exceptional failure! (-1 G)"
evolve = -1
return (eval: eval, like: like, evolve: evolve)
proc doOutcome(action: string): string =
if chara.hasEntEnc:
var oc = randOutcome()
chara.giraffe += oc.evolve
chara.hasEntEnc = false
chara.lastEnc = ""
return join(["You ", action, " like a ", oc.like, ". It was ", oc.eval,
" ", getGiraffe()])
else:
return "You haven't encountered anyone yet. " & getGiraffe()
proc endGame(): string =
if chara.giraffe == 6:
chara.gameEnded = true
return "You evolve into the platonic ideal of a giraffe. " &
"Your neck is so long. You can easily reach all the best leaves."
elif chara.giraffe == 1:
chara.gameEnded = true
return "You devolve into a miserable human. " &
"You never get the best leaves. Instead you have to go get a job and " &
"work for the rest of your life."
proc handleLook(): string =
# Remind of existing encounter
if not chara.gameEnded and chara.hasEntEnc:
return join([chara.lastEnc, getGiraffe()], " ")
# Show new encounter
elif not chara.gameEnded and not chara.hasEntEnc:
return randEncounter()
# Get best leaves
else:
return randEncounter("tree")
proc run(): void =
var
p = initOptParser(quoteShellCommand(commandLineParams()))
args: seq[string]
for kind, k, _ in p.getopt():
case kind
of cmdArgument:
add(args, k)
of cmdShortOption, cmdLongOption, cmdEnd:
discard
# When running within `our` bot, the args sequence received is
# @[input, nick!username@cloak, channel], with input being the string to
# parse. Reset the args sequence.
if env.our.on:
var input = args[0]
args = unicode.split(input)
# Command run without args
if len(args) == 0:
loadData()
# Show ending only once per game session
if (chara.giraffe == 6 or chara.giraffe == 1) and not chara.gameEnded:
echo endGame()
else:
echo handleLook()
saveChara()
# Command run with args
elif len(args) == 1:
case args[0]
of "g", "giraffe":
loadData()
echo getGiraffe(true)
of "n", "name", "nick":
loadData()
echo randName()
of "r", "reset":
resetChara()
saveChara()
echo "Game reset."
of "h", "help", "halp":
echo "Options: get a giraffe [n]ame, show this [h]elp message," &
" [r]eset, [v]ersion"
of "v", "version":
echo join([env.modName, " ", env.modVer, " ~ ", env.modDesc])
else:
loadData()
if not chara.gameEnded:
echo doOutcome(join(args[0..^1], " "))
saveChara()
run()

View File

@ -0,0 +1,117 @@
{
"giraffeNames": {
"adjs": [
"big", "little", "long", "short", "tall", "spotted",
"black", "brown", "red", "yellow", "fast", "hungry",
"jumpy", "sleepy", "walking",
"chubby", "skinny", "stocky", "stubby", "sturdy", "wiry",
"auburn", "caramel", "chocolate", "ebony", "orange", "rainbow",
"dotty", "furry", "striped", "motley", "splotchy", "sprinkly",
"adventurous", "alluring", "amenable", "amiable", "aquatic", "awesome",
"beany", "beautiful", "bewildered", "bewitching", "bold", "brave",
"caring", "compassionate", "cool", "curly", "curvy", "cute",
"dangerous", "daring", "dashing", "delightful", "dippy", "divine",
"early", "earnest", "eccentric", "efficient", "elegant", "energetic",
"fanciful", "fearsome", "felicitous", "floppy", "friendly", "frisky",
"gummy", "horsey", "inquisitive", "jelly", "kickass", "lazy",
"meandering", "nifty", "oatmeal", "plush", "questing", "rocky",
"sprightly", "tanasinn", "uniquely", "vintage", "wise", "xoxo",
"yummy", "zippy", "funky", "funny", "party", "spiffy"
],
"names": [
"chandler", "ingrid", "irving", "irwin", "joey", "johnny",
"martha", "monica", "phoebe", "rachel", "ross", "suzie",
"thelma",
"aaron", "ahmed", "andy", "armand", "antonio", "atticus",
"abigail", "arashi", "alex", "anita", "anna", "artemis",
"barack", "benny", "bento", "bharat", "billy", "boris",
"becky", "bella", "beryl", "betty", "bianca", "britney",
"carlos", "cecil", "chris", "chucky", "corey", "craig",
"carla", "chandra", "chloe", "christina", "coco", "cordelia",
"danny", "david", "denzel", "derek", "drake", "duncan",
"dahlia", "dana", "daniella", "deepa", "delilah", "diana",
"earl", "eddie", "elijah", "emilio", "ernest", "evan",
"ekaterina", "elsa", "emily", "emma", "erin", "evi",
"eliot", "ellis", "elvis", "enid", "esther", "ethan",
"farad", "felix", "finn", "fran", "floyd", "fred",
"fariah", "fatima", "felicity", "fiona", "flora", "francesca",
"garry", "george", "gerald", "gilbert", "gunther", "guy",
"gabby", "georgina", "geri", "gina", "giselle", "greta",
"hansel", "harry", "hassan", "henri", "herman", "hyde",
"halle", "hannah", "haram", "harriet", "hazel", "henrietta",
"ian", "ibrahim", "icarus", "igor", "isaac", "ivan",
"ida", "ioana", "iliana", "irma", "isabella", "ivanka",
"jack", "jan", "jean", "jimmy", "jin", "johannes",
"janet", "jeanne", "jen", "jessie", "joanna", "june",
"karim", "keanu", "keigo", "kenny", "kingsley", "kyle",
"karin", "kate", "katya", "kelly", "kiera", "kim",
"lars", "larry", "leslie", "leviticus", "lionel", "luke",
"leah", "lena", "libby", "lily", "louise", "lucy",
"manfred", "mark", "matt", "merlin", "mike", "mortimer",
"maria", "marion", "maya", "mel", "moira", "mona",
"mahmud", "mehdi", "mustafa", "megan", "mikhaela", "mikuru",
"nate", "neil", "nick", "nigel", "norm", "nasheen",
"nala", "natasha", "nelly", "netta", "nigella", "nora",
"ollie", "omar", "oren", "oriol", "oscar", "octavia",
"pablo", "paul", "percy", "phineas", "pierre", "pete",
"pasha", "patty", "paula", "penelope", "petra", "priscilla",
"rand", "ricky", "ringo", "robbie", "rory", "rupert",
"reema", "ren", "rika", "rita", "ruby", "rukia",
"sam", "sergey", "sid", "sara", "selena", "sofia",
"takeshi", "teddy", "thebault", "timmy", "tommy", "tristan",
"tabitha", "tamara", "tammy", "tina", "tori", "trudy",
"uma", "ursula", "valentin", "valentina", "vicky", "victoria",
"vassily", "verne", "victor", "vincy", "vito", "vanessa",
"wally", "wayne", "willy", "wanda", "wendy", "wilma",
"yuki", "yuri", "yana", "yuna", "zach", "zedekiah"
],
"nouns": [
"hoof", "horn", "leaf", "legs", "neck", "kick",
"spots", "tongue", "tree",
"ear", "head", "heart", "knee", "mane", "tail",
"bark", "bud", "calyx", "petals", "root", "trunk"
]
},
"entities": {
"names": [
"a crocodile", "a mongoose", "a lion",
"a warthog", "a zebra", "a wildebeast",
"humans", "some wild dogs", "a cheetah",
"a giraffe", "an elephant", "a hyena"
],
"statuses": [
"hungry", "just wanting to chill", "hunting",
"wallowing", "on a pilgrimage", "passing through",
"poaching", "caring for the dead", "laying an ambush",
"looking for a mate", "digging for water", "setting up a lair"
],
"comps": [
", suffering from a toothache.", " but there are snakes!", " but bored.",
" and injured.", " while fleeing from someone or something.",
" and paranoid.",
" and lost.", " but it was all a ruse!", ", having been blackmailed.",
", way too awkward.", " with a sick child at home.",
" having been tricked."
]
},
"trees": {
"names": [
"an atlas cedar", "a baobab", "a camphor tree", "a gum tree",
"a large oak", "a mahogany tree", "a walnut tree", "a white lead tree",
"a yew tree"
],
"maxLeaves": 12
},
"verbs": {
"ents": [
"bump into", "come upon", "cross paths with", "run into", "see", "spot",
"spy"
],
"trees": [
"come upon", "discover", "find", "stumble upon"
],
"eats": [
"eat", "munch on", "nibble on", "snack on"
]
}
}

View File

@ -0,0 +1,23 @@
# giraffe
A minigame for the our bot based on dozens' [giraffe] TTRPG.
## Install
```
# Build executable
nim c -d:release giraffe.nim
# Copy executable to the our bot scripts directory
cp giraffe /town/our/
# Copy *.json files to the our bot data directory
cp *.json /town/our/data/
chmod 666 /town/our/data/giraffe.json
```
If running outside of our bot, set `env.our.on` to `false` in giraffe.nim before building the executable. The `.json` files should be in the same directory as the giraffe executable.
[giraffe]: https://tilde.town/~dozens/giraffe

View File

@ -1,3 +1,3 @@
# Readme # thirdparty/
Content for other townies' applications and bots. Content for other townies' applications and bots.