diff --git a/ftg/config.sample.yml b/deprecated/ftg/config.sample.yml similarity index 100% rename from ftg/config.sample.yml rename to deprecated/ftg/config.sample.yml diff --git a/ftg/formatter.py b/deprecated/ftg/formatter.py similarity index 100% rename from ftg/formatter.py rename to deprecated/ftg/formatter.py diff --git a/ftg/hashi.py b/deprecated/ftg/hashi.py similarity index 100% rename from ftg/hashi.py rename to deprecated/ftg/hashi.py diff --git a/ftg/main.py b/deprecated/ftg/main.py similarity index 100% rename from ftg/main.py rename to deprecated/ftg/main.py diff --git a/ftg/readme.md b/deprecated/ftg/readme.md similarity index 100% rename from ftg/readme.md rename to deprecated/ftg/readme.md diff --git a/opml/mug.of.opml b/deprecated/opml/mug.of.opml similarity index 100% rename from opml/mug.of.opml rename to deprecated/opml/mug.of.opml diff --git a/opml/opml.sh b/deprecated/opml/opml.sh similarity index 100% rename from opml/opml.sh rename to deprecated/opml/opml.sh diff --git a/opml/readme.md b/deprecated/opml/readme.md similarity index 100% rename from opml/readme.md rename to deprecated/opml/readme.md diff --git a/opml/urls b/deprecated/opml/urls similarity index 100% rename from opml/urls rename to deprecated/opml/urls diff --git a/saiba80/readme.md b/deprecated/saiba80/readme.md similarity index 100% rename from saiba80/readme.md rename to deprecated/saiba80/readme.md diff --git a/saiba80/saiba80 b/deprecated/saiba80/saiba80 similarity index 100% rename from saiba80/saiba80 rename to deprecated/saiba80/saiba80 diff --git a/saiba80/saiba80.py b/deprecated/saiba80/saiba80.py similarity index 100% rename from saiba80/saiba80.py rename to deprecated/saiba80/saiba80.py diff --git a/saiba80/saiba80_game_titles.py b/deprecated/saiba80/saiba80_game_titles.py similarity index 100% rename from saiba80/saiba80_game_titles.py rename to deprecated/saiba80/saiba80_game_titles.py diff --git a/saiba80/sources/combined.txt b/deprecated/saiba80/sources/combined.txt similarity index 100% rename from saiba80/sources/combined.txt rename to deprecated/saiba80/sources/combined.txt diff --git a/saiba80/sources/fashion.txt b/deprecated/saiba80/sources/fashion.txt similarity index 100% rename from saiba80/sources/fashion.txt rename to deprecated/saiba80/sources/fashion.txt diff --git a/saiba80/sources/films.txt b/deprecated/saiba80/sources/films.txt similarity index 100% rename from saiba80/sources/films.txt rename to deprecated/saiba80/sources/films.txt diff --git a/saiba80/sources/games.txt b/deprecated/saiba80/sources/games.txt similarity index 100% rename from saiba80/sources/games.txt rename to deprecated/saiba80/sources/games.txt diff --git a/saiba80/sources/readme.md b/deprecated/saiba80/sources/readme.md similarity index 100% rename from saiba80/sources/readme.md rename to deprecated/saiba80/sources/readme.md diff --git a/saiba80/sources/toys.txt b/deprecated/saiba80/sources/toys.txt similarity index 100% rename from saiba80/sources/toys.txt rename to deprecated/saiba80/sources/toys.txt diff --git a/saiba80/sources/tv.txt b/deprecated/saiba80/sources/tv.txt similarity index 100% rename from saiba80/sources/tv.txt rename to deprecated/saiba80/sources/tv.txt diff --git a/twtxt/tw2txt b/deprecated/twtxt/tw2txt similarity index 100% rename from twtxt/tw2txt rename to deprecated/twtxt/tw2txt diff --git a/twtxt/txtsh b/deprecated/twtxt/txtsh similarity index 100% rename from twtxt/txtsh rename to deprecated/twtxt/txtsh diff --git a/thirdparty/our/coffee b/thirdparty/our/coffee deleted file mode 100755 index c06373c..0000000 Binary files a/thirdparty/our/coffee and /dev/null differ diff --git a/thirdparty/our/coffee.nim b/thirdparty/our/coffeefact/coffeefact.nim similarity index 100% rename from thirdparty/our/coffee.nim rename to thirdparty/our/coffeefact/coffeefact.nim diff --git a/thirdparty/our/giraffe/giraffe.json b/thirdparty/our/giraffe/giraffe.json new file mode 100644 index 0000000..da72e71 --- /dev/null +++ b/thirdparty/our/giraffe/giraffe.json @@ -0,0 +1,7 @@ +{ + "giraffe": 3, + "leaves": 0, + "hasEntEnc": false, + "lastEnc": "", + "gameEnded": false +} \ No newline at end of file diff --git a/thirdparty/our/giraffe/giraffe.nim b/thirdparty/our/giraffe/giraffe.nim new file mode 100644 index 0000000..be61f0d --- /dev/null +++ b/thirdparty/our/giraffe/giraffe.nim @@ -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() diff --git a/thirdparty/our/giraffe/giraffeData.json b/thirdparty/our/giraffe/giraffeData.json new file mode 100644 index 0000000..08a057b --- /dev/null +++ b/thirdparty/our/giraffe/giraffeData.json @@ -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" + ] + } +} diff --git a/thirdparty/our/giraffe/readme.md b/thirdparty/our/giraffe/readme.md new file mode 100644 index 0000000..5f6223d --- /dev/null +++ b/thirdparty/our/giraffe/readme.md @@ -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 diff --git a/thirdparty/readme.md b/thirdparty/readme.md index 1d027e1..df65b05 100644 --- a/thirdparty/readme.md +++ b/thirdparty/readme.md @@ -1,3 +1,3 @@ -# Readme +# thirdparty/ Content for other townies' applications and bots.