import random as r import argparse import sys import adversaries import gear beg = ["a","e","i","o","u","ba","be","bi","bo","bu","by","y","da","de","di","do","du","dy","fa","fi","fo","fe","fu","ga","ge","gi","go","gu","ka","ke","ki","ko","ku","ky","ma","me","mi","mo","mu","na","ne","ni","no","nu","pa","pe","pi","po","pu","ra","re","ri","ro","ru","ry","sa","se","si","so","su","ta","te","ti","to","tu","ty","wa","we","wi","wo","wy","za","ze","zi","zo","zu","zy"] mid = beg + ["l","x","n","r"] def binarize(num, l=None): r = bin(num)[2:] try: l = int(l) except: l = None if l != None: while len(r) < l: r = "0" + r return r def gen_name(length=None, minimum=3): maximum = 8 if length == None: lgt = r.randint(minimum,maximum) else: if length > maximum: length = maximum print("Maximum name length is 8.") lgt = length morae = [] while len("".join(morae)) < lgt: if len(morae) == 0: mora = r.choice(beg) morae.append(mora[0].upper() + mora[1:]) else: mora = r.choice(mid) if morae[-1] == mora: mora = r.choice(mid) morae.append(mora) fname = "".join(morae)[:lgt] return fname class Plot: loc1 = ["friendly","hostile","derelict","airless","poison-filled/covered","overgrown","looted","burning","frozen","haunted","infested"] loc2 = ["asteroid","moon","space station","spaceship","ringworld","Dyson sphere","planet","Space Whale","pocket of folded space","time vortex","Reroll"] miss = ["explore","loot everything not bolted down too securely","find the last group of kobolds who came here","find a rumored secret weapon","find a way to break someone else's secret weapon","claim this place in the name of the Kobold Empire","make friends","rediscover lost technology","find lost magical items","find and defeat a powerful enemy"] prob = adversaries.prob def __init__(self, loc_desc=None, locIndex=None, battlefield=None, location=None, missIndex=None, oops=None, mission=None, probIndex=None, problem=None, probName=None, secProblem=None, thirdProblem=None): self.loc_desc = loc_desc if loc_desc != None else Plot.loc1[r.randint(0, len(Plot.loc1)-1)] self.locIndex = int(locIndex) if locIndex != None else r.randint(0, len(Plot.loc2)-1) self.battlefield = int(battlefield) if battlefield != None else 0 self.location = location if location != None else Plot.loc2[self.locIndex] if locIndex == None and self.locIndex == len(Plot.loc2) - 2: if self.battlefield == 0: self.battlefield = 1 self.locIndex = r.randint(0, len(Plot.loc2)-3) elif locIndex == None and self.locIndex != len(Plot.loc2) - 1: if self.location == "": self.location = Plot.loc2[self.locIndex] if self.location[0].lower() in ["a","e","i","o","u"]: self.locart = 1 else: self.locart = 0 self.missIndex = missIndex if missIndex != None else r.randint(0, len(Plot.miss)-1) self.oops = int(oops) if oops != None else r.randint(1,12) if self.oops != 1: self.oops = 0 self.mission = Plot.miss[self.missIndex] self.probIndex = probIndex if probIndex != None else r.randint(0, len(Plot.prob)-1) self.problem = Plot.prob[self.probIndex] if type(self.problem["name"]) != str: self.problem["name"] = self.problem["name"]() if type(self.problem["note"]) != str: self.problem["note"] = self.problem["note"]() if self.problem["hasMinion"]: if secProblem != None: try: self.secProblem = Plot.prob[secProblem] except: self.secProblem = Plot.prob[r.choice(self.problem["potentialMinions"])] else: self.secProblem = Plot.prob[r.choice(self.problem["potentialMinions"])] if type(self.secProblem["name"]) != str: self.secProblem["name"] = self.secProblem["name"]() if type(self.secProblem["note"]) != str: self.secProblem["note"] = self.secProblem["note"]() self.fullProblem = "" if self.problem["needsName"]: self.problem["givenname"] = probName if probName != None else gen_name() self.fullProblem += self.problem["givenname"] + ", " if not self.problem["isPlural"] and self.problem["name"].split(" ")[0] != "Old": if self.problem["name"][0].lower() in ["a","e","i","o","u"]: self.fullProblem += "an " else: self.fullProblem += "a " self.fullProblem += self.problem["name"] if self.problem["hasMinion"]: self.fullProblem += " and their minion, " # if self.secProblem["name"][0].lower() in ["a","e","i","o","u"]: # self.fullProblem += "an " # else: # self.fullProblem += "a " self.fullProblem += self.secProblem["name"] class Character: # Remember to update gen_gadget() when you add gadgets GADGETS = gear.gadgets # Remember to update gen_career() when you add careers CAREERS = [ {"id": 0, "name": "Soldier/Guard"}, {"id": 1, "name": "Pilot"}, {"id": 2, "name": "Medic"}, {"id": 3, "name": "Mechanic"}, {"id": 4, "name": "Politician"}, {"id": 5, "name": "Spellcaster"}, {"id": 6, "name": "Performer"}, {"id": 7, "name": "Historian"}, {"id": 8, "name": "Spy"}, {"id": 9, "name": "Cook"}, {"id": 10, "name": "Cartographer"}, {"id": 11, "name": "Inventor"}, {"id": 12, "name": "Merchant"}, {"id": 13, "name": "Bard"}, {"id": 14, "name": "Sorcerer"}, {"id": 15, "name": "Cleric"}, {"id": 16, "name": "Rogue"}, {"id": 17, "name": "Ranger"}, {"id": 18, "name": "Barbarian"}, {"id": 19, "name": "Artificer"}, {"id": 20, "name": "Druid"}, {"id": 21, "name": "Wizard"}, {"id": 22, "name": "Fighter"}, {"id": 23, "name": "Monk"}, {"id": 24, "name": "Paladin"}, {"id": 25, "name": "Warlock"}, {"id": 26, "name": "Blood Hunter"} ] def __init__(self, name=None, career=None, stats=None, gadget=None): self.name = name if name != None else "" if career == None: self.career = "" elif isinstance(career, str): self.career = career elif isinstance(career, int) and career in range(27): self.career = [x for x in Character.CAREERS if x["id"] == career][0] else: self.career = "" self.stats = stats if stats != None else [] if gadget == None: self.gadget = "" elif isinstance(gadget, str) or isinstance(gadget, dict): self.gadget = gadget if type(self.gadget["description"]) != str: self.gadget["description"] = self.gadget["description"]() else: self.gadget = next((x for x in Character.GADGETS if x["id"] == gadget), "") if type(self.gadget["description"]) != str: self.gadget["description"] = self.gadget["description"]() self.generate() def generate(self): if self.name == "" or self.name == None: self.gen_name() if self.stats == [] or self.stats == None: self.gen_stats() if self.career == "" or self.career == None: self.gen_career() if self.gadget == "" or self.gadget == None: self.gen_gadget() def gen_name(self): self.name = gen_name() def gen_stats(self, n=12): if n < 0: print("Too few stat points!") return [0,0,0,0] stats = [0,0,0,0] points = n slots = [0,1,2,3] for _ in range(points): tgl = False while tgl == False: slt = r.choice(slots) if slt <= 1: if stats[slt] == 6: continue if stats[slt] == 5 and r.randint(0,1) != 1: continue else: if stats[slt] == 6: continue if stats[slt] > 2 and r.randint(0,stats[slt]-2) != 1: continue stats[slt] += 1 tgl = True stats[3] = stats[3] + 1 if stats[3] > 6: stats[3] = 6 stats[2] = stats[2] + 1 if stats[2] > 6: stats[2] = 6 self.stats = stats def gen_career(self): cid = r.randint(0,26) self.career = next((x for x in Character.CAREERS if x["id"] == cid), "") def gen_gadget(self): gid = r.randint(0,36) self.gadget = [x for x in Character.GADGETS if x["id"] == gid][0] if type(self.gadget["description"]) != str: self.gadget["description"] = self.gadget["description"]() def print_name(self, html=False): if isinstance(self.career, str): cname = self.career cid = next((x for x in Character.CAREERS if x["name"] == cname), "") else: cname = self.career["name"] c = dict(next((x for x in Character.CAREERS if x["name"] == cname), "")) cid = c["id"] if html: charText = f"

