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.
|
||||
|
|
Loading…
Reference in New Issue