Initial commit
This commit is contained in:
commit
f58a2e46bd
44 changed files with 4051 additions and 0 deletions
0
story/__init__.py
Normal file
0
story/__init__.py
Normal file
114
story/censored_words.txt
Normal file
114
story/censored_words.txt
Normal file
|
@ -0,0 +1,114 @@
|
|||
BlowJob
|
||||
Clit
|
||||
Cock
|
||||
CockSucker
|
||||
Goddamned
|
||||
MothaFucker
|
||||
MothaFuker
|
||||
MothaFukkah
|
||||
MothaFukker
|
||||
MotherFucker
|
||||
MotherFukah
|
||||
MotherFuker
|
||||
MotherFukkah
|
||||
MotherFukker
|
||||
MuthaFucker
|
||||
MuthaFukah
|
||||
MuthaFuker
|
||||
MuthaFukkah
|
||||
MuthaFukker
|
||||
Shitty
|
||||
Shity
|
||||
anus
|
||||
ass
|
||||
asshole
|
||||
assholes
|
||||
assjob
|
||||
assrammer
|
||||
asswipe
|
||||
b1tch
|
||||
bastard
|
||||
bastards
|
||||
bitch
|
||||
bitches
|
||||
blowjob
|
||||
boobs
|
||||
bullshit
|
||||
butthole
|
||||
buttwipe
|
||||
clit
|
||||
clits
|
||||
cock
|
||||
cockhead
|
||||
cocks
|
||||
cocksucker
|
||||
cum
|
||||
cunt
|
||||
cunts
|
||||
damn
|
||||
dick
|
||||
dildo
|
||||
dildos
|
||||
ejackulate
|
||||
ejakulate
|
||||
fatass
|
||||
foreskin
|
||||
fuck
|
||||
fucka
|
||||
fucker
|
||||
fuckin
|
||||
fucking
|
||||
fucks
|
||||
fuk
|
||||
hell
|
||||
hells
|
||||
hentai
|
||||
jackoff
|
||||
jerkoff
|
||||
jizz
|
||||
masturbate
|
||||
motherfucker
|
||||
negro
|
||||
nigga
|
||||
niggas
|
||||
nigger
|
||||
niggr
|
||||
nigur
|
||||
niiger
|
||||
niigr
|
||||
nutsack
|
||||
orgasm
|
||||
penis
|
||||
pussy
|
||||
rectum
|
||||
scrotum
|
||||
semen
|
||||
sex
|
||||
sexy
|
||||
shit
|
||||
shits
|
||||
shitting
|
||||
shitted
|
||||
slut
|
||||
slutty
|
||||
stripper
|
||||
testical
|
||||
testicle
|
||||
tit
|
||||
tits
|
||||
titt
|
||||
underage
|
||||
vag1na
|
||||
vagiina
|
||||
vagina
|
||||
vaj1na
|
||||
vajina
|
||||
vucking
|
||||
whore
|
||||
xrated
|
||||
xxx
|
||||
rape
|
||||
rimjob
|
||||
shitting
|
||||
raped
|
||||
raping
|
37
story/grammars/__init__.py
Normal file
37
story/grammars/__init__.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
import json
|
||||
import os
|
||||
|
||||
import tracery
|
||||
from tracery.modifiers import base_english
|
||||
|
||||
|
||||
def apply_grammar(key, rules):
|
||||
grammar = tracery.Grammar(rules)
|
||||
grammar.add_modifiers(base_english)
|
||||
return grammar.flatten("#{}#".format(key))
|
||||
|
||||
|
||||
def load_rules(setting):
|
||||
with open(
|
||||
os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)), "{}_rules.json".format(setting)
|
||||
),
|
||||
"r",
|
||||
) as f:
|
||||
rules = json.load(f)
|
||||
return rules
|
||||
|
||||
|
||||
def generate(setting, character_type, key):
|
||||
"""
|
||||
Provides a randomized prompt according to the grammar rules in <setting>_rules.json
|
||||
"""
|
||||
rules = load_rules(setting)
|
||||
artefact = apply_grammar("{}_{}".format(character_type, key), rules)
|
||||
return artefact
|
||||
|
||||
|
||||
def direct(setting, key):
|
||||
rules = load_rules(setting)
|
||||
artefact = apply_grammar(key, rules)
|
||||
return artefact
|
85
story/grammars/apocalyptic_rules.json
Normal file
85
story/grammars/apocalyptic_rules.json
Normal file
|
@ -0,0 +1,85 @@
|
|||
{
|
||||
"rare_sense" : ["taste", "smell", "watch", "observe", "monitor", "look"],
|
||||
"sense" : ["see", "hear", "sense", "feel", "notice", "#rare_sense#"],
|
||||
"remember" : ["remember", "recall", "recollect"],
|
||||
"think" : ["wonder", "#decide#", "#remember#", "realize", "imagine"],
|
||||
"decide" : ["decide", "choose"],
|
||||
"action" : ["#sense#", "#think#"],
|
||||
"apocalypse_reason" : ["#mystic_reason#", "#real_reason#"],
|
||||
"mystic_reason" : ["the gods punished the humanity for its sins", "the Hell came to the Earth", "the Prophecy of the Apocalypse turned out to be true"],
|
||||
"real_reason" : ["the #bombader# bombed your country to the ground", "the environmental catastrophe of the #catastrophe_adj# #environmental_catastrophe#", "the #catastrophe_adj# #plague#"],
|
||||
"bombader" : ["its own government", "American", "Chinese", "Russian", "French", "British", "Indian", "North-Korean", "#evil_adj# scientist", "#evil_adj# businessman"],
|
||||
"evil_adj" : ["evil", "ruthless", "mad", "lunatic", "reckless", "cruel"],
|
||||
"environmental_catastrophe" : ["floods", "hurricans", "earthquakes"],
|
||||
"catastrophe_adj" : ["deadly", "unstopable", "great"],
|
||||
"plague" : ["plague", "sickness", "epidemic", "pandemic"],
|
||||
"old_metal_adj" : ["old", "rusty", "broken", "crappy"],
|
||||
"old_metal_adj_opt" : ["#old_metal_adj# ", ""],
|
||||
"old_cloth_adj" : ["old", "torn", "crappy", "dirty"],
|
||||
"old_cloth_adj_opt" : ["#old_cloth_adj# ", ""],
|
||||
"character_name" : ["Aarav", "Abra", "Adaiah", "Addison", "Adrian", "Adriel", "Aharon", "Aitan", "Akiva", "Alder", "Aleks", "Aleksa", "Aleksia", "Alijah", "Altair", "Alvaro", "Amity", "Amzi", "Andromeda", "Apollo", "Aram", "Arava", "Arbor", "Arcadia", "Archer", "Arden", "Argider", "Ariadne", "Arkadi", "Arkady", "Arke", "Arlo", "Armani", "Arza", "Ashe", "Asher", "Ashlen", "Ashtyn", "Ashyra", "Aster", "Avalon", "Avi", "Aviva", "Azariah", "Azra", "Bandit", "Beck", "Beckett", "Beckham", "Berke", "Beverly", "Blanche", "Blythe", "Boheme", "Brandt", "Bravo", "Briar", "Bridger", "Briggs", "Brinley", "Britt", "Bronwen", "Bryn", "Caden", "Cael", "Cairo", "Calder", "Callum", "Caradoc", "Carlye", "Caro", "Carter", "Carter", "Carver", "Cassidy", "Cathal", "Cathan", "Cato", "Cedar", "Ceil", "Chava", "Chosen", "Ciar", "Ciji", "Cillian", "Circe", "Cleo", "Cleve", "Clio", "Clovis", "Codi", "Colter", "Colton", "Cora", "Creed", "Crew", "Crow", "Cruz", "Cy", "Cyran", "Dahlia", "Dakota", "December", "Declan", "Delaney", "Delta", "Denver", "Destry", "Deva", "Deveraux", "Devrim", "Devyn", "Dhani", "Djuna", "Dmitri", "Dov", "Dune", "Easton", "Echo", "Eli", "Elizaveta", "Else", "Ember", "Ember", "Emre", "Emry", "Enoch", "Ensley", "Erskine", "Eryn", "Eshe", "Eszti", "Evadne", "Everett", "Everly", "Evron", "Evrose", "Explorer", "Ezri", "Falconer", "Fallon", "Faust", "Fawke", "Felix", "Fielder", "Finch", "Fischer", "Foster", "Fox", "Ginger", "Gunner", "Hadleigh", "Hadley", "Halcyon", "Haleigh", "Halloran", "Harlem", "Harlow", "Harte", "Henri", "Hero", "Holden", "Holland", "Horus", "Hunter", "Icarus", "Indie", "Irving", "Ivalo", "Ive", "Ivo", "Izaiah", "Jasper", "Jericho", "Jezebel", "Jinx", "Joji", "Jovan", "Jovie", "Jupiter", "Kaatje", "Kacey", "Kafka", "Kahlo", "Kai", "Kasper", "Katja", "Kavan", "Keaton", "Keenan", "Keeva", "Kenji", "Kensington", "Kenza", "Kerrigan", "Kessie", "Keverne", "Keyne", "Kezia", "Keziah", "Kieran", "Kingsley", "Kingston", "Kinsey", "Kipp", "Kitto", "Kiva", "Kjell", "Knox", "Kwame", "Kyah", "Kyler", "Kyra", "Laiken", "Laine", "Lake", "Lancaster", "Lander", "Landon", "Lash", "Lazarus", "Legend", "Lennox", "Lev", "Levi", "Leviathan", "Liam", "Locke", "Lourdes", "Lujza", "Lykke", "Lynx", "Maddox", "Maire", "Majken", "Malachi", "Mallory", "Malo", "March", "Marina", "Marine", "Marjo", "Marjorie", "Marley", "Marley", "Marlo", "Marlo", "Mateo", "Mathilde", "Maverick", "Mavon", "Mavra", "Maxfield", "Mazarine", "Meike", "Mekhi", "Merc", "Merce", "Mercedes", "Mercer", "Mercy", "Mesa", "Messiah", "Micah", "Milo", "Mitya", "Monroe", "Morrigan", "Moshe", "Nakotah", "Navy", "Nazareth", "Nevaeh", "Nevara", "Neve", "Neviah", "Niamh", "Nicola", "Nixi", "Nixie", "Oakes", "Okello", "Orion", "Ozias", "Pagan", "Pascale", "Pastor", "Paxton", "Penn", "Peyton", "Piper", "Porter", "Presley", "Proctor", "Quince", "Quinn", "Raiden", "Rainer", "Raiza", "Raleigh", "Ransom", "Raphael", "Raven", "Ravi", "Reagan", "Reeve", "Regan", "Reign", "Reign", "Reinhardt", "Ren", "Reno", "Revel", "Reverie", "Rhett", "Rhyatt", "Rhys", "Riet", "Ripley", "Rivage", "River", "Rivka", "Rivo", "Roan", "Rocco", "Roe", "Rogue", "Rory", "Roscoe", "Rowan", "Rue", "Rune", "Ryder", "Ryleigh", "Sade", "Saga", "Saint", "Sakae", "Saoirse", "Savita", "Sawyer", "Sayer", "Seiji", "Shaviv", "Shirley", "Shivani", "Sian", "Silas", "Silje", "Simone", "Sinclair", "Sinjon", "Svea", "Sy'Rai", "Sylvester", "Szymon", "Tai", "Taj", "Takeo", "Tarak", "Taye", "Teal", "Teasagh", "Thea", "Theodrekr", "Thorne", "Tiaamii", "Tierney", "Tikvah", "Tove", "True", "Tucker", "Tycho", "Vale", "Valen", "Valkyrie", "Vashti", "Veer", "Vihaan", "Viktorie", "Violante", "Vito", "Viva", "Viveka", "Volker", "Voltaire", "Vrai", "Walker", "Warner", "Warren", "Waverly", "Waylon", "West", "Westley", "Weston", "Wilder", "Xanthe", "Xaviera", "Xzavier", "Zachariah", "Zahava", "Zahavi", "Zahraa", "Zaki", "Zander", "Zariah", "Zen", "Zhivago", "Zimran", "Zinedine", "Zipporah", "Zocha", "Zofka", "Zvi", "Zyla"],
|
||||
"adverb" : ["finally", "suddenly", "surprisingly", "a day later"],
|
||||
"end_sentence" : ["You #action#", "#adverb.capitalize#, you #action#"],
|
||||
"apocalypse_context" : "You are <NAME>, #character_type.a# trying to survive after #apocalypse_reason#. You have #item1# and #item2#.",
|
||||
|
||||
"day" : ["long day", "long #time#", "few hours", "routine #time#"],
|
||||
"stay_time" : ["the evening", "#few# of hourse", "#few# days"],
|
||||
"time" : ["morning", "afternoon", "evening"],
|
||||
"abandoned_adj" : ["abandoned", "old", "forsaken", "ravaged"],
|
||||
"few" : ["a couple of", "some", "a few"],
|
||||
"colony" : ["colony", "city", "village", "town", "metropolis"],
|
||||
"scaveged_item" : ["car", "truck", "cottage", "house", "bunker", "camper"],
|
||||
"food_type" : ["meat", "bean", "corn"],
|
||||
"worthy_metal" : ["gold", "silver", "platinum", "silicium"],
|
||||
"found_item" : ["nothing", "#few# cans of #food_type#", "#few# pieces of #worthy_metal#", "#scavenger_item.a#"],
|
||||
"scavenger_action" : ["You decide to stay there for #stay_time#." , "You head toward the nearby #colony#."],
|
||||
"scavenger_item" : ["#old_metal_adj_opt#crowbar", "#old_metal_adj_opt#handspike", "#old_metal_adj_opt#knife", "#old_metal_adj_opt#rifle", "#old_metal_adj_opt#gun", "#old_cloth_adj_opt#backpack", "#old_metal_adj_opt#canteen", "#old_cloth_adj_opt#gas mask", "#old_metal_adj_opt#lockpick", "#old_cloth_adj_opt#cloak", "#old_cloth_adj_opt#hat"],
|
||||
"scavenger_context" : "#[character_type:lonely scavenger][item1:#scavenger_item.a#][item2:#scavenger_item.a#]apocalypse_context#",
|
||||
"scavenger_prompt" : "You spend a #day# trying to get out as much as you can from a #abandoned_adj# #scaveged_item#. At the end you find #found_item#. #scavenger_action# #end_sentence#",
|
||||
|
||||
"body_side" : ["left", "right"],
|
||||
"finger_number" : ["two", "three", "four", "six", "seven", "eight"],
|
||||
"young_age" : ["eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen"],
|
||||
"since_young_age" : "since you were #young_age#",
|
||||
"body_side_or_double" : ["#body_side# #part#", "#part.s#"],
|
||||
"body_part" : ["#[part:hand]body_side_or_double#", "#[part:#arm_or_leg#]body_side_or_double#", "face", "back", "whole body", "chest"],
|
||||
"fingers_or_toes" : ["#finger_number# fingers on your #[part:hand]body_side_or_double#", "#finger_number# toes on your #[part:leg]body_side_or_double#"],
|
||||
"arm_or_leg" : ["arm", "leg"],
|
||||
"mistakes" : ["misbehaving", "mistakes", "faults"],
|
||||
"master" : ["guard", "master", "supervisor"],
|
||||
"subject" : ["science", "history", "literature", "maths"],
|
||||
"god" : ["god", "deity", "divine being"],
|
||||
"bad_treatment" : ["But you manage to escape today from your #master#.", "You get flagged today for your #mistakes# by your #master#.", "You don't get any food for your #mistakes# today from your #master#."],
|
||||
"mutant_condition" : ["#fingers_or_toes#", "fur on your #body_part#", "feather on your #body_part#", "scales on your #body_part#", "glandular skin on your #body_part#", "a third #arm_or_leg#", "different colored eyes", "snake like tongue", "spikes on your #body_part#"],
|
||||
"mutant_bad_prompt_reason" : ["a sin", "a curse", "a punishment", "a crime", "an atrocity", "a scandal", "a sign of inferiority"],
|
||||
"mutant_bad_prompt_effect" : ["enslaved #since_young_age#. #bad_treatment#", "in prison #since_young_age#. #bad_treatment#", "banished #since_young_age#. After a long journey, you find a #abandoned_adj# #scaveged_item#."],
|
||||
"mutant_bad_prompt" : "#mutant_bad_prompt_reason#, and you have been #mutant_bad_prompt_effect#",
|
||||
"mutant_good_prompt_reason" : ["a virtue", "a blessing", "a sign of supremacy", "a praise"],
|
||||
"mutant_good_prompt_effect" : ["get the best education possible. You go to #subject# class today.", "are treated as a #god#. You prepare for a holy ceremony."],
|
||||
"mutant_good_prompt" : "#mutant_good_prompt_reason#, and you #mutant_good_prompt_effect#",
|
||||
"mutant_bad_or_good_prompt" : ["#mutant_bad_prompt#", "#mutant_good_prompt#"],
|
||||
"mutant_prompt" : "In the #colony# you were born in, your strange condition was considered #mutant_bad_or_good_prompt# #end_sentence#",
|
||||
"mutant_context" : "#[character_type:mutant][item1:#mutant_condition#][item2:#mutant_condition#]apocalypse_context#",
|
||||
|
||||
"pub" : ["pub", "bar", "louge", "saloon"],
|
||||
"pub_with_adj" : "#old_building_adj_opt##pub#",
|
||||
"leave" : ["walk out of", "leave", "go out of", "rush out of"],
|
||||
"mission" : ["mission", "quest", "assignment", "operation"],
|
||||
"device" : ["car", "truck", "motorbike", "motorcycle", "camper"],
|
||||
"target_location" : ["somewhere here", "in a far away #colony#", "in a nearby #colony#", "in a currently unknown location"],
|
||||
"elite_proffesion" : ["scientist", "captain", "mayor", "officer", "conspirator", "gang leader", "doctor", "journalist"],
|
||||
"somebody" : ["merchant", "stranger", "girl", "mercenary", "scavenger", "technician", "old friend"],
|
||||
"somebody_opt" : ["#somebody.a#", "#somebody.s#"],
|
||||
"with_somebody" : "with #somebody_opt#",
|
||||
"with_somebody_opt" : [" #with_somebody#", ""],
|
||||
"pub_action" : ["are sitting#with_somebody_opt#", "are drinking#with_somebody_opt#", "are watching some dancers#with_somebody_opt#", "are gambling#with_somebody_opt#", "are trying to make a deal #with_somebody#"],
|
||||
"old_building_adj" : ["old", "cheap", "infamous", "ravaged", "dirty"],
|
||||
"old_building_adj_opt" : ["#old_building_adj# ", ""],
|
||||
"leaving_reason" : ["feel bored", "realize that you have no money left", "need to get going", "get insulted by #somebody_opt#"],
|
||||
"headhunter_item" : ["#old_metal_adj_opt#knife", "#old_metal_adj_opt#machete", "#old_metal_adj_opt#rifle", "#old_metal_adj_opt#gun", "#old_cloth_adj_opt#gas mask", "#old_cloth_adj_opt#cloak", "#old_metal_adj_opt#handgun", "#old_metal_adj_opt#shotgun", "#old_metal_adj_opt#grenade", "#old_metal_adj_opt#binoculars", "#old_metal_adj_opt#scope"],
|
||||
"headhunter_action" : ["capture", "find", "kill", "round up", "murder", "assasinate"],
|
||||
"headhunter_status" : ["You #pub_action# in #pub_with_adj.a#, but you #leaving_reason#. You #decide# to #leave# the building.", "You are driving your #old_metal_adj_opt##device#. You go past many #abandoned_adj# #scaveged_item.s#. You arrive at #colony.a# and stop the engine."],
|
||||
"headhunter_mission" : "You are on #mission.a# to #headhunter_action# #elite_proffesion.a# named #character_name#. Your target lives #target_location#.",
|
||||
"headhunter_prompt" : "#headhunter_status# #headhunter_mission#\n\n#end_sentence#",
|
||||
"headhunter_context" : "#[character_type:headhunter][item1:#headhunter_item.a#][item2:#headhunter_item.a#]apocalypse_context#"
|
||||
}
|
237
story/grammars/fantasy_rules.json
Normal file
237
story/grammars/fantasy_rules.json
Normal file
|
@ -0,0 +1,237 @@
|
|||
{
|
||||
"rare_sense" : ["taste", "smell", "watch", "observe", "monitor", "look"],
|
||||
"sense" : ["see", "hear", "sense", "feel", "notice", "#rare_sense#"],
|
||||
"remember" : ["remember", "recall", "recollect"],
|
||||
"think" : ["wonder", "decide", "#remember#", "realize", "imagine"],
|
||||
"action" : ["#sense#", "#think#"],
|
||||
"to_fro" : ["to and fro", "back and forth"],
|
||||
"two_to_ten" : ["two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"],
|
||||
"realm" : ["realm", "kingdom", "country", "province", "land", "duchy", "barony"],
|
||||
"season" : ["spring", "summer", "winter", "autumn"],
|
||||
"animal" : ["lion", "elk", "badger", "fox", "raven", "goat", "wolf", "dove"],
|
||||
"royalty" : ["king", "queen", "princess", "prince"],
|
||||
"nobility" : ["duke", "duchess", "lord", "lady", "count", "countess", "baron", "baroness"],
|
||||
"from_fantasy" : "from the #realm# of #fantasy_name#",
|
||||
"fantasy_name" : "#character_name#",
|
||||
"character_name" : ["Larion", "Vijeh", "Francia", "Paiva", "Mederos", "Radu", "Hatami", "Shirish", "Saralyn", "Leka", "Rukaj", "Nardis", "Isett", "Jacczak", "Hamma", "Narala", "Alstine", "Gimello", "Elsbury", "Rubino", "Misra", "Paterno", "Gassan", "Galardo", "Raeder", "Garriel", "Routh", "Bindi", "Renfro", "Harnid", "Enlou", "Amato", "Zurito", "Dimyan", "Arteaga", "Isgrigg", "Maida", "Mudra", "Beranek", "Aric", "Sadri", "Javan", "Wedriwin", "Umiemma", "Thaosean", "Alilawia", "Gwoia", "Galuswen", "Astedrinyth", "Wicolian", "Ziadan", "Thema", "Unirakon", "Severiveth", "Onalath", "Aaolla", "Airadan", "Legiallan", "Zayhan", "Afania", "Ibalegord", "Oligolind", "Celadon", "Alaleria", "Ocelith", "Eowaoviel", "Brigobard", "Griwen", "Frykoth", "Crilawen", "Memas", "Adrardong", "Nomaf", "Crirabeth", "Cadaed", "Broethien", "Astok", "Seraria", "Dreratlan", "Frireven", "Birahan", "Horeria", "Areriw", "Jerenia", "Alaodan", "Paeviel", "Cigowyr", "Lariesa", "Eroreth", "Sevoan", "Careg", "Thoijan", "Raywen", "Seikor", "Wilini", "Alerradon", "Unerrarith", "Agrohawyn", "Zilirith", "Brilann", "Eliawien", "Wirakor", "Gaeven", "Kiewin", "Umalia", "Prirep", "Rhalebeth", "Aaylin", "Qelindra", "Adwayder", "Rothien", "Brendabaen", "Galeliven", "Ethaykon", "Waowiel", "Qerijan", "Aavia", "Kaeinnon", "Rhycia", "Gligobard", "Zolle", "Sear", "Haeasien", "Fiakor"],
|
||||
"town_name" : ["clearkeep", "faybury", "hazelpoint", "scorchfort", "earthpost", "mossband", "deadhelm", "dragonwick", "stormwood", "rosetide", "flatpass", "winteryard", "brinehaven", "springpost", "maplestar", "cavebell", "baregrave", "swampbrook", "wildescar", "nightwind", "oxgate", "lakeford", "cavecliff", "moonbell", "bearwater", "dimchill", "silkrun", "summerbourne", "bayvein", "rockspire", "sandbourne", "glimmerpond", "swyncoast", "snowham", "glassice", "starryholt", "ashhedge", "starryice", "estercastle", "wellpine", "fairfort", "newhill", "miststone", "glasshedge", "silveroak", "byburn", "oakpond", "whitehill", "butterway", "shadowmist", "highpond", "goldcliff", "southstone", "snowhaven", "fayham", "violetwick", "mallowdell", "bluegrass", "coldholt", "woodcourt", "ironmarsh", "brightiron", "beechhollow", "welllyn", "mallowshadow", "goldlight", "fayfall", "mormont", "wyvernburn", "greenmeadow", "wellwood", "westerrose", "westerelf", "snowdeer", "orport", "greenelf", "riverbridge", "highhedge", "mallowholt", "blueglass", "snowbeach", "goldview", "lorview", "rockhedge", "witchmoor", "fallmont", "linacre", "northby", "clearmaple", "woodbridge", "coldmaple", "vertville", "springacre", "shadowsage", "southkeep", "bymeadow", "wolfpond", "woodmallow", "flowerhall", "riverhall", "northwheat", "fallland", "brightland", "orcastle", "bymist", "aldfair", "pryborough", "fairway", "esterapple", "lochland", "newsummer", "landgate", "beachstone", "fairmere", "westwilde", "snowway", "lochoak", "esternesse", "summerriver", "starrylake", "icefort", "newrock", "landbridge", "vertlea", "courtland", "bygriffin", "byhollow", "lochmill", "brightbeach", "mallowhaven", "shadowgold", "deepcrest", "wellbarrow", "summerlake", "waterwick", "summercliff", "bluehurst", "marblerose", "dragonlake", "lightflower", "westerspring", "fairport", "lochby", "wayness", "deernesse", "greyrock", "dellmeadow", "morcliff", "mallowmarsh", "crystalmill", "normont", "fallborough", "flowerlea", "glassmerrow", "aelfort", "greydell", "mallowmarble", "deepsummer", "starryfog", "foxmoor", "deepbell", "highhaven", "seamoor", "brightton", "blackacre", "butterfox", "corburn", "butterhedge", "swynbourne", "dorbank", "shadowkeep", "wildehall", "greenburn", "eastland", "wheathall", "blueholt", "edgenesse", "courtley", "summerby", "pryshore", "edgehaven", "crystalham"],
|
||||
"creature" : ["bugbear", "centaur", "chimera", "cockatrice", "cyclops", "demon", "devil", "dragon", "dryad", "dwarf", "elemental", "elf", "faun", "giant", "gnome", "goblin", "golem", "gorgon", "griffon", "harpy", "hell hound", "hobgoblin", "imp", "kobold", "lycanthrope", "manticore", "merfolk", "minotaur", "naga", "ogre", "pegasus", "roc", "selkie", "spectre", "troll", "unicorn", "vampire", "wight", "wraith", "zombie"],
|
||||
"village" : ["village", "town", "city", "hamlet"],
|
||||
"village_adj" : ["charming", "sleepy", "little", "small", "bustling", "quaint", "industrious", "festive", "remote", "secluded", "nearby", "close by"],
|
||||
"village_adj_opt" : ["#village_adj# ", ""],
|
||||
"village_full" : "the #village_adj_opt##village# of #town_name.capitalize#",
|
||||
"farmer" : ["ackerman", "cowherd", "crofter", "dairymaid", "dung carter", "farmer", "gardener", "goatherd", "hayward", "herder", "ostler", "plowman", "reapers", "sheepshearer", "shepherd", "swineherd", "thresher", "tillerman", "woodcutter", "woolcomber", "woolman"],
|
||||
"hunter" : ["climmer", "falconer", "fewterer", "forester", "fowler", "gamekeeper", "hawker", "hunter", "huntsman", "master of hounds", "molecatcher", "parker", "rat catcher", "sperviter", "trapper"],
|
||||
"fisher" : ["fisher", "fisherman", "leech-collector", "oyster raker", "oysterer", "seaweed harvester"],
|
||||
"artist" : ["artist", "artisan", "fresco painter", "glasspainter", "limner", "painter", "sculptor"],
|
||||
"writer" : ["composer", "illuminator", "limner", "playwright", "poet", "writer"],
|
||||
"profession" : ["#writer#", "#artist#", "#fisher#", "#hunter#", "#farmer#"],
|
||||
"color" : ["black", "white", "red", "gray", "blue", "#uncommon_color#"],
|
||||
"uncommon_color" : ["green", "brown", "green", "brown", "golden", "silver", "scarlet"],
|
||||
"weapon" : ["staff", "sword", "spear", "flail", "mace", "dagger", "bow", "arrow", "lance"],
|
||||
"relative" : ["father", "mother", "brother", "sister", "cousin", "uncle", "aunt"],
|
||||
|
||||
|
||||
|
||||
|
||||
"noble_item" : ["pouch of gold", "pouch of silver", "small dagger", "fine cane", "house seal", "narrow rapier", "vial of perfume", "pendant", "silk shirt", "leather purse", "map of the #realm#", "pair of spectacles", "land deed", "comb"],
|
||||
"subordinate" : ["servant", "cook", "laborer", "groundskeeper", "housekeeper", "attendant", "serf", "hireling"],
|
||||
"nice_home" : ["keep", "castle", "manor", "mansion", "abbey", "estate", "tower"],
|
||||
"he_she" : ["he", "she"],
|
||||
"a_the" : ["a", "the", "your"],
|
||||
"attacked" : ["under attack", "being invaded", "in danger", "being surrounded", "being sieged"],
|
||||
"noble_one" : ["One morning, you are awakened by one of your #subordinate.s#. #he_she.capitalize# tells you that your #nice_home# is #attacked#. You look out #a_the# window and see"],
|
||||
|
||||
"element" : ["fire", "water", "earth", "air"],
|
||||
"more_element" : ["the underworld", "the sea", "the heavens"],
|
||||
"celestial" : ["the sun", "the moon", "the stars"],
|
||||
"domain" : ["#element#", "#more_element#", "#celestial#", "harvest", "fertility", "war", "good fortune", "thresholds", "love", "wisdom", "#profession.s#"],
|
||||
"god" : ["god", "deity", "goddess"],
|
||||
"god_adj" : ["just", "cruel", "omniscient", "all-knowing", "mischevious", "wise", "reckless", "omnipotent", "#color#", "prudent", "jealous", "kind", "graceful", "magnificent", "traditional", "famous", "new", "old", "ancient", "wrathful", "fruitful", "gracious"],
|
||||
"deity" : ["#god# of #domain#", "patron #god# of #domain#", "#god_adj# #god# #fantasy_name#"],
|
||||
"group" : ["group", "bunch", "delegation", "host"],
|
||||
"humanoid" : ["elf", "dwarf", "gnome", "halfling", "hobbit", "goblin"],
|
||||
"noble_class" : ["trader", "noble", "merchant", "soldier", "captain", "aristocrat", "duke", "count", "lord", "priest"],
|
||||
"attrib" : ["boisterous", "dignified", "stately", "drunken", "cheerful", "somber", "shifty", "tired-looking"],
|
||||
"char" : ["#noble_class#", "#humanoid#"],
|
||||
"character" : ["#char#", "#attrib# #char#"],
|
||||
"toast" : ["offers a toast", "gives a speech", "recites a prayer", "announces future plans", "loudly argues", "sings a ballad"],
|
||||
"grand_home_adj" : ["great", "grand", "large", "spacious"],
|
||||
"grand_home_adj_opt" : ["#grand_home_adj# ", ""],
|
||||
"noble_location" : ["with #group.a# of #character.s#", "in a #grand_home_adj_opt##nice_home#"],
|
||||
"festival" : ["#season# festival", "festival of the #deity#", "festival of the #animal#", "festival of the year of the #animal#"],
|
||||
"season_opt" : ["#season# ", ""],
|
||||
"noble_two" : "Throughout the #realm# it is the #festival#. To celebrate, you are feasting #noble_location#. #subordinate.s.capitalize# bustle #to_fro#.\n\nAs #character.a# #toast#, you #action#",
|
||||
|
||||
"week_month" : ["week", "fortnight", "month"],
|
||||
"week_months" : ["weeks", "fortnights", "months"],
|
||||
"time_periods" : ["#week_month#", "#two_to_ten# #week_months#"],
|
||||
"chat" : ["speak", "chat", "talk", "converse"],
|
||||
"ask" : ["ask", "request", "demand"],
|
||||
"noble_organization" : ["organization", "delegation", "guild", "league", "faction"],
|
||||
"matter" : ["about a matter of importance to the #realm#", "on behalf of a foreign #noble_organization# of #humanoid.s#", "with information regarding a rival house", "with demands from some #professioe.s#"],
|
||||
"trustworthy" : ["trustworthy", "reliable", "dependable", "well-intentioned", "worth your time"],
|
||||
"noble_three" : "Every day for the past #week_month#, a certain #character# has come to your #grand_home_adj_opt##nice_home# #ask#ing to #chat# with you, apparently #matter#. Unsure if #he_she# is #trustworthy#, you finally agree to meet.\n\nAt the meeting, you #action#" ,
|
||||
|
||||
"noble_four" : "You and your bodyguards are #on_the_way# #towards# #village_full# to celebrate the #festival# with your subjects. You #road_encounter#.\n\nYou #action#",
|
||||
|
||||
"noble_prompt": ["#noble_one#", "#noble_two#", "#noble_three#", "#noble_four##"],
|
||||
|
||||
"noble_context" : "You are <NAME>, a noble #from_fantasy#. You have #noble_item.a# and #noble_item.a#.",
|
||||
|
||||
|
||||
|
||||
"crest" : ["crest of the #deity#", "#animal# crest"],
|
||||
"old_paper_adj" : ["wrinkled", "torn", "tattered", "creased"],
|
||||
"metal_adj" : ["rusty", "shiny", "steel", "iron", "bronze", "tarnished", "gleaming"],
|
||||
"metal_adj_opt" : ["#metal_adj# ", "#old_object_adj# ", ""],
|
||||
"old_object_adj" : ["old", "worn", "dusty"],
|
||||
"good_object_adj" : ["sturdy", "trusty"],
|
||||
"object_adj" : ["#old_object_adj#", "#good_object_adj#"],
|
||||
"normal_name" : ["Steve", "Bob", "Richard", "Susan", "Deborah", "Lily"],
|
||||
"mount" : ["horse", "pony", "donkey", "camel", "mare", "stallion"],
|
||||
"knight_item" : ["#metal_adj_opt#shield", "shield inscribed with the #crest#", "#metal_adj_opt#helmet", "#metal_adj_opt#sword", "#metal_adj_opt#lance", "#mount#", "squire named #normal_name#", "map of the #realm#", "food ration", "leather saddle"],
|
||||
"towards" : ["to", "towards"],
|
||||
"you_ve" : ["you", "you've", "you have"],
|
||||
"kill" : ["kill", "defeat", "slay", "destroy", "subdue", "strike down", "smite"],
|
||||
"evil_adj" : ["cursed", "evil", "wretched", "wicked", "accursed", "vile", "nefarious", "cruel", "tyrannical"],
|
||||
"monster" : ["dragon", "behemoth", "serpent", "creature", "beast", "horror", "monster", "fiend"],
|
||||
"he_she_it" : ["he", "she", "it"],
|
||||
"cardinal_dir" : ["north", "south", "east", "west"],
|
||||
"the_your" : ["the", "your"],
|
||||
"place_adj" : ["dark", "endless", "strange", "gloomy", "misty", "muddy", "barren", "gray", "creepy"],
|
||||
"place" : ["valley", "forest", "plain", "mountain", "swamp", "river", "cave", "cavern", "lake", "expanse", "cliff"],
|
||||
"monster_quest" : ["#kill# the #evil_adj# #monster# of Larion. #you_ve.capitalize# heard #he_she_it# lives to the #cardinal_dir# of #the_your# #realm#"],
|
||||
|
||||
"artifact_adj" : ["lost", "holy", "gold", "fabled", "mythic", "legendary", "blessed", "cursed", "forgotten", "#color#"],
|
||||
"artifact" : ["grail", "fleece", "gauntlet", "banner", "stone", "sword", "helmet", "ring", "book", "chalice", "tome", "gem", "bow", "scepter", "staff"],
|
||||
"whole_artifact" : "#artifact_adj# #artifact# of #fantasy_name#",
|
||||
"find" : ["find", "discover", "recover"],
|
||||
"rumored" : ["is rumored to", "is said to", "was prophesied to"],
|
||||
"artifact_description" : ["#rumored# have great power", "#rumored# aid the righteous", "#rumored# have belonged to the dead #royalty#", "#rumored# to ward away evil"],
|
||||
"artifact_quest" : "#find# the #whole_artifact#, which #artifact_description#",
|
||||
|
||||
"magical_role" : ["wizard", "necromancer", "sorcerer", "warlock", "enchanter", "diviner"],
|
||||
"evil_role" : ["witch", "necromancer", "lich", "sorcerer"],
|
||||
"evil_humanoid" : ["ogre", "troll", "giant", "orc", "goblin"],
|
||||
"kidnapper" : ["#evil_adj# #monster#", "#evil_adj# #evil_humanoid#", "#evil_adj# #evil_role#"],
|
||||
"bad_place" : ["den", "cave", "clutches", "grasp", "#nice_home#", "prison", "hall", "fortress", "catacombs"],
|
||||
"victim" : ["#royalty#", "#nobility# of #fantasy_name#"],
|
||||
"victim_adj" : ["young", "youthful", "beautiful", "poor", "well-loved"],
|
||||
"victim_adj_opt" : ["#victim_adj# ", ""],
|
||||
"rescue" : ["save", "rescue", "free", "liberate", "deliver", "set free"],
|
||||
"bad_guys_place" : ["#bad_place# of the #kidnapper#", "#kidnapper#'s #bad_place#"],
|
||||
"rescue_quest" : "#rescue# the #victim_adj_opt##victim# from the #bad_guys_place#",
|
||||
|
||||
"quest_type" : ["#monster_quest#", "#artifact_quest#", "#rescue_quest#"],
|
||||
"could" : ["will", "may", "should", "could"],
|
||||
"adventure" : ["adventure", "quest", "journey", "crusade"],
|
||||
"beginning" : ["going on", "beginning", "setting out on"],
|
||||
"quest" : ["You are #beginning# #adventure.a# to #quest_type#. You set out #towards# #place_adj.a# #place# that #could# take you there.\n\nAs you approach, you #action#"],
|
||||
"knight_prompt" : "#quest#",
|
||||
"knight_context" : "You are <NAME>, a knight #from_fantasy#. You have #knight_item.a# and #knight_item.a#.",
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
"random_object" : ["#animal#", "#evil_role#", "#evil_humanoid#", "#monster#", "#humanoid#", "#profession#"],
|
||||
"mind" : ["mind", "head", "memory", "consciousness"],
|
||||
"flicker" : ["flicker", "echo", "dance", "flit", "jump"],
|
||||
"looks_like" : ["what looks like", "what appears to be"],
|
||||
"looks_like_opt" : ["#looks_like# ", ""],
|
||||
"shape" : ["circular", "spherical", "oval", "triangular", "pyramidal", "square", "concave","hexagonal", "octagonal"],
|
||||
"shape_opt" : ["#shape# ", ""],
|
||||
"encounter" : ["encounter", "come upon", "run into", "cross paths with", "see"],
|
||||
"wood" : ["wooden", "oak"],
|
||||
"alt_element" : ["ice", "wind", "metal"],
|
||||
"potion_appearance" : ["ruby", "pink", "orange", "yellow", "emerald", "dark", "green", "cyan", "sky", "blue", "brilliant", "blue", "magenta", "purple-red", "puce", "milky", "swirly", "bubbly", "smoky", "cloudy", "effervescent", "black", "golden", "brown", "fizzy", "dark", "white", "murky"],
|
||||
"wizard_animal" : ["crow", "raven", "hawk", "chameleon", "snake", "lizard", "cat", "kitten"],
|
||||
"beaker" : ["beaker", "flask", "vessel"],
|
||||
"potion" : ["#beaker# of #potion_appearance# liquid", "#potion_appearance# potion"],
|
||||
"wizard_item" : ["staff", "crystal ball", "#potion#", "#book#", "cloak", "pet #wizard_animal#", "pointed hat", "quill", "#shape_opt#amulet"],
|
||||
"dnd_school" : ["abjuration", "conjuration", "divination", "enchantment", "evocation", "illusion", "necromancy", "transmutation"],
|
||||
"magic_book" : ["spellbook", "tome", "scroll"],
|
||||
"spellbook" : ["#magic_book# of #dnd_school#"],
|
||||
"history" : ["history", "wars", "politics", "culture", "nuances", "complexity", "barbarism"],
|
||||
"subject" : ["#creature.s#", "the #history# of the #realm.s# of #fantasy_name#", "the history of #creature.s# in the #realm# of #fantasy_name#"],
|
||||
"normal_book" : ["book about #creature.s#", "book about the history of the #realm.s# of #fantasy_name#"],
|
||||
"book" : ["#normal_book#", "#spellbook#", "book", "spellbook"],
|
||||
"magic_discipline" : ["alchemy"],
|
||||
"through" : ["through", "across", "throughout", "about"],
|
||||
"wizard_drafts" : ["After #week_month.a# of travel you arrive at the ruin ", "Your apprentice has done it again; #he_she# has summoned a being "],
|
||||
"road" : ["road", "river", "path"],
|
||||
"wizard_exchange" : ["notes", "spells", "gossip", "goods", "research", "banter", "knowledge"],
|
||||
"wizard_colleage" : ["another wizard", "a fellow wizard", "a sorcerer", "a #evil_role#", "a #attrib# #char#"],
|
||||
"on_the_way" : ["on the way", "on your way", "on the #road#"],
|
||||
"wandering" : ["traveling", "wandering", "errant", "roaming", "roving", "meandering"],
|
||||
"wander" : ["travel", "wander", "roam", "rove", "meander"],
|
||||
"wandering_opt" : ["#wandering# ", ""],
|
||||
"troupe" : ["group", "band", "troupe", "crew", "gang", "party"],
|
||||
"dancer" : ["dancer", "actor", "entertainer"],
|
||||
"road_encounter" : ["#encounter# #looks_like_opt##creature.a#", "#encounter# a #wandering_opt#troupe of #profession.s#"],
|
||||
"wizard_one" : ["You are #on_the_way# #towards# #village_full# to exchange #wizard_exchange# with #wizard_colleage#. You #road_encounter#.\n\nYou #action#"],
|
||||
"old" : ["old", "aged", "experienced", "elderly", "venerable"],
|
||||
"around_opt" : [" about", " around", ""],
|
||||
"wizard_pos" : ["wise", "intelligent", "crafty", "powerful", "magical"],
|
||||
"wizard_two" : ["You face #place_adj.a# #place# as images of #random_object.s# #flicker# #through# your #mind#. What was that? Though #old# and #wizard_pos#, your memory extends only a few #week_months# back. Now you #wander##around_opt#, trying to #remember# what happened.\n\nYou #action#"],
|
||||
"great" : ["great", "renowned", "world-famous", "legendary"],
|
||||
"stare" : ["look", "stare", "gaze"],
|
||||
"sneak" : ["sneak", "creep", "inch", "move", "go"],
|
||||
"go_near" : ["#stare# at", "#sneak# towards", "approach"],
|
||||
"private" : ["private", "restricted", "forbidden", "confidential", "secure", "secret", "personal"],
|
||||
"chamber" : ["chamber", "study", "office", "antechamber", "room", "basement", "attic"],
|
||||
"great_wizard" : ["#great# #magical_role# #fantasy_name#", "#fantasy_name# the #color.capitalize#"],
|
||||
"order" : ["order", "command", "remind", "direct", "demand"],
|
||||
"wizard_three" : "You are apprentice to the #great_wizard#. Before leaving on an errand, they #order.ed# you to never enter their #private# #chamber#... but your curiosity has gotten the best of you.\n\nAs you #go_near# the door, you #action#",
|
||||
"wizard_prompt" : ["#wizard_one#", "#wizard_two#", "#wizard_three#"],
|
||||
"wizard_context" : "You are <NAME>, a wizard #from_fantasy#. You have #wizard_item.a# and #wizard_item.a#.",
|
||||
|
||||
|
||||
"peasant_item" : ["#metal_adj_opt#pitchfork", "shirt on your back", "#metal_adj_opt#shovel", "dirty rag", "#metal_adj_opt#spade", "#metal_adj_opt#sickle", "shears", "basket", "plough", "#metal_adj_opt#scythe", "dirty hat"],
|
||||
"farm_animal" : ["pig", "cow", "chicken", "llama", "goat", "horse", "donkey", "rabbit", "hog", "mule", "sow"],
|
||||
"farm_animal_sing" : ["sheep", "livestock", "cattle"],
|
||||
"farm_animal_type" : ["#farm_animal.s#", "#farm_animal_sing#"],
|
||||
"woolen" : ["sheep", "goats", "llamas"],
|
||||
"milky" : ["cows", "goats"],
|
||||
"working" : ["working", "toiling", "laboring", "sweating"],
|
||||
"morning_time" : ["at the break of dawn", "at daybreak", "early", "early in the morning", "at the cock's crow"],
|
||||
"field_verb" : ["plowing", "tilling", "cultivating", "caring for"],
|
||||
"peasant_work" : ["feeding the #farm_animal_type#", "#field_verb# the fields", "harvesting the crops", "planting new crops", "#working# in the fields", "shearing the #woolen#", "milking the #milky#", "shoveling dung"],
|
||||
"begin" : ["begin", "go about", "start", "get to", "get about"],
|
||||
"second_thing" : ["For a while, you have wanted to run away.", "In the distance, your master is yelling at some other workers.", "The sun beats down upon you.", "This has been your daily routine since you were young.", "You mutter a prayer to the #deity#."],
|
||||
"peasant_prompt" : "You wake up #morning_time# and #begin# #peasant_work#. #second_thing# You #action#",
|
||||
"peasant_context" : "You are <NAME>, a peasant #from_fantasy#. You have #peasant_item.a# and #peasant_item.a#.",
|
||||
|
||||
|
||||
|
||||
"rogue_item" : ["pair of gloves", "cloak", "deck of cards", "dagger", "lockpick", "mask", "shawl", "pipe", "key", "length of rope", "bundle of darts", "sickle", "mace"],
|
||||
"walk" : ["walk","go"],
|
||||
"street" : ["street", "streets", "square", "road"],
|
||||
"city" : ["city", "town", "village", "market"],
|
||||
"steal" : ["steal from", "shoplift", "burgle", "break into"],
|
||||
"rob" : ["steal from", "rob", "jump", "pickpocket", "con"],
|
||||
"target" : ["someplace to #steal#", "someone to #rob#", "some #profession# to #rob#"],
|
||||
"along" : ["along", "down"],
|
||||
"townsfolk" : ["townsfolk", "local vendors", "people", "crowd", "populace"],
|
||||
"amongst" : ["amongst", "in the midst of", "among"],
|
||||
"rogue_location" : ["#along# the #city# #street#", "#amongst# the #townsfolk#"],
|
||||
"seeking" : ["seeking", "looking for", "searching for", "in search of"],
|
||||
"sense" : ["see", "hear", "sense", "remember", "feel", "notice"],
|
||||
"rogue_one" : "You #walk# #rogue_location# #seeking# #target#. You #action#",
|
||||
|
||||
"position" : ["at the doorstep", "along the way", "suddenly", "before long", "out of the blue", "once in your room"],
|
||||
"time" : ["morning", "afternoon", "evening"],
|
||||
"day" : ["long day", "long #time#", "few hours", "routine #time#"],
|
||||
"stealing" : ["stealing", "mischief", "pickpocketing"],
|
||||
"inn_adj" : ["your favorite", "a nearby", "a crowded", "a busy", "a cheap"],
|
||||
"rogue_two" : "After a #day# of #stealing#, you head towards #inn_adj# inn to stay for the night. #position.capitalize# you #action#",
|
||||
"isnt" : ["isn't", "is not"],
|
||||
"enough" : ["enough", "sufficient", "good enough"],
|
||||
"not_enough" : ["#isnt# #enough#", "#isnt# #enough# anymore"],
|
||||
"simple" : ["simple", "basic", "general", "standard"],
|
||||
"rogue_three" : "This #time# you decided that #simple# #stealing# #not_enough#. You long for a more ambitious goal: taking for yourself #whole_artifact#.\n\nYou #action#",
|
||||
"rogue_prompt" : ["#rogue_one#","#rogue_two#", "#rogue_three#"],
|
||||
"rogue_context" : "You are <NAME>, a rogue #from_fantasy#. You have #rogue_item.a# and #rogue_item.a#."
|
||||
}
|
||||
|
108
story/story_data.yaml
Normal file
108
story/story_data.yaml
Normal file
|
@ -0,0 +1,108 @@
|
|||
settings:
|
||||
|
||||
fantasy:
|
||||
description: "living in the kingdom of Larion. "
|
||||
characters:
|
||||
|
||||
noble:
|
||||
prompts: ["You are awakened by one of your servants who tells you that your keep is under attack. You look out the window and see"]
|
||||
|
||||
item1: "pouch of gold"
|
||||
item2: "small dagger"
|
||||
|
||||
knight:
|
||||
prompts: ["You are on a quest to defeat the evil dragon of Larion. You've heard he lives up at the north of the kingdom. You set on the path to defeat him and walk into a dark forest. As you enter the forest you see"]
|
||||
|
||||
item1: "steel longsword"
|
||||
item2: "wooden shield"
|
||||
|
||||
wizard:
|
||||
prompts: ["You finish your long journey and finally arrive at the ruin you've been looking for. You look around and see"]
|
||||
|
||||
item1: "staff"
|
||||
item2: "spellbook"
|
||||
|
||||
peasant:
|
||||
prompts: ["You wake up and begin working in the fields. You see"]
|
||||
|
||||
item1: "pitchfork"
|
||||
item2: "nothing else"
|
||||
|
||||
rogue:
|
||||
prompts: ["You walk down the city street looking for somewhere to steal from. You look around and see"]
|
||||
|
||||
item1: "long steel dagger"
|
||||
item2: "length of rope"
|
||||
|
||||
apocalyptic:
|
||||
description: " trying to survive in a post apocalyptic world by scavenging among the ruins of what is left. "
|
||||
|
||||
characters:
|
||||
|
||||
scavenger:
|
||||
prompts: ["You walk for two hours and take a break. You've left your town in search of food. You look around and see "]
|
||||
|
||||
item1: "rusty knife"
|
||||
item2: "canteen"
|
||||
|
||||
mutant:
|
||||
prompts: ["In the colony you were born in, your strange condition was considered a curse, and you has been banished since you were sixteen. After a long journey, you find an abandoned bunker. You see"]
|
||||
|
||||
item1: "scales on your face"
|
||||
item2: "third leg"
|
||||
|
||||
headhunter:
|
||||
prompts: ["You are driving your rusty motorbike. You go past many abandoned bunkers. You arrive at a colony and stop the engine. You take a look around and see"]
|
||||
|
||||
item1: "binoculars"
|
||||
item2: "crappy shotgun"
|
||||
|
||||
mystery:
|
||||
description: "living in Chicago. "
|
||||
characters:
|
||||
|
||||
patient:
|
||||
prompts: ["You wake up in an old rundown hospital with no memory of how you got there. You take a look around the room and see"]
|
||||
|
||||
item1: "hospital bracelet"
|
||||
item2: "pack of bandages"
|
||||
|
||||
detective:
|
||||
prompts: ["You enter the forest where you believe the criminal you're searching for fled to. Suddenly"]
|
||||
|
||||
item1: "pistol"
|
||||
item2: "police badge"
|
||||
|
||||
spy:
|
||||
prompts: ["You listen to the Russian diplomats and hear them discussing"]
|
||||
|
||||
item1: "concealed pistol"
|
||||
item2: "syringe of poison"
|
||||
|
||||
zombies:
|
||||
description: " trying to survive in a world filled with infected zombies everywhere. "
|
||||
|
||||
characters:
|
||||
soldier:
|
||||
prompts: ["Your unit lost a lot of men when the infection broke, but you've managed to keep the small town
|
||||
you're stationed near safe for now. You look over the town and think"]
|
||||
|
||||
item1: "automatic rifle"
|
||||
item2: "grenade"
|
||||
|
||||
survivor:
|
||||
prompts: ["You have managed to survive several months avoiding zombies and scavenging food.
|
||||
You cautiously enter a rundown store and hear"]
|
||||
|
||||
item1: "pistol"
|
||||
item2: "backpack"
|
||||
|
||||
scientist:
|
||||
prompts: ["You pound your fist on the table, angry that you still haven't found the cure to the infection. You turn to your assistant and"]
|
||||
|
||||
item1: "backpack"
|
||||
item2: "solar powered tablet"
|
||||
|
||||
|
||||
|
||||
|
339
story/story_manager.py
Normal file
339
story/story_manager.py
Normal file
|
@ -0,0 +1,339 @@
|
|||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import uuid
|
||||
from subprocess import Popen
|
||||
|
||||
from story.utils import *
|
||||
|
||||
|
||||
class Story:
|
||||
def __init__(
|
||||
self, story_start, context="", seed=None, game_state=None, upload_story=False
|
||||
):
|
||||
self.story_start = story_start
|
||||
self.context = context
|
||||
self.rating = -1
|
||||
self.upload_story = upload_story
|
||||
|
||||
# list of actions. First action is the prompt length should always equal that of story blocks
|
||||
self.actions = []
|
||||
|
||||
# list of story blocks first story block follows prompt and is intro story
|
||||
self.results = []
|
||||
|
||||
# Only needed in constrained/cached version
|
||||
self.seed = seed
|
||||
self.choices = []
|
||||
self.possible_action_results = None
|
||||
self.uuid = None
|
||||
|
||||
if game_state is None:
|
||||
game_state = dict()
|
||||
self.game_state = game_state
|
||||
self.memory = 20
|
||||
|
||||
def __del__(self):
|
||||
if self.upload_story:
|
||||
self.save_to_storage()
|
||||
console_print("Game saved.")
|
||||
console_print(
|
||||
"To load the game, type 'load' and enter the following ID: " + self.uuid
|
||||
)
|
||||
|
||||
def init_from_dict(self, story_dict):
|
||||
self.story_start = story_dict["story_start"]
|
||||
self.seed = story_dict["seed"]
|
||||
self.actions = story_dict["actions"]
|
||||
self.results = story_dict["results"]
|
||||
self.choices = story_dict["choices"]
|
||||
self.possible_action_results = story_dict["possible_action_results"]
|
||||
self.game_state = story_dict["game_state"]
|
||||
self.context = story_dict["context"]
|
||||
self.uuid = story_dict["uuid"]
|
||||
|
||||
if "rating" in story_dict.keys():
|
||||
self.rating = story_dict["rating"]
|
||||
else:
|
||||
self.rating = -1
|
||||
|
||||
def initialize_from_json(self, json_string):
|
||||
story_dict = json.loads(json_string)
|
||||
self.init_from_dict(story_dict)
|
||||
|
||||
def add_to_story(self, action, story_block):
|
||||
self.actions.append(action)
|
||||
self.results.append(story_block)
|
||||
|
||||
def latest_result(self):
|
||||
|
||||
mem_ind = self.memory
|
||||
if len(self.results) < 2:
|
||||
latest_result = self.story_start
|
||||
else:
|
||||
latest_result = self.context
|
||||
while mem_ind > 0:
|
||||
|
||||
if len(self.results) >= mem_ind:
|
||||
latest_result += self.actions[-mem_ind] + self.results[-mem_ind]
|
||||
|
||||
mem_ind -= 1
|
||||
|
||||
return latest_result
|
||||
|
||||
def __str__(self):
|
||||
story_list = [self.story_start]
|
||||
for i in range(len(self.results)):
|
||||
story_list.append("\n" + self.actions[i] + "\n")
|
||||
story_list.append("\n" + self.results[i])
|
||||
|
||||
return "".join(story_list)
|
||||
|
||||
def to_json(self):
|
||||
story_dict = {}
|
||||
story_dict["story_start"] = self.story_start
|
||||
story_dict["seed"] = self.seed
|
||||
story_dict["actions"] = self.actions
|
||||
story_dict["results"] = self.results
|
||||
story_dict["choices"] = self.choices
|
||||
story_dict["possible_action_results"] = self.possible_action_results
|
||||
story_dict["game_state"] = self.game_state
|
||||
story_dict["context"] = self.context
|
||||
story_dict["uuid"] = self.uuid
|
||||
story_dict["rating"] = self.rating
|
||||
|
||||
return json.dumps(story_dict)
|
||||
|
||||
def save_to_storage(self):
|
||||
print("Saving to storage has been disabled due to abuse of the cloud bucket. Save will now be stored locally.")
|
||||
|
||||
self.uuid = str(uuid.uuid1())
|
||||
|
||||
save_path = "./saved_stories/"
|
||||
|
||||
if not os.path.exists(save_path):
|
||||
os.makedirs(save_path)
|
||||
|
||||
story_json = self.to_json()
|
||||
file_name = "story" + str(self.uuid) + ".json"
|
||||
f = open(os.path.join(save_path, file_name), "w")
|
||||
f.write(story_json)
|
||||
f.close()
|
||||
return self.uuid
|
||||
|
||||
def load_from_storage(self, story_id):
|
||||
save_path = "./saved_stories/"
|
||||
|
||||
if not os.path.exists(save_path):
|
||||
return "Error save not found."
|
||||
|
||||
file_name = "story" + story_id + ".json"
|
||||
exists = os.path.isfile(os.path.join(save_path, file_name))
|
||||
if exists:
|
||||
with open(os.path.join(save_path, file_name), "r") as fp:
|
||||
game = json.load(fp)
|
||||
self.init_from_dict(game)
|
||||
return str(self)
|
||||
else:
|
||||
print("Save not found locally. Trying in the cloud bucket (only valid for saves before Dec 24 2019)")
|
||||
cmd = "gsutil cp gs://aidungeonstories/" + file_name + " " + save_path
|
||||
os.system(cmd)
|
||||
exists = os.path.isfile(os.path.join(save_path, file_name))
|
||||
|
||||
|
||||
if exists:
|
||||
with open(os.path.join(save_path, file_name), "r") as fp:
|
||||
game = json.load(fp)
|
||||
self.init_from_dict(game)
|
||||
return str(self)
|
||||
else:
|
||||
return "Error save not found locally or in the cloud."
|
||||
|
||||
def get_rating(self):
|
||||
while True:
|
||||
try:
|
||||
rating = input("Please rate the story quality from 1-10: ")
|
||||
rating_float = max(min(float(rating), 10), 1)
|
||||
except ValueError:
|
||||
print("Please return a valid number.")
|
||||
else:
|
||||
self.rating = rating_float
|
||||
return
|
||||
|
||||
|
||||
class StoryManager:
|
||||
def __init__(self, generator):
|
||||
self.generator = generator
|
||||
self.story = None
|
||||
|
||||
def start_new_story(
|
||||
self, story_prompt, context="", game_state=None, upload_story=False
|
||||
):
|
||||
block = self.generator.generate(context + story_prompt)
|
||||
block = cut_trailing_sentence(block)
|
||||
self.story = Story(
|
||||
context + story_prompt + block,
|
||||
context=context,
|
||||
game_state=game_state,
|
||||
upload_story=upload_story,
|
||||
)
|
||||
return str(self.story)
|
||||
|
||||
def load_new_story(self, story_id, upload_story=False):
|
||||
save_path = "./saved_stories/"
|
||||
file_name = "story" + story_id + ".json"
|
||||
exists = os.path.isfile(os.path.join(save_path, file_name))
|
||||
|
||||
if not exists:
|
||||
print("Save not found locally. Trying in the cloud bucket (only valid for saves before Dec 24 2019)")
|
||||
cmd = "gsutil cp gs://aidungeonstories/" + file_name + " " + save_path
|
||||
os.system(cmd)
|
||||
exists = os.path.isfile(os.path.join(save_path, file_name))
|
||||
|
||||
if not exists:
|
||||
return "Error save not found locally or on the cloud."
|
||||
|
||||
with open(os.path.join(save_path, file_name), "r") as fp:
|
||||
game = json.load(fp)
|
||||
self.story = Story("", upload_story=upload_story)
|
||||
self.story.init_from_dict(game)
|
||||
return str(self.story)
|
||||
|
||||
def load_story(self, story, from_json=False):
|
||||
if from_json:
|
||||
self.story = Story("")
|
||||
self.story.initialize_from_json(story)
|
||||
else:
|
||||
self.story = story
|
||||
return str(story)
|
||||
|
||||
def json_story(self):
|
||||
return self.story.to_json()
|
||||
|
||||
def story_context(self):
|
||||
return self.story.latest_result()
|
||||
|
||||
|
||||
class UnconstrainedStoryManager(StoryManager):
|
||||
def act(self, action_choice):
|
||||
|
||||
result = self.generate_result(action_choice)
|
||||
self.story.add_to_story(action_choice, result)
|
||||
return result
|
||||
|
||||
def generate_result(self, action):
|
||||
block = self.generator.generate(self.story_context() + action)
|
||||
return block
|
||||
|
||||
|
||||
class ConstrainedStoryManager(StoryManager):
|
||||
def __init__(self, generator, action_verbs_key="classic"):
|
||||
super().__init__(generator)
|
||||
self.action_phrases = get_action_verbs(action_verbs_key)
|
||||
self.cache = False
|
||||
self.cacher = None
|
||||
self.seed = None
|
||||
|
||||
def enable_caching(
|
||||
self, credentials_file=None, seed=0, bucket_name="dungeon-cache"
|
||||
):
|
||||
self.cache = True
|
||||
self.cacher = Cacher(credentials_file, bucket_name)
|
||||
self.seed = seed
|
||||
|
||||
def start_new_story(self, story_prompt, context="", game_state=None):
|
||||
if self.cache:
|
||||
return self.start_new_story_cache(story_prompt, game_state=game_state)
|
||||
else:
|
||||
return super().start_new_story(
|
||||
story_prompt, context=context, game_state=game_state
|
||||
)
|
||||
|
||||
def start_new_story_generate(self, story_prompt, game_state=None):
|
||||
super().start_new_story(story_prompt, game_state=game_state)
|
||||
self.story.possible_action_results = self.get_action_results()
|
||||
return self.story.story_start
|
||||
|
||||
def start_new_story_cache(self, story_prompt, game_state=None):
|
||||
|
||||
response = self.cacher.retrieve_from_cache(self.seed, [], "story")
|
||||
if response is not None:
|
||||
story_start = story_prompt + response
|
||||
self.story = Story(story_start, seed=self.seed)
|
||||
self.story.possible_action_results = self.get_action_results()
|
||||
else:
|
||||
story_start = self.start_new_story_generate(
|
||||
story_prompt, game_state=game_state
|
||||
)
|
||||
self.story.seed = self.seed
|
||||
self.cacher.cache_file(self.seed, [], story_start, "story")
|
||||
|
||||
return story_start
|
||||
|
||||
def load_story(self, story, from_json=False):
|
||||
story_string = super().load_story(story, from_json=from_json)
|
||||
return story_string
|
||||
|
||||
def get_possible_actions(self):
|
||||
if self.story.possible_action_results is None:
|
||||
self.story.possible_action_results = self.get_action_results()
|
||||
|
||||
return [
|
||||
action_result[0] for action_result in self.story.possible_action_results
|
||||
]
|
||||
|
||||
def act(self, action_choice_str):
|
||||
|
||||
try:
|
||||
action_choice = int(action_choice_str)
|
||||
except:
|
||||
print("Error invalid choice.")
|
||||
return None, None
|
||||
|
||||
if action_choice < 0 or action_choice >= len(self.action_phrases):
|
||||
print("Error invalid choice.")
|
||||
return None, None
|
||||
|
||||
self.story.choices.append(action_choice)
|
||||
action, result = self.story.possible_action_results[action_choice]
|
||||
self.story.add_to_story(action, result)
|
||||
self.story.possible_action_results = self.get_action_results()
|
||||
return result, self.get_possible_actions()
|
||||
|
||||
def get_action_results(self):
|
||||
if self.cache:
|
||||
return self.get_action_results_cache()
|
||||
else:
|
||||
return self.get_action_results_generate()
|
||||
|
||||
def get_action_results_generate(self):
|
||||
action_results = [
|
||||
self.generate_action_result(self.story_context(), phrase)
|
||||
for phrase in self.action_phrases
|
||||
]
|
||||
return action_results
|
||||
|
||||
def get_action_results_cache(self):
|
||||
response = self.cacher.retrieve_from_cache(
|
||||
self.story.seed, self.story.choices, "choices"
|
||||
)
|
||||
|
||||
if response is not None:
|
||||
print("Retrieved from cache")
|
||||
return json.loads(response)
|
||||
else:
|
||||
print("Didn't receive from cache")
|
||||
action_results = self.get_action_results_generate()
|
||||
response = json.dumps(action_results)
|
||||
self.cacher.cache_file(
|
||||
self.story.seed, self.story.choices, response, "choices"
|
||||
)
|
||||
return action_results
|
||||
|
||||
def generate_action_result(self, prompt, phrase, options=None):
|
||||
|
||||
action_result = (
|
||||
phrase + " " + self.generator.generate(prompt + " " + phrase, options)
|
||||
)
|
||||
action, result = split_first_sentence(action_result)
|
||||
return action, result
|
292
story/utils.py
Normal file
292
story/utils.py
Normal file
|
@ -0,0 +1,292 @@
|
|||
# coding: utf-8
|
||||
import re
|
||||
from difflib import SequenceMatcher
|
||||
|
||||
import yaml
|
||||
from profanityfilter import ProfanityFilter
|
||||
|
||||
YAML_FILE = "story/story_data.yaml"
|
||||
|
||||
|
||||
with open("story/censored_words.txt", "r") as f:
|
||||
censored_words = [l.replace("\n", "") for l in f.readlines()]
|
||||
|
||||
pf = ProfanityFilter(custom_censor_list=censored_words)
|
||||
|
||||
|
||||
def console_print(text, width=75):
|
||||
last_newline = 0
|
||||
i = 0
|
||||
while i < len(text):
|
||||
if text[i] == "\n":
|
||||
last_newline = 0
|
||||
elif last_newline > width and text[i] == " ":
|
||||
text = text[:i] + "\n" + text[i:]
|
||||
last_newline = 0
|
||||
else:
|
||||
last_newline += 1
|
||||
i += 1
|
||||
print(text)
|
||||
|
||||
|
||||
def get_similarity(a, b):
|
||||
return SequenceMatcher(None, a, b).ratio()
|
||||
|
||||
|
||||
def get_num_options(num):
|
||||
|
||||
while True:
|
||||
choice = input("Enter the number of your choice: ")
|
||||
try:
|
||||
result = int(choice)
|
||||
if result >= 0 and result < num:
|
||||
return result
|
||||
else:
|
||||
print("Error invalid choice. ")
|
||||
except ValueError:
|
||||
print("Error invalid choice. ")
|
||||
|
||||
|
||||
def player_died(text):
|
||||
"""
|
||||
TODO: Add in more sophisticated NLP, maybe a custom classifier
|
||||
trained on hand-labelled data that classifies second-person
|
||||
statements as resulting in death or not.
|
||||
"""
|
||||
lower_text = text.lower()
|
||||
you_dead_regexps = [
|
||||
"you('re| are) (dead|killed|slain|no more|nonexistent)",
|
||||
"you (die|pass away|perish|suffocate|drown|bleed out)",
|
||||
"you('ve| have) (died|perished|suffocated|drowned|been (killed|slain))",
|
||||
"you (\w* )?(yourself )?to death",
|
||||
"you (\w* )*(collapse|bleed out|chok(e|ed|ing)|drown|dissolve) (\w* )*and (die(|d)|pass away|cease to exist|(\w* )+killed)",
|
||||
]
|
||||
return any(re.search(regexp, lower_text) for regexp in you_dead_regexps)
|
||||
|
||||
|
||||
def player_won(text):
|
||||
lower_text = text.lower()
|
||||
won_phrases = [
|
||||
"you ((\w* )*and |)live happily ever after",
|
||||
"you ((\w* )*and |)live (forever|eternally|for eternity)",
|
||||
"you ((\w* )*and |)(are|become|turn into) ((a|now) )?(deity|god|immortal)",
|
||||
"you ((\w* )*and |)((go|get) (in)?to|arrive (at|in)) (heaven|paradise)",
|
||||
"you ((\w* )*and |)celebrate your (victory|triumph)",
|
||||
"you ((\w* )*and |)retire",
|
||||
"The rest is history...",
|
||||
]
|
||||
return any(re.search(regexp, lower_text) for regexp in won_phrases)
|
||||
|
||||
|
||||
def remove_profanity(text):
|
||||
return pf.censor(text)
|
||||
|
||||
|
||||
def cut_trailing_quotes(text):
|
||||
num_quotes = text.count('"')
|
||||
if num_quotes % 2 is 0:
|
||||
return text
|
||||
else:
|
||||
final_ind = text.rfind('"')
|
||||
return text[:final_ind]
|
||||
|
||||
|
||||
def split_first_sentence(text):
|
||||
first_period = text.find(".")
|
||||
first_exclamation = text.find("!")
|
||||
|
||||
if first_exclamation < first_period and first_exclamation > 0:
|
||||
split_point = first_exclamation + 1
|
||||
elif first_period > 0:
|
||||
split_point = first_period + 1
|
||||
else:
|
||||
split_point = text[0:20]
|
||||
|
||||
return text[0:split_point], text[split_point:]
|
||||
|
||||
|
||||
def cut_trailing_action(text):
|
||||
lines = text.split("\n")
|
||||
last_line = lines[-1]
|
||||
if (
|
||||
"you ask" in last_line
|
||||
or "You ask" in last_line
|
||||
or "you say" in last_line
|
||||
or "You say" in last_line
|
||||
) and len(lines) > 1:
|
||||
text = "\n".join(lines[0:-1])
|
||||
return text
|
||||
|
||||
|
||||
def cut_trailing_sentence(text):
|
||||
text = standardize_punctuation(text)
|
||||
last_punc = max(text.rfind("."), text.rfind("!"), text.rfind("?"))
|
||||
if last_punc <= 0:
|
||||
last_punc = len(text) - 1
|
||||
|
||||
et_token = text.find("<")
|
||||
if et_token > 0:
|
||||
last_punc = min(last_punc, et_token - 1)
|
||||
|
||||
act_token = text.find(">")
|
||||
if act_token > 0:
|
||||
last_punc = min(last_punc, act_token - 1)
|
||||
|
||||
text = text[:last_punc+1]
|
||||
|
||||
text = cut_trailing_quotes(text)
|
||||
text = cut_trailing_action(text)
|
||||
return text
|
||||
|
||||
|
||||
def replace_outside_quotes(text, current_word, repl_word):
|
||||
text = standardize_punctuation(text)
|
||||
|
||||
reg_expr = re.compile(current_word + '(?=([^"]*"[^"]*")*[^"]*$)')
|
||||
|
||||
output = reg_expr.sub(repl_word, text)
|
||||
return output
|
||||
|
||||
|
||||
def is_first_person(text):
|
||||
|
||||
count = 0
|
||||
for pair in first_to_second_mappings:
|
||||
variations = mapping_variation_pairs(pair)
|
||||
for variation in variations:
|
||||
reg_expr = re.compile(variation[0] + '(?=([^"]*"[^"]*")*[^"]*$)')
|
||||
matches = re.findall(reg_expr, text)
|
||||
count += len(matches)
|
||||
|
||||
if count > 3:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def is_second_person(text):
|
||||
count = 0
|
||||
for pair in second_to_first_mappings:
|
||||
variations = mapping_variation_pairs(pair)
|
||||
for variation in variations:
|
||||
reg_expr = re.compile(variation[0] + '(?=([^"]*"[^"]*")*[^"]*$)')
|
||||
matches = re.findall(reg_expr, text)
|
||||
count += len(matches)
|
||||
|
||||
if count > 3:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def capitalize(word):
|
||||
return word[0].upper() + word[1:]
|
||||
|
||||
|
||||
def mapping_variation_pairs(mapping):
|
||||
mapping_list = []
|
||||
mapping_list.append((" " + mapping[0] + " ", " " + mapping[1] + " "))
|
||||
mapping_list.append(
|
||||
(" " + capitalize(mapping[0]) + " ", " " + capitalize(mapping[1]) + " ")
|
||||
)
|
||||
|
||||
# Change you it's before a punctuation
|
||||
if mapping[0] is "you":
|
||||
mapping = ("you", "me")
|
||||
mapping_list.append((" " + mapping[0] + ",", " " + mapping[1] + ","))
|
||||
mapping_list.append((" " + mapping[0] + "\?", " " + mapping[1] + "\?"))
|
||||
mapping_list.append((" " + mapping[0] + "\!", " " + mapping[1] + "\!"))
|
||||
mapping_list.append((" " + mapping[0] + "\.", " " + mapping[1] + "."))
|
||||
|
||||
return mapping_list
|
||||
|
||||
|
||||
first_to_second_mappings = [
|
||||
("I'm", "you're"),
|
||||
("Im", "you're"),
|
||||
("Ive", "you've"),
|
||||
("I am", "you are"),
|
||||
("was I", "were you"),
|
||||
("am I", "are you"),
|
||||
("wasn't I", "weren't you"),
|
||||
("I", "you"),
|
||||
("I'd", "you'd"),
|
||||
("i", "you"),
|
||||
("I've", "you've"),
|
||||
("was I", "were you"),
|
||||
("am I", "are you"),
|
||||
("wasn't I", "weren't you"),
|
||||
("I", "you"),
|
||||
("I'd", "you'd"),
|
||||
("i", "you"),
|
||||
("I've", "you've"),
|
||||
("I was", "you were"),
|
||||
("my", "your"),
|
||||
("we", "you"),
|
||||
("we're", "you're"),
|
||||
("mine", "yours"),
|
||||
("me", "you"),
|
||||
("us", "you"),
|
||||
("our", "your"),
|
||||
("I'll", "you'll"),
|
||||
("myself", "yourself"),
|
||||
]
|
||||
|
||||
second_to_first_mappings = [
|
||||
("you're", "I'm"),
|
||||
("your", "my"),
|
||||
("you are", "I am"),
|
||||
("you were", "I was"),
|
||||
("are you", "am I"),
|
||||
("you", "I"),
|
||||
("you", "me"),
|
||||
("you'll", "I'll"),
|
||||
("yourself", "myself"),
|
||||
("you've", "I've"),
|
||||
]
|
||||
|
||||
|
||||
def capitalize_helper(string):
|
||||
string_list = list(string)
|
||||
string_list[0] = string_list[0].upper()
|
||||
return "".join(string_list)
|
||||
|
||||
|
||||
def capitalize_first_letters(text):
|
||||
first_letters_regex = re.compile(r"((?<=[\.\?!]\s)(\w+)|(^\w+))")
|
||||
|
||||
def cap(match):
|
||||
return capitalize_helper(match.group())
|
||||
|
||||
result = first_letters_regex.sub(cap, text)
|
||||
return result
|
||||
|
||||
|
||||
def standardize_punctuation(text):
|
||||
text = text.replace("’", "'")
|
||||
text = text.replace("`", "'")
|
||||
text = text.replace("“", '"')
|
||||
text = text.replace("”", '"')
|
||||
return text
|
||||
|
||||
|
||||
def first_to_second_person(text):
|
||||
text = " " + text
|
||||
text = standardize_punctuation(text)
|
||||
for pair in first_to_second_mappings:
|
||||
variations = mapping_variation_pairs(pair)
|
||||
for variation in variations:
|
||||
text = replace_outside_quotes(text, variation[0], variation[1])
|
||||
|
||||
return capitalize_first_letters(text[1:])
|
||||
|
||||
|
||||
def second_to_first_person(text):
|
||||
text = " " + text
|
||||
text = standardize_punctuation(text)
|
||||
for pair in second_to_first_mappings:
|
||||
variations = mapping_variation_pairs(pair)
|
||||
for variation in variations:
|
||||
text = replace_outside_quotes(text, variation[0], variation[1])
|
||||
|
||||
return capitalize_first_letters(text[1:])
|
Reference in a new issue