Name: {self.name} (Kobold {cname})

" else: charText = f"\nName: {self.name} (Kobold {cname} {cid})" print(charText) def print(self, html=False): if html: if isinstance(self.career, str): cname = self.career else: cname = self.career["name"] if isinstance(self.gadget, str): gdg = {"id": 127, "name": self.gadget, "description": "", "reusable": True} else: gdg = self.gadget out = ( f"
\n" f" \n" f" {self.name}
\n" f" Kobold {cname}\n" f"
\n" f"
\n" f" \n" f" \n" f" \n" f"
\n" f" \n" f" {gdg['name']}
\n" f" {gdg['description']}\n" f" {'
Reusable' if gdg['reusable'] else ''}
\n" f"
" f"
\n" ) print(out) else: self.print_name() print(f"Order: {self.stats[0]}") print(f"Chaos: {self.stats[1]}") print(f"Brain: {self.stats[2]}") print(f"Body: {self.stats[3]}") if isinstance(self.gadget, str): print(f"Gadget: {self.gadget}") else: print(f"Gadget: {self.gadget['name']} ({self.gadget['description']}{'- Reusable' if self.gadget['reusable'] else ''})") class Ship: NAME1 = ["Red","Orange","Yellow","Green","Blue","Violet","Dark","Light","Frenzied","Maniacal","Ancient"] NAME2 = ["Moon","Comet","Star","Saber","World-Eater","Dancer","Looter","Phlogiston","Fireball","Mecha","Raptor"] GQUAL = ["is stealthy & unarmored","is speedy & unarmored","is maneuverable & unarmored","is always repairable","is self-repairing","is flamboyant & speedy","is slow & armored","is flamboyant & armored","is hard to maneuver & armored","has Too Many Weapons!","has a prototype hyperdrive"] BQUAL = ["has an annoying AI","has inconveniently crossed circuits","has an unpredictable power source","drifts to the right","is haunted","was recently 'found' so the kobolds are unused to it","is too cold","has a constant odd smell","its interior design... changes","its water pressure shifts between slow drip and power wash","it leaves a visible smoke trail"] def __init__(self, name1=None, name2=None, gqual = None, bqual = None): self.name1 = name1 if name1 != None else r.choice(Ship.NAME1) self.name2 = name2 if name2 != None else r.choice(Ship.NAME2) self.gqual = gqual if gqual != None else r.choice(Ship.GQUAL) self.bqual = bqual if bqual != None else r.choice(Ship.BQUAL) self.fullname = f"{self.name1} {self.name2}" def print(self, html=False): if (html): shipText = f"

The {self.fullname} {self.gqual}, but {self.bqual}.

\n" else: shipText = f"The {self.fullname} {self.gqual}, but {self.bqual}.\n" print(shipText) class Campaign: ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz?- " NAMELETS = ['a', 'e', 'i', 'o', 'u', 'b', 'y', 'd', 'f', 'g', 'k', 'm', 'n', 'p', 'r', 's', 't', 'w', 'z', 'l', 'x'] def __init__(self, n=None, makeChars=True, fromPW=False, pw=None): if fromPW == True: self.ship = None self.params = None self.characters = None self.art = None self.masterpassword = pw self.decode_key(pw) else: self.masterpassword = None self.create_campaign(n, makeChars) def create_campaign(self, n=None, makeChars=True): n = 6 if n == None else n self.ship = Ship() self.params = Plot() self.params.problem["fullname"] = "" # if self.params.problem["id"] in [1,2]: # self.params.problem["fullname"] += " led by " + self.params.problem["name"] # if self.params.problem["id"] in [4,7,8,10]: # self.params.problem["fullname"] += " named " + self.params.problem["name"] if makeChars: self.characters = [] for _ in range(n): c = Character() c.generate() self.characters.append(c) self.art = "an" if self.params.loc_desc[0] in ["a","e","i","o","u"] else "a" def generate_key(self): """ "PACKTA CTICS! ------- ------- ------- ------- ------- ------- ------- ------- ------- ------- ------- -------" should generate the Season 3 Pack Tactics crew. "JUSTIN BAILEY" and "NARPAS SWORD" should do something too. Key is analphanumeric string generated from a bitfield Bitfield is: Location 1: 7 bits Location 2: 7 bits Location Battlefield: 1 bit Mission: 7 bits Oops: 1 bit Problem 1: 7 bits Problem 1 name: 40 bits Problem 2: 7 bits Ship name 1: 7 bits Ship name 2: 7 bits Ship gqual: 7 bits Ship bqual: 7 bits Character 1 name: 40 bits Character 1 career: 7 bits Character 1 order: 3 bits Character 1 chaos: 3 bits Character 1 body: 3 bits Character 1 brain: 3 bits Character 1 gadget: 7 bits Character 2 name: 40 bits Character 2 career: 7 bits Character 2 order: 3 bits Character 2 chaos: 3 bits Character 2 body: 3 bits Character 2 brain: 3 bits Character 2 gadget: 7 bits Character 3 name: 40 bits Character 3 career: 7 bits Character 3 order: 3 bits Character 3 chaos: 3 bits Character 3 body: 3 bits Character 3 brain: 3 bits Character 3 gadget: 7 bits Character 4 name: 40 bits Character 4 career: 7 bits Character 4 order: 3 bits Character 4 chaos: 3 bits Character 4 body: 3 bits Character 4 brain: 3 bits Character 4 gadget: 7 bits Character 5 name: 40 bits Character 5 career: 7 bits Character 5 order: 3 bits Character 5 chaos: 3 bits Character 5 body: 3 bits Character 5 brain: 3 bits Character 5 gadget: 7 bits Character 6 name: 40 bits Character 6 career: 7 bits Character 6 order: 3 bits Character 6 chaos: 3 bits Character 6 body: 3 bits Character 6 brain: 3 bits Character 6 gadget: 7 bits 104 for campaign 396 for characters total 501 11 remaining """ self.key = "" l1 = bin(Plot.loc1.index(self.params.loc_desc))[2:] l2 = bin(Plot.loc2.index(self.params.location))[2:] lb = bin(self.params.battlefield)[2:] op = bin(self.params.oops)[2:] ms = bin(self.params.missIndex)[2:] pb1 = bin(self.params.probIndex)[2:] if self.params.problem["hasMinion"]: pb2 = bin(self.params.secProblem["id"])[2:] else: pb2 = bin(127)[2:] if self.params.problem["needsName"]: pbname = self.encode_name(self.params.problem["givenname"]) else: pbname = self.encode_name("yyyyyyyy") n1 = bin(Ship.NAME1.index(self.ship.name1))[2:] n2 = bin(Ship.NAME2.index(self.ship.name2))[2:] gq = bin(Ship.GQUAL.index(self.ship.gqual))[2:] bq = bin(Ship.BQUAL.index(self.ship.bqual))[2:] chars = {} i = 0 for chct in self.characters: chars[i] = { "name": self.encode_name(chct.name), "career": bin(chct.career["id"])[2:], "order": bin(chct.stats[0])[2:], "chaos": bin(chct.stats[1])[2:], "body": bin(chct.stats[2])[2:], "brains": bin(chct.stats[3])[2:], "gadget": bin(chct.gadget["id"])[2:] } i += 1 l1 = lpad(l1, 7) l2 = lpad(l2, 7) ms = lpad(ms, 7) pb1 = lpad(pb1, 7) pb2 = lpad(pb2, 7) pbname = lpad(pbname, 40, "1") n1 = lpad(n1, 7) n2 = lpad(n2, 7) gq = lpad(gq, 7) bq = lpad(bq, 7) self.key += l1 + l2 + lb + ms + op + pb1 + pbname + pb2 + n1 + n2 + gq + bq for k,chct in chars.items(): chct["name"] = lpad(chct["name"], 40, "1") chct["career"] = lpad(chct["career"], 7) chct["order"] = lpad(chct["order"],3) chct["chaos"] = lpad(chct["chaos"], 3) chct["body"] = lpad(chct["body"], 3) chct["brains"] = lpad(chct["brains"], 3) chct["gadget"] = lpad(chct["gadget"], 7) self.key += chct["name"] + chct["career"] + chct["order"] + chct["chaos"] + chct["body"] + chct["brains"] + chct["gadget"] while len(self.key) < 509: self.key = self.key + "0" letters = [] letter = [] for bit in self.key: letter.append(bit) if len(letter) == 6: letters.append(Campaign.ALPHABET[int("".join(letter),2)]) letter = [] words = [] word = [] for lt in letters: word.append(lt) if len(word) == 6: words.append("".join(word)) word = [] words.append("".join(word)) self.password = " ".join(words) return self.password def decode_key(self, pw): densePwd = pw.replace(" ", "") aBuiltin = densePwd[:12].upper() builtins = ["PACKTACTICS!", "JUSTINBAILEY", "NARPASSWORD", "PACKTACTICS1", "PACKTACTICS2", "PACKTACTICS3", "OHNOITSPEV!!"] if len(densePwd) != 84 and (aBuiltin not in builtins): print("This password is not valid. If this is a password that this generator created, please email noelle@noelle.codes and let me know.") sys.exit(0) if aBuiltin in builtins: if aBuiltin == "PACKTACTICS!" or aBuiltin == "PACKTACTICS3": # Create a campaign featuring the Season 3 Pack Tactics crew. self.ship = Ship("Red", "Star", "is maneuverable & unarmored", "has a politician who thinks they're in charge of it") self.params = Plot() self.art = "an" if self.params.loc_desc[0] in ["a","e","i","o","u"] else "a" self.characters = [] self.characters.append(Character("Niwri", 17, [3, 4, 4, 3], 123)) self.characters.append(Character("Zax", 18, [1, 6, 2, 5], 124)) self.characters.append(Character("Chroma", 19, [4, 2, 5, 3], 125)) self.characters.append(Character("Zenosha", 20, [3, 4, 5, 2], 126)) self.characters.append(Character("Snax", 21, [3, 4, 6, 1], 127)) # self.print_params() # self.print_chars() return elif aBuiltin == "PACKTACTICS1": # Create a campaign featuring the Season 1 Pack Tactics crew. self.ship = Ship() self.params = Plot() self.art = "an" if self.params.loc_desc[0] in ["a","e","i","o","u"] else "a" self.characters = [] self.characters.append(Character("Daldain", 13, [3, 4, 5, 2], 114)) self.characters.append(Character("Gox", 18, [2, 5, 2, 5], 115)) self.characters.append(Character("Zeeli", 14, [4, 2, 5, 3], 116)) self.characters.append(Character("Sox", 16, [3, 3, 3, 3], 117)) # self.print_params() # self.print_chars() return elif aBuiltin == "PACKTACTICS2": # Create a campaign featuring the Season 2 Pack Tactics crew. self.ship = Ship("Red", "Star", "is maneuverable & unarmored", "has a politician who thinks they're in charge of it") self.params = Plot() self.art = "an" if self.params.loc_desc[0] in ["a","e","i","o","u"] else "a" self.characters = [] self.characters.append(Character("Daldain", 13, [4, 5, 5, 3], 118)) self.characters.append(Character("Gox", 18, [2, 6, 4, 5], 119)) self.characters.append(Character("Zeeli", 14, [3, 4, 6, 5], 120)) self.characters.append(Character("Marwyse", 15, [4, 4, 6, 3], 121)) self.characters.append(Character("Sox", 16, [5, 4, 4, 4], 122)) # self.print_params() # self.print_chars() return elif aBuiltin == "JUSTINBAILEY": # Create a random campaign, but everyone's Gadget is a leotard that somehow is also an environment suit self.create_campaign(n=6, makeChars=True) for c in self.characters: c.gadget = {"id":127, "name": "The Bailey", "description": "A form-fitting leotard that somehow protects the wearer from all environmental effects except extreme heat - including vacuum and poison.", "reusable": True} # self.print_params() # self.print_chars() return elif aBuiltin == "NARPASSWORD": # Create a random campaign, but all the kobolds' stats are set to 6 self.create_campaign(n=6, makeChars=True) for c in self.characters: c.stats = [6,6,6,6] # self.print_params() # self.print_chars() return elif aBuiltin == "OHNOITSPEV!!": # Create a random campaign, but the adversary is Pev self.create_campaign(n=6, makeChars=True) self.params = Plot(probIndex=121) numPwd = [] for c in densePwd: numPwd.append(Campaign.ALPHABET.index(c)) bitPwd = [lpad(bin(x).replace("0b",""), 6) for x in numPwd] longBitPwd = [] for word in bitPwd: longword = lpad(word,6) longBitPwd.append(longword) self.newBitfield = "".join(longBitPwd) while len(self.newBitfield) < 509: self.newBitfield += "0" outkey = {} # Location 1: 7 bits i,j = 0,7 outkey["loc1"] = int(self.newBitfield[i:j], 2) # Location 2: 7 bits i,j = j,j+7 outkey["loc2"] = int(self.newBitfield[i:j], 2) # Location Battlefield: 1 bit i,j = j,j+1 outkey["battlefield"] = int(self.newBitfield[i:j], 2) # Mission: 7 bits i,j = j,j+7 outkey["miss"] = int(self.newBitfield[i:j], 2) # Oops: 1 bit i,j = j,j+1 outkey["oops"] = int(self.newBitfield[i:j], 2) # Problem 1: 7 bits i,j = j,j+7 outkey["prob1"] = int(self.newBitfield[i:j], 2) # Problem 1 name: 40 bits i,j = j,j+40 outkey["prob1name"] = self.newBitfield[i:j] # Problem 2: 7 bits i,j = j,j+7 outkey["prob2"] = int(self.newBitfield[i:j], 2) # Ship name 1: 7 bits i,j = j,j+7 outkey["sname1"] = int(self.newBitfield[i:j], 2) # Ship name 2: 7 bits i,j = j,j+7 outkey["sname2"] = int(self.newBitfield[i:j], 2) # Ship gqual: 7 bits i,j = j,j+7 outkey["gqual"] = int(self.newBitfield[i:j], 2) # Ship bqual: 7 bits i,j = j,j+7 outkey["bqual"] = int(self.newBitfield[i:j], 2) # Character 1 name: 40 bits i,j = j,j+40 outkey["char1name"] = self.newBitfield[i:j] # Character 1 career: 7 bits i,j = j,j+7 outkey["char1career"] = int(self.newBitfield[i:j], 2) # Character 1 order: 3 bits i,j = j,j+3 outkey["char1ord"] = int(self.newBitfield[i:j], 2) # Character 1 chaos: 3 bits i,j = j,j+3 outkey["char1cha"] = int(self.newBitfield[i:j], 2) # Character 1 body: 3 bits i,j = j,j+3 outkey["char1bod"] = int(self.newBitfield[i:j], 2) # Character 1 brain: 3 bits i,j = j,j+3 outkey["char1bra"] = int(self.newBitfield[i:j], 2) # Character 1 gadget: 7 bits i,j = j,j+7 outkey["char1gad"] = int(self.newBitfield[i:j], 2) # Character 2 name: 40 bits i,j = j,j+40 outkey["char2name"] = self.newBitfield[i:j] # Character 2 career: 7 bits i,j = j,j+7 outkey["char2career"] = int(self.newBitfield[i:j], 2) # Character 2 order: 3 bits i,j = j,j+3 outkey["char2ord"] = int(self.newBitfield[i:j], 2) # Character 2 chaos: 3 bits i,j = j,j+3 outkey["char2cha"] = int(self.newBitfield[i:j], 2) # Character 2 body: 3 bits i,j = j,j+3 outkey["char2bod"] = int(self.newBitfield[i:j], 2) # Character 2 brain: 3 bits i,j = j,j+3 outkey["char2bra"] = int(self.newBitfield[i:j], 2) # Character 2 gadget: 7 bits i,j = j,j+7 outkey["char2gad"] = int(self.newBitfield[i:j], 2) # Character 3 name: 40 bits i,j = j,j+40 outkey["char3name"] = self.newBitfield[i:j] # Character 3 career: 7 bits i,j = j,j+7 outkey["char3career"] = int(self.newBitfield[i:j], 2) # Character 3 order: 3 bits i,j = j,j+3 outkey["char3ord"] = int(self.newBitfield[i:j], 2) # Character 3 chaos: 3 bits i,j = j,j+3 outkey["char3cha"] = int(self.newBitfield[i:j], 2) # Character 3 body: 3 bits i,j = j,j+3 outkey["char3bod"] = int(self.newBitfield[i:j], 2) # Character 3 brain: 3 bits i,j = j,j+3 outkey["char3bra"] = int(self.newBitfield[i:j], 2) # Character 3 gadget: 7 bits i,j = j,j+7 outkey["char3gad"] = int(self.newBitfield[i:j], 2) # Character 4 name: 40 bits i,j = j,j+40 outkey["char4name"] = self.newBitfield[i:j] # Character 4 career: 7 bits i,j = j,j+7 outkey["char4career"] = int(self.newBitfield[i:j], 2) # Character 4 order: 3 bits i,j = j,j+3 outkey["char4ord"] = int(self.newBitfield[i:j], 2) # Character 4 chaos: 3 bits i,j = j,j+3 outkey["char4cha"] = int(self.newBitfield[i:j], 2) # Character 4 body: 3 bits i,j = j,j+3 outkey["char4bod"] = int(self.newBitfield[i:j], 2) # Character 4 brain: 3 bits i,j = j,j+3 outkey["char4bra"] = int(self.newBitfield[i:j], 2) # Character 4 gadget: 7 bits i,j = j,j+7 outkey["char4gad"] = int(self.newBitfield[i:j], 2) # Character 5 name: 40 bits i,j = j,j+40 outkey["char5name"] = self.newBitfield[i:j] # Character 5 career: 7 bits i,j = j,j+7 outkey["char5career"] = int(self.newBitfield[i:j], 2) # Character 5 order: 3 bits i,j = j,j+3 outkey["char5ord"] = int(self.newBitfield[i:j], 2) # Character 5 chaos: 3 bits i,j = j,j+3 outkey["char5cha"] = int(self.newBitfield[i:j], 2) # Character 5 body: 3 bits i,j = j,j+3 outkey["char5bod"] = int(self.newBitfield[i:j], 2) # Character 5 brain: 3 bits i,j = j,j+3 outkey["char5bra"] = int(self.newBitfield[i:j], 2) # Character 5 gadget: 7 bits i,j = j,j+7 outkey["char5gad"] = int(self.newBitfield[i:j], 2) # Character 6 name: 40 bits i,j = j,j+40 outkey["char6name"] = self.newBitfield[i:j] # Character 6 career: 7 bits i,j = j,j+7 outkey["char6career"] = int(self.newBitfield[i:j], 2) # Character 6 order: 3 bits i,j = j,j+3 outkey["char6ord"] = int(self.newBitfield[i:j], 2) # Character 6 chaos: 3 bits i,j = j,j+3 outkey["char6cha"] = int(self.newBitfield[i:j], 2) # Character 6 body: 3 bits i,j = j,j+3 outkey["char6bod"] = int(self.newBitfield[i:j], 2) # Character 6 brain: 3 bits i,j = j,j+3 outkey["char6bra"] = int(self.newBitfield[i:j], 2) # Character 6 gadget: 7 bits i,j = j,j+7 outkey["char6gad"] = int(self.newBitfield[i:j], 2) self.ship = Ship(Ship.NAME1[outkey["sname1"]], Ship.NAME2[outkey["sname2"]], Ship.GQUAL[outkey["gqual"]], Ship.BQUAL[outkey["bqual"]]) self.params = Plot(loc_desc=Plot.loc1[outkey["loc1"]], locIndex=outkey["loc2"], battlefield=outkey["battlefield"], location=None, missIndex=outkey["miss"], oops=outkey["oops"], mission=None, probIndex=outkey["prob1"], problem=None, probName=self.decode_name(outkey["prob1name"]), secProblem=outkey["prob2"], thirdProblem=None) self.art = "an" if self.params.loc_desc[0] in ["a","e","i","o","u"] else "a" self.characters = [] for q in range(1,7): keys = [f"char{q}name", f"char{q}career", f"char{q}ord", f"char{q}cha", f"char{q}bod", f"char{q}bra", f"char{q}gad"] c = Character(name=self.decode_name(outkey[keys[0]]), career=outkey[keys[1]], stats=[outkey[keys[2]], outkey[keys[3]], outkey[keys[4]], outkey[keys[5]]], gadget=outkey[keys[6]]) self.characters.append(c) #return self.newBitfield def encode_name(self, name): field = "".join([lpad(bin(Campaign.NAMELETS.index(c.lower()))[2:], 5) for c in name]) return field def decode_name(self, field): i,j = 35,40 name = "" for _ in range(8): k = int(field[i:j], 2) if k != 31: name = Campaign.NAMELETS[k] + name i,j = i-5, i name = name[0].upper() + name[1:] return name def print_params(self, endc=" ", html=False): st = ["Order:", "Chaos:", "Brains:", "Body:"] cst = ", ".join([" ".join(y) for y in list(zip(st, [str(x) for x in self.params.problem["stats"]]))]) if self.params.oops == 1: oops = "...well, they weren't paying attention, so don't tell them, but they're supposed to " else: oops = "" mission = oops + self.params.mission # pl = "s" if self.params.problem["isPlural"] else "" note = self.params.problem["note"] secnote = "" if self.params.problem["hasMinion"]: secnote = "Their minion: " + self.params.secProblem["note"] lines = [ f"The Kobolds of the {self.ship.fullname}", f"have been sent out to {self.art} {self.params.loc_desc} {self.params.location}!", f"in order to {mission}", f"but they're challenged by {self.params.fullProblem}!", f"{note} {secnote}", f"The stats of the {self.params.problem['shortname']}", f"{cst}" ] if self.params.problem["hasMinion"]: mst = ", ".join([" ".join(y) for y in list(zip(st, [str(x) for x in self.params.secProblem["stats"]]))]) # spl = "s" if self.params.secProblem["isPlural"] else "" lines.append(f"The stats of the {self.params.secProblem['shortname']}") lines.append(f"{mst}") if html: secnote = "" if self.params.problem["hasMinion"]: secnote = "Their minion: " + self.params.secProblem["note"] + "
\n" out = ( f"
\n" f" The Ship\n" f" \n" f" The {self.ship.fullname}!\n" f" \n" f"
\n" f" \n" f" It {self.ship.gqual}...\n" f"
\n" f" \n" f" But {self.ship.bqual}!\n" f" \n" f"
\n" f"
\n" f" The Mission\n" f" \n" f" The kobolds have been sent to {self.art} {self.params.loc_desc} {self.params.location}\n" f"
\n" f" \n" f" in order to {mission}!\n" f" \n" f"
\n
\n" f"
\n" f" The Adversary\n" f" They're challenged by {self.params.fullProblem}!\n" f"
\n" f" \n" f" {self.params.problem['note']}
\n" f" {secnote}" f"
\n" f" \n" f" The stats of the {self.params.problem['shortname']}:
\n" f" {cst}\n" f"
\n" ) if self.params.problem["hasMinion"]: out += ( f"
\n" f" The stats of the {self.params.secProblem['shortname']}:
\n" f" {mst}\n" f"
\n" ) out += f"
\n" print(out) print(f"
\n") else: print(f"{lines[0]} {lines[1]} {lines[2]} -- {lines[3]}") print(f"{lines[4]}") print(f"{lines[5]}: {lines[6]}") if self.params.problem["hasMinion"]: print(f"- {lines[7]}: {lines[8]}") print() self.ship.print(html=html) def print_chars(self, html=False): if html: print(f"
\n") print(f"The Kobolds\n") else: print("The kobolds:") for k in self.characters: k.print(html=html) if html: print(f"
\n
\n") def print_password(self, html=False): if self.masterpassword: pw = self.masterpassword else: pw = self.generate_key() if html: out = ( f"
" f"Permalink to this campaign:
" f"{pw.replace(' ', '')}

" f"Generate a new random campaign
" f"
" ) print(out) print(f"
\n") else: print(f"Password: {pw}") def decode(self, pwd): pass def lpad(s, n, c="0"): while len(s) < n: s = c + s return s if __name__ == "__main__": parser = argparse.ArgumentParser() group = parser.add_mutually_exclusive_group() group.add_argument("-c", "--campaign", help="print a full campaign block with N kobolds (default 6)", nargs="?", const=6, type=int, metavar="N") group.add_argument("-k", "--kobolds", help="print N kobolds", type=int, nargs="?", const=1, default=1, metavar="N") group.add_argument("-n", "--names", help="print N kobolds without stat blocks", nargs="?", const=1, type=int, metavar="N") group.add_argument("-p", "--params", help="print only the parameters of a campaign", action="store_true") group.add_argument("-s", "--ship", help="print only the ship name and description", action="store_true") group.add_argument("-pw", "--password", help="print the campaign defined by the submitted password", type=str, nargs="?", const=1, metavar="PW") parser.add_argument("--html", help="print in HTML instead of plain text", action="store_true") args = parser.parse_args() html = True if args.html else False if args.password: cmp = Campaign(fromPW = True, pw=args.password) cmp.print_params(html=html) cmp.print_chars(html=html) cmp.print_password(html=html) elif args.campaign: cmp = Campaign(args.campaign) cmp.print_params(html=html) cmp.print_chars(html=html) cmp.print_password(html=html) elif args.params: cmp = Campaign(makeChars=False) cmp.print_params(html=html) elif args.ship: ship = Ship() ship.print(html=html) elif args.names: for _ in range(args.names): c = Character() c.generate() c.print_name(html=html) else: for _ in range(args.kobolds): c = Character() c.generate() c.print(html=html)