scripts/thirdparty/our/giraffe/giraffe.nim

290 lines
7.2 KiB
Nim
Raw Permalink Normal View History

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()