forked from mio/scripts
Add giraffe script, deprecate old scripts
parent
802412ba22
commit
961d89d11b
Binary file not shown.
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"giraffe": 3,
|
||||||
|
"leaves": 0,
|
||||||
|
"hasEntEnc": false,
|
||||||
|
"lastEnc": "",
|
||||||
|
"gameEnded": false
|
||||||
|
}
|
|
@ -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()
|
|
@ -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"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
|
@ -1,3 +1,3 @@
|
||||||
# Readme
|
# thirdparty/
|
||||||
|
|
||||||
Content for other townies' applications and bots.
|
Content for other townies' applications and bots.
|
||||||
|
|
Loading…
Reference in New Issue