cleaning up

This commit is contained in:
NikolajDanger
2020-03-23 22:34:53 +01:00
parent 775f3fe0c7
commit bc7048d493
21 changed files with 1234 additions and 691 deletions

545
funcs/dice/dice.py Normal file
View File

@ -0,0 +1,545 @@
import logging
import random
import re
import traceback
from heapq import nlargest, nsmallest
from math import floor
from re import IGNORECASE
import numexpr
import errors
log = logging.getLogger(__name__)
VALID_OPERATORS = 'k|rr|ro|mi|ma|ra|e|p'
VALID_OPERATORS_ARRAY = VALID_OPERATORS.split('|')
VALID_OPERATORS_2 = re.compile('|'.join(["({})".format(i) for i in VALID_OPERATORS_ARRAY]))
DICE_PATTERN = re.compile(
r'^\s*(?:(?:(\d*d\d+)(?:(?:' + VALID_OPERATORS + r')(?:[lh<>]?\d+))*|(\d+)|([-+*/().=])?)\s*(\[.*\])?)(.*?)\s*$',
IGNORECASE)
def list_get(index, default, l):
try:
a = l[index]
except IndexError:
a = default
return a
def roll(rollStr, adv: int = 0, rollFor='', inline=False, double=False, show_blurbs=True, **kwargs):
roller = Roll()
result = roller.roll(rollStr, adv, rollFor, inline, double, show_blurbs, **kwargs)
return result
def get_roll_comment(rollStr):
"""Returns: A two-tuple (dice without comment, comment)"""
try:
comment = ''
no_comment = ''
dice_set = re.split('([-+*/().=])', rollStr)
dice_set = [d for d in dice_set if not d in (None, '')]
log.debug("Found dice set: " + str(dice_set))
for index, dice in enumerate(dice_set):
match = DICE_PATTERN.match(dice)
log.debug("Found dice group: " + str(match.groups()))
no_comment += dice.replace(match.group(5), '')
if match.group(5):
comment = match.group(5) + ''.join(dice_set[index + 1:])
break
return no_comment, comment
except:
pass
return rollStr, ''
class Roll(object):
def __init__(self, parts=None):
if parts is None:
parts = []
self.parts = parts
def get_crit(self):
"""Returns: 0 for no crit, 1 for 20, 2 for 1."""
try:
crit = next(p.get_crit() for p in self.parts if isinstance(p, SingleDiceGroup))
except StopIteration:
crit = 0
return crit
def get_total(self):
"""Returns: int"""
return numexpr.evaluate(''.join(p.get_eval() for p in self.parts if not isinstance(p, Comment)))
# # Dice Roller
def roll(self, rollStr, adv: int = 0, rollFor='', inline=False, double=False, show_blurbs=True, **kwargs):
try:
if '**' in rollStr:
raise errors.InvalidArgument("Exponents are currently disabled.")
self.parts = []
# split roll string into XdYoptsSel [comment] or Op
# set remainder to comment
# parse each, returning a SingleDiceResult
dice_set = re.split('([-+*/().=])', rollStr)
dice_set = [d for d in dice_set if not d in (None, '')]
log.debug("Found dice set: " + str(dice_set))
for index, dice in enumerate(dice_set):
match = DICE_PATTERN.match(dice)
log.debug("Found dice group: " + str(match.groups()))
# check if it's dice
if match.group(1):
roll = self.roll_one(dice.replace(match.group(5), ''), adv)
self.parts.append(roll)
# or a constant
elif match.group(2):
self.parts.append(Constant(value=int(match.group(2)), annotation=match.group(4)))
# or an operator
elif not match.group(5):
self.parts.append(Operator(op=match.group(3), annotation=match.group(4)))
if match.group(5):
self.parts.append(Comment(match.group(5) + ''.join(dice_set[index + 1:])))
break
# calculate total
crit = self.get_crit()
try:
total = self.get_total()
except SyntaxError:
raise errors.InvalidArgument("No dice found to roll.")
rolled = ' '.join(str(res) for res in self.parts if not isinstance(res, Comment))
if rollFor is '':
rollFor = ''.join(str(c) for c in self.parts if isinstance(c, Comment))
# return final solution
if not inline:
# Builds end result while showing rolls
reply = ' '.join(
str(res) for res in self.parts if not isinstance(res, Comment)) + '\n**Total:** ' + str(
floor(total))
skeletonReply = reply
rollFor = rollFor if rollFor is not '' else 'Result'
reply = '**{}:** '.format(rollFor) + reply
if show_blurbs:
if adv == 1:
reply += '\n**Rolled with Advantage**'
elif adv == -1:
reply += '\n**Rolled with Disadvantage**'
if crit == 1:
critStr = "\n_**Critical Hit!**_ "
reply += critStr
elif crit == 2:
critStr = "\n_**Critical Fail!**_ "
reply += critStr
else:
# Builds end result while showing rolls
reply = ' '.join(str(res) for res in self.parts if not isinstance(res, Comment)) + ' = `' + str(
floor(total)) + '`'
skeletonReply = reply
rollFor = rollFor if rollFor is not '' else 'Result'
reply = '**{}:** '.format(rollFor) + reply
if show_blurbs:
if adv == 1:
reply += '\n**Rolled with Advantage**'
elif adv == -1:
reply += '\n**Rolled with Disadvantage**'
if crit == 1:
critStr = "\n_**Critical Hit!**_ "
reply += critStr
elif crit == 2:
critStr = "\n_**Critical Fail!**_ "
reply += critStr
reply = re.sub(' +', ' ', reply)
skeletonReply = re.sub(' +', ' ', str(skeletonReply))
return DiceResult(result=int(floor(total)), verbose_result=reply, crit=crit, rolled=rolled,
skeleton=skeletonReply, raw_dice=self)
except Exception as ex:
if not isinstance(ex, (SyntaxError, KeyError, errors.AvraeException)):
log.error('Error in roll() caused by roll {}:'.format(rollStr))
traceback.print_exc()
return DiceResult(verbose_result="Invalid input: {}".format(ex))
def roll_one(self, dice, adv: int = 0):
result = SingleDiceGroup()
result.rolled = []
# splits dice and comments
split = re.match(r'^([^\[\]]*?)\s*(\[.*\])?\s*$', dice)
dice = split.group(1).strip()
annotation = split.group(2)
result.annotation = annotation if annotation is not None else ''
# Recognizes dice
obj = re.findall('\d+', dice)
obj = [int(x) for x in obj]
numArgs = len(obj)
ops = []
if numArgs == 1:
if not dice.startswith('d'):
raise errors.InvalidArgument('Please pass in the value of the dice.')
numDice = 1
diceVal = obj[0]
if adv is not 0 and diceVal == 20:
numDice = 2
ops = ['k', 'h1'] if adv is 1 else ['k', 'l1']
elif numArgs == 2:
numDice = obj[0]
diceVal = obj[-1]
if adv is not 0 and diceVal == 20:
ops = ['k', 'h' + str(numDice)] if adv is 1 else ['k', 'l' + str(numDice)]
numDice = numDice * 2
else: # split into xdy and operators
numDice = obj[0]
diceVal = obj[1]
dice = re.split('(\d+d\d+)', dice)[-1]
ops = VALID_OPERATORS_2.split(dice)
ops = [a for a in ops if a is not None]
# dice repair/modification
if numDice > 300 or diceVal < 1:
raise errors.InvalidArgument('Too many dice rolled.')
result.max_value = diceVal
result.num_dice = numDice
result.operators = ops
for _ in range(numDice):
try:
tempdice = SingleDice()
tempdice.value = random.randint(1, diceVal)
tempdice.rolls = [tempdice.value]
tempdice.max_value = diceVal
tempdice.kept = True
result.rolled.append(tempdice)
except:
result.rolled.append(SingleDice())
if ops is not None:
rerollList = []
reroll_once = []
keep = None
to_explode = []
to_reroll_add = []
valid_operators = VALID_OPERATORS_ARRAY
last_operator = None
for index, op in enumerate(ops):
if last_operator is not None and op in valid_operators and not op == last_operator:
result.reroll(reroll_once, 1)
reroll_once = []
result.reroll(rerollList, greedy=True)
rerollList = []
result.keep(keep)
keep = None
result.reroll(to_reroll_add, 1, keep_rerolled=True, unique=True)
to_reroll_add = []
result.reroll(to_explode, greedy=True, keep_rerolled=True)
to_explode = []
if op == 'rr':
rerollList += parse_selectors([list_get(index + 1, 0, ops)], result, greedy=True)
if op == 'k':
keep = [] if keep is None else keep
keep += parse_selectors([list_get(index + 1, 0, ops)], result)
if op == 'p':
keep = [] if keep is None else keep
keep += parse_selectors([list_get(index + 1, 0, ops)], result, inverse=True)
if op == 'ro':
reroll_once += parse_selectors([list_get(index + 1, 0, ops)], result)
if op == 'mi':
_min = list_get(index + 1, 0, ops)
for r in result.rolled:
if r.value < int(_min):
r.update(int(_min))
if op == 'ma':
_max = list_get(index + 1, 0, ops)
for r in result.rolled:
if r.value > int(_max):
r.update(int(_max))
if op == 'ra':
to_reroll_add += parse_selectors([list_get(index + 1, 0, ops)], result)
if op == 'e':
to_explode += parse_selectors([list_get(index + 1, 0, ops)], result, greedy=True)
if op in valid_operators:
last_operator = op
result.reroll(reroll_once, 1)
result.reroll(rerollList, greedy=True)
result.keep(keep)
result.reroll(to_reroll_add, 1, keep_rerolled=True, unique=True)
result.reroll(to_explode, greedy=True, keep_rerolled=True)
return result
class Part:
"""Class to hold one part of the roll string."""
pass
class SingleDiceGroup(Part):
def __init__(self, num_dice: int = 0, max_value: int = 0, rolled=None, annotation: str = "", result: str = "",
operators=None):
if operators is None:
operators = []
if rolled is None:
rolled = []
self.num_dice = num_dice
self.max_value = max_value
self.rolled = rolled # list of SingleDice
self.annotation = annotation
self.result = result
self.operators = operators
def keep(self, rolls_to_keep):
if rolls_to_keep is None: return
for _roll in self.rolled:
if not _roll.value in rolls_to_keep:
_roll.kept = False
elif _roll.kept:
rolls_to_keep.remove(_roll.value)
def reroll(self, rerollList, max_iterations=1000, greedy=False, keep_rerolled=False, unique=False):
if not rerollList: return # don't reroll nothing - minor optimization
if unique:
rerollList = list(set(rerollList)) # remove duplicates
if len(rerollList) > 100:
raise OverflowError("Too many dice to reroll (max 100)")
last_index = 0
count = 0
should_continue = True
while should_continue: # let's only iterate 250 times for sanity
should_continue = False
if any(d.value in set(rerollList) for d in self.rolled[last_index:] if d.kept and not d.exploded):
should_continue = True
to_extend = []
for r in self.rolled[last_index:]: # no need to recheck everything
count += 1
if count > max_iterations:
should_continue = False
if r.value in rerollList and r.kept and not r.exploded:
try:
tempdice = SingleDice()
tempdice.value = random.randint(1, self.max_value)
tempdice.rolls = [tempdice.value]
tempdice.max_value = self.max_value
tempdice.kept = True
to_extend.append(tempdice)
if not keep_rerolled:
r.drop()
else:
r.explode()
except:
to_extend.append(SingleDice())
if not keep_rerolled:
r.drop()
else:
r.explode()
if not greedy:
rerollList.remove(r.value)
last_index = len(self.rolled)
self.rolled.extend(to_extend)
def get_total(self):
"""Returns:
int - The total value of the dice."""
return sum(r.value for r in self.rolled if r.kept)
def get_eval(self):
return str(self.get_total())
def get_num_kept(self):
return sum(1 for r in self.rolled if r.kept)
def get_crit(self):
"""Returns:
int - 0 for no crit, 1 for crit, 2 for crit fail."""
if self.get_num_kept() == 1 and self.max_value == 20:
if self.get_total() == 20:
return 1
elif self.get_total() == 1:
return 2
return 0
def __str__(self):
return "{0.num_dice}d{0.max_value}{1} ({2}) {0.annotation}".format(
self, ''.join(self.operators), ', '.join(str(r) for r in self.rolled))
def to_dict(self):
return {'type': 'dice', 'dice': [d.to_dict() for d in self.rolled], 'annotation': self.annotation,
'value': self.get_total(), 'is_crit': self.get_crit(), 'num_kept': self.get_num_kept(),
'text': str(self), 'num_dice': self.num_dice, 'dice_size': self.max_value, 'operators': self.operators}
class SingleDice:
def __init__(self, value: int = 0, max_value: int = 0, kept: bool = True, exploded: bool = False):
self.value = value
self.max_value = max_value
self.kept = kept
self.rolls = [value] # list of ints (for X -> Y -> Z)
self.exploded = exploded
def drop(self):
self.kept = False
def explode(self):
self.exploded = True
def update(self, new_value):
self.value = new_value
self.rolls.append(new_value)
def __str__(self):
formatted_rolls = [str(r) for r in self.rolls]
if int(formatted_rolls[-1]) == self.max_value or int(formatted_rolls[-1]) == 1:
formatted_rolls[-1] = '**' + formatted_rolls[-1] + '**'
if self.exploded:
formatted_rolls[-1] = '__' + formatted_rolls[-1] + '__'
if self.kept:
return ' -> '.join(formatted_rolls)
else:
return '~~' + ' -> '.join(formatted_rolls) + '~~'
def __repr__(self):
return "<SingleDice object: value={0.value}, max_value={0.max_value}, kept={0.kept}, rolls={0.rolls}>".format(
self)
def to_dict(self):
return {'type': 'single_dice', 'value': self.value, 'size': self.max_value, 'is_kept': self.kept,
'rolls': self.rolls, 'exploded': self.exploded}
class Constant(Part):
def __init__(self, value: int = 0, annotation: str = ""):
self.value = value
self.annotation = annotation if annotation is not None else ''
def __str__(self):
return "{0.value} {0.annotation}".format(self)
def get_eval(self):
return str(self.value)
def to_dict(self):
return {'type': 'constant', 'value': self.value, 'annotation': self.annotation}
class Operator(Part):
def __init__(self, op: str = "+", annotation: str = ""):
self.op = op if op is not None else ''
self.annotation = annotation if annotation is not None else ''
def __str__(self):
return "{0.op} {0.annotation}".format(self)
def get_eval(self):
return self.op
def to_dict(self):
return {'type': 'operator', 'value': self.op, 'annotation': self.annotation}
class Comment(Part):
def __init__(self, comment: str = ""):
self.comment = comment
def __str__(self):
return self.comment.strip()
def to_dict(self):
return {'type': 'comment', 'value': self.comment}
def parse_selectors(opts, res, greedy=False, inverse=False):
"""Returns a list of ints."""
for o in range(len(opts)):
if opts[o][0] is 'h':
opts[o] = nlargest(int(opts[o].split('h')[1]), (d.value for d in res.rolled if d.kept))
elif opts[o][0] is 'l':
opts[o] = nsmallest(int(opts[o].split('l')[1]), (d.value for d in res.rolled if d.kept))
elif opts[o][0] is '>':
if greedy:
opts[o] = list(range(int(opts[o].split('>')[1]) + 1, res.max_value + 1))
else:
opts[o] = [d.value for d in res.rolled if d.value > int(opts[o].split('>')[1])]
elif opts[o][0] is '<':
if greedy:
opts[o] = list(range(1, int(opts[o].split('<')[1])))
else:
opts[o] = [d.value for d in res.rolled if d.value < int(opts[o].split('<')[1])]
out = []
for o in opts:
if isinstance(o, list):
out.extend(int(l) for l in o)
elif not greedy:
out.extend(int(o) for a in res.rolled if a.value is int(o) and a.kept)
else:
out.append(int(o))
if not inverse:
return out
inverse_out = []
for rolled in res.rolled:
if rolled.kept and rolled.value in out:
out.remove(rolled.value)
elif rolled.kept:
inverse_out.append(rolled.value)
return inverse_out
class DiceResult:
"""Class to hold the output of a dice roll."""
def __init__(self, result: int = 0, verbose_result: str = '', crit: int = 0, rolled: str = '', skeleton: str = '',
raw_dice: Roll = None):
self.plain = result
self.total = result
self.result = verbose_result
self.crit = crit
self.rolled = rolled
self.skeleton = skeleton if skeleton is not '' else verbose_result
self.raw_dice = raw_dice # Roll
def __str__(self):
return self.result
def __repr__(self):
return '<DiceResult object: total={}>'.format(self.total)
def consolidated(self):
"""Gets the most simplified version of the roll string."""
if self.raw_dice is None:
return "0"
parts = [] # list of (part, annotation)
last_part = ""
for p in self.raw_dice.parts:
if isinstance(p, SingleDiceGroup):
last_part += str(p.get_total())
else:
last_part += str(p)
if not isinstance(p, Comment) and p.annotation:
parts.append((last_part, p.annotation))
last_part = ""
if last_part:
parts.append((last_part, ""))
to_roll = ""
last_annotation = ""
out = ""
for numbers, annotation in parts:
if annotation and annotation != last_annotation and to_roll:
out += f"{roll(to_roll).total:+} {last_annotation}"
to_roll = ""
if annotation:
last_annotation = annotation
to_roll += numbers
if to_roll:
out += f"{roll(to_roll).total:+} {last_annotation}"
out = out.strip('+ ')
return out
if __name__ == '__main__':
while True:
print(roll(input().strip()))

162
funcs/dice/errors.py Normal file
View File

@ -0,0 +1,162 @@
class AvraeException(Exception):
"""A base exception class."""
def __init__(self, msg):
super().__init__(msg)
class NoCharacter(AvraeException):
"""Raised when a user has no active character."""
def __init__(self):
super().__init__("You have no character active.")
class NoActiveBrew(AvraeException):
"""Raised when a user has no active homebrew of a certain type."""
def __init__(self):
super().__init__("You have no homebrew of this type active.")
class ExternalImportError(AvraeException):
"""Raised when something fails to import."""
def __init__(self, msg):
super().__init__(msg)
class InvalidArgument(AvraeException):
"""Raised when an argument is invalid."""
pass
class EvaluationError(AvraeException):
"""Raised when a cvar evaluation causes an error."""
def __init__(self, original):
super().__init__(f"Error evaluating expression: {original}")
self.original = original
class FunctionRequiresCharacter(AvraeException):
"""
Raised when a function that requires a character is called without one.
"""
def __init__(self, msg=None):
super().__init__(msg or "This alias requires an active character.")
class OutdatedSheet(AvraeException):
"""Raised when a feature is used that requires an updated sheet."""
def __init__(self, msg=None):
super().__init__(msg or "This command requires an updated character sheet. Try running `!update`.")
class NoSpellDC(AvraeException):
def __init__(self):
super().__init__("No spell save DC found.")
class NoSpellAB(AvraeException):
def __init__(self):
super().__init__("No spell attack bonus found.")
class InvalidSaveType(AvraeException):
def __init__(self):
super().__init__("Invalid save type.")
class ConsumableException(AvraeException):
"""A base exception for consumable exceptions to stem from."""
pass
class ConsumableNotFound(ConsumableException):
"""Raised when a consumable is not found."""
def __init__(self):
super().__init__("The requested counter does not exist.")
class CounterOutOfBounds(ConsumableException):
"""Raised when a counter is set to a value out of bounds."""
def __init__(self):
super().__init__("The new value is out of bounds.")
class NoReset(ConsumableException):
"""Raised when a consumable without a reset is reset."""
def __init__(self):
super().__init__("The counter does not have a reset value.")
class InvalidSpellLevel(ConsumableException):
"""Raised when a spell level is invalid."""
def __init__(self):
super().__init__("The spell level is invalid.")
class SelectionException(AvraeException):
"""A base exception for message awaiting exceptions to stem from."""
pass
class NoSelectionElements(SelectionException):
"""Raised when get_selection() is called with no choices."""
def __init__(self, msg=None):
super().__init__(msg or "There are no choices to select from.")
class SelectionCancelled(SelectionException):
"""Raised when get_selection() is cancelled or times out."""
def __init__(self):
super().__init__("Selection timed out or was cancelled.")
class CombatException(AvraeException):
"""A base exception for combat-related exceptions to stem from."""
pass
class CombatNotFound(CombatException):
"""Raised when a channel is not in combat."""
def __init__(self):
super().__init__("This channel is not in combat.")
class RequiresContext(CombatException):
"""Raised when a combat is committed without context."""
def __init__(self):
super().__init__("Combat not contextualized.")
class ChannelInCombat(CombatException):
"""Raised when a combat is started with an already active combat."""
def __init__(self):
super().__init__("Channel already in combat.")
class CombatChannelNotFound(CombatException):
"""Raised when a combat's channel is not in the channel list."""
def __init__(self):
super().__init__("Combat channel does not exist.")
class NoCombatants(CombatException):
"""Raised when a combat tries to advance turn with no combatants."""
def __init__(self):
super().__init__("There are no combatants.")

149
funcs/gwendolynFuncs.py Normal file
View File

@ -0,0 +1,149 @@
import lxml.etree #used by imageFunc
import re #used by roll_dice
import datetime #used by helloFunc
import json #used by spellFunc
import random #used by imageFunc
import urllib #used by imageFunc
import imdb #used by movieFunc
from dice import dice
from lookup import lookupFuncs
from other import movie, generators
from swfuncs import swchar, swroll
def roll_dice(author, rollStr: str = "1d20"):
print("Rolling "+str(rollStr))
if rollStr == '0/0': # easter eggs
return("What do you expect me to do, destroy the universe?")
adv = 0
if re.search('(^|\s+)(adv|dis)(\s+|$)', rollStr) is not None:
adv = 1 if re.search('(^|\s+)adv(\s+|$)', rollStr) is not None else -1
rollStr = re.sub('(adv|dis)(\s+|$)', '', rollStr)
res = dice.roll(rollStr, adv=adv)
out = res.result
outStr = author + ' :game_die:\n' + out
if len(outStr) > 1999:
outputs = author + ' :game_die:\n[Output truncated due to length]\n**Result:** ' + str(res.plain)
else:
outputs = outStr
print("Successfully ran !roll")
print("")
return(outputs)
no_caps_list = ["of","the"]
def cap(s):
word_number = 0
lst = s.split()
res = ''
for word in lst:
word_number += 1
if word not in no_caps_list or word_number == 1:
word = word.capitalize()
res += word+" "
res = res[:-1]
return res
def time_in_range(start, end, x):
"""Return true if x is in the range [start, end]"""
if start <= end:
return start <= x <= end
else:
return start <= x or x <= end
def helloFunc(author):
print("")
now = datetime.datetime.now()
if time_in_range(now.replace(hour=5, minute=0, second=0, microsecond=0),now.replace(hour=10, minute=0, second=0, microsecond=0), now):
return("Good morning, "+str(author))
elif time_in_range(now.replace(hour=10, minute=0, second=0, microsecond=0),now.replace(hour=13, minute=0, second=0, microsecond=0), now):
return("Good day, "+str(author))
elif time_in_range(now.replace(hour=13, minute=0, second=0, microsecond=0),now.replace(hour=18, minute=0, second=0, microsecond=0), now):
return("Good afternoon, "+str(author))
elif time_in_range(now.replace(hour=18, minute=0, second=0, microsecond=0),now.replace(hour=22, minute=0, second=0, microsecond=0), now):
return("Good evening, "+str(author))
elif time_in_range(now.replace(hour=22, minute=0, second=0, microsecond=0),now.replace(hour=23, minute=59, second=59, microsecond=0), now):
return("Good night, "+str(author))
else:
return("Why hello, "+str(author))
def imageFunc():
cams = ("one","two","three","four")
cam = random.choice(cams)
if cam == "one":
a = str(random.randint(0 ,9))
b = str(random.randint(0,9))
c = str(random.randint(0,9))
d = str(random.randint(0,9))
search = ("img_"+a+b+c+d)
elif cam == "two":
a = str(random.randint(2012,2016))
b = str(random.randint(1,12)).zfill(2)
c = str(random.randint(1,29)).zfill(2)
search = ("IMG_"+a+b+c)
elif cam == "three":
a = str(random.randint(1,500)).zfill(4)
search = ("IMAG_"+a)
elif cam == "four":
a = str(random.randint(0,9))
b = str(random.randint(0,9))
c = str(random.randint(0,9))
d = str(random.randint(0,9))
search = ("DSC_"+a+b+c+d)
page = urllib.request.urlopen("https://www.bing.com/images/search?q="+search+"&safesearch=off")
read = page.read()
tree = lxml.etree.HTML(read)
images = tree.xpath('//a[@class = "thumb"]/@href')
number = random.randint(1,len(images))-1
image = images[number]
print("Successfully returned an image")
print("")
return(image)
def movieFunc():
try:
print("Creating IMDb object")
ia = imdb.IMDb()
print("Picking a movie")
movs = open("movies.txt", "r")
movlist = movs.read().split("\n")
mov = random.choice(movlist)
movs.close()
print("Searching for "+mov)
s_result = ia.search_movie(mov)
print("Getting the data")
movie = s_result[0]
ia.update(movie)
cast = movie['cast']
pcast = ""
for x in range(3):
if cast[x]:
pcast += cast[x]['name']+", "
print("Successfully ran !movie")
print("")
return(movie['title'], movie['plot'][0].split("::")[0], movie['cover url'].replace("150","600").replace("101","404"), pcast[:-2])
except:
print("Something bad happened...")
return("error","","","")
def parseChar(user : str, cmd : str = ""):
return swchar.parseChar(user,cmd)
def parseRoll(user : str, cmd : str = ""):
return swroll.parseRoll(user,cmd)
def spellFunc(content):
return lookupFuncs.spellFunc(content)
def monsterFunc(content):
return lookupFuncs.spellFunc(content)
def nameGen():
return generators.nameGen
def tavernGen():
return generators.tavernGen

28
funcs/help.txt Normal file
View File

@ -0,0 +1,28 @@
**!hello** - En venlig hilsen.
**!roll** - Rul terninger i xdy format. Kan udføre matematik udover rullende. Kan også gøre følgende:
kx: Beholder kun rul med værdien x.
rox: Genrul rul med værdien x første gang.
rrx: Genrul alle rul med værdien x
mix: Gør alle rul under x til x.
max: Gør alle rul over x til x.
rax: Genruller og tilføjer rul med værdien x.
l/h før x: For de laveste/højeste x rul.
**!spell** - Slå en besværgelse op.
**!monster** - Slå et monster op.
**!map** - Få et billede af Senkulpa kortet.
**!image** - Find et tilfældigt billede fra internettet.
**!movie** - Giver titlen på en tilfældig film fra Bedre Netflix
**!name** - Genererer et tilfældigt navn.
**!tavern** - Genererer en tilfældig tavern.
**!swchar** - Lader dig lave en Star Wars karakter. Du kan bruge kommandoer som "!swchar name Jared" eller "!swchar skills astrogation 3" til at ændre din karakters info.
**!swroll** - Lader dig rulle Star Wars terninger. Du kan skrive tal der repræsenterer antallet af hver terning i rækkefølgen: ability, proficiency, difficulty, challenge, boost, setback og force. Du behøver ikke skrive et tal til alle terningerne. Du kan også skrive forbogstavet for terningen du vil rulle før antallet, såsom "!swroll f2", der ruller 2 force terninger.

123
funcs/lookup/lookupFuncs.py Normal file
View File

@ -0,0 +1,123 @@
import math
import discord
import json
from funcs import gwendolynFuncs as gf
def modifier(statistic):
mods = math.floor((statistic-10)/2)
if mods >= 0:
mods = "+"+str(mods)
return(str(mods))
saves = ["strength_save","dexterity_save","constitution_save","intelligence_save","wisdom_save","charisma_save"]
abilities = ["acrobatics","animal_handling","arcana","athletics","deception","history","insight","intimidation","investigation","medicine","nature","perception","performance","persuasion","religion","sleight_of_hand","stealth","survival"]
def monsterFunc(content):
command = gf.cap(content.lower().replace("!monster ",""))
print("Looking up "+command)
if len(content.lower().split()) < 2:
print("Monster doesn't exist in database")
print("")
return("I don't know that monster...","","","","","")
else:
data = json.load(open('monsters.json', encoding = "utf8"))
for monster in data:
if str(command) == monster["name"]:
if monster["subtype"] != "":
typs = (monster["type"]+" ("+monster["subtype"]+")")
else:
typs = monster["type"]
con_mod = math.floor((monster["constitution"]-10)/2)
hit_dice = monster["hit_dice"]
stats = ("**Str:** "+str(monster["strength"])+" ("+modifier(monster["strength"])+")\t**Dex:** "+str(monster["dexterity"])+" ("+modifier(monster["dexterity"])+")\t**Con:** "+str(monster["constitution"])+" ("+modifier(monster["constitution"])+")\n**Int: **"+str(monster["intelligence"])+" ("+modifier(monster["intelligence"])+")\t**Wis: **"+str(monster["wisdom"])+" ("+modifier(monster["wisdom"])+")\t**Cha: **"+str(monster["charisma"])+" ("+modifier(monster["charisma"])+")")
saving_throws = ""
for save in saves:
if save in monster:
if monster[save] >= 0:
saving_throws += " "+gf.cap(save[:3])+" +"+str(monster[save])+","
else:
saving_throws += " "+gf.cap(save[:3])+" "+str(monster[save])+","
if saving_throws != "":
saving_throws = "\n**Saving Throws**"+saving_throws[:-1]
skills = ""
for skill in abilities:
if skill in monster:
if monster[skill] >= 0:
skills += " "+gf.cap(skill.replace("_"," "))+" +"+str(monster[skill])+","
else:
skills += " "+gf.cap(skill.replace("_"," "))+" "+str(monster[skill])+","
if skills != "":
skills = "\n**Skills**"+skills[:-1]
vulnerabilities = monster["damage_vulnerabilities"]
if vulnerabilities != "":
vulnerabilities = "\n**Damage Vulnerabilities** "+vulnerabilities
resistances = monster["damage_resistances"]
if resistances != "":
resistances = "\n**Damage Resistances** "+resistances
immunities = monster["damage_immunities"]
if immunities != "":
immunities = "\n**Damage Immunities** "+immunities
c_immunities = monster["condition_immunities"]
if c_immunities != "":
c_immunities = "\n**Condition Immunities** "+c_immunities
spec_ab = ""
if "special_abilities" in monster:
for ability in monster["special_abilities"]:
spec_ab += "\n\n***"+ability["name"]+".*** "+ability["desc"]
act = ""
if "actions" in monster:
for action in monster["actions"]:
act += "\n\n***"+action["name"]+".*** "+action["desc"]
react = ""
if "reactions" in monster:
for reaction in monster["reactions"]:
react += "\n\n***"+reaction["name"]+".*** "+reaction["desc"]
leg_act = ""
if "legendary_actions" in monster:
for action in monster["legendary_actions"]:
leg_act += "\n\n***"+action["name"]+".*** "+action["desc"]
if con_mod < 0:
hit_dice += (" - "+str(con_mod * int(monster["hit_dice"].replace("d"," ").split()[0])*(-1)))
if con_mod > 0:
hit_dice += (" + "+str(con_mod * int(monster["hit_dice"].replace("d"," ").split()[0])))
new_part = "\n--------------------"
monster_type = monster["size"]+" "+typs+", "+monster["alignment"]+"*"
basic_info = "\n**Armor Class** "+str(monster["armor_class"])+"\n**Hit Points** "+str(monster["hit_points"])+" ("+hit_dice+")\n**Speed **"+monster["speed"]+new_part+"\n"
text1 = (monster_type+new_part+basic_info+stats+new_part+saving_throws+skills+vulnerabilities+resistances+immunities+c_immunities+"\n**Senses** "+monster["senses"]+"\n**Languages** "+monster["languages"]+"\n**Challenge** "+monster["challenge_rating"])
text2 = (spec_ab)
text3 = (act)
text4 = (react)
text5 = (leg_act)
print("Returning monster information")
print("")
return(str(command),text1,text2,text3,text4,text5)
print("")
return("I don't know that monster...","","","","","")
def spellFunc(content):
command = gf.cap(content.lower().replace("!spell ",""))
print("Looking up "+command)
data = json.load(open('spells.json', encoding = "utf8"))
if str(command) in data:
print("Returning spell information")
spell_output = ("***"+str(command)+"***\n*"+str(data[str(command)]["level"])+" level "+str(data[str(command)]["school"])+"\nCasting Time: "+str(data[str(command)]["casting_time"])+"\nRange: "+str(data[str(command)]["range"])+"\nComponents: "+str(data[str(command)]["components"])+"\nDuration: "+str(data[str(command)]["duration"])+"*\n \n"+str(data[str(command)]["description"]))
else:
print("I don't know that spell")
spell_output = "I don't think that's a spell"
print("Successfully ran !spell")
return(spell_output)

18349
funcs/lookup/monsters.json Normal file

File diff suppressed because it is too large Load Diff

3645
funcs/lookup/spells.json Normal file

File diff suppressed because it is too large Load Diff

307
funcs/names.txt Normal file
View File

@ -0,0 +1,307 @@
Eddard Ned Stark
Robert Baratheon
Jaime Lannister
Catelyn Stark
Cersei Lannister
Daenerys Targaryen
Jorah Mormont
Viserys Targaryen
Jon Snow
Sansa Stark
Arya Stark
Robb Stark
Theon Greyjoy
Bran Stark
Joffrey Baratheon
Sandor The Hound Clegane
Tyrion Lannister
Khal Drogo
Petyr Littlefinger Baelish
Davos Seaworth
Samwell Tarly
Stannis Baratheon
Melisandre
Jeor Mormont
Bronn
Varys
Shae
Margaery Tyrell
Tywin Lannister
Talisa Maegyr
Ygritte
Gendry
Tormund Giantsbane
Brienne of Tarth
Ramsay Bolton
Gilly
Daario Naharis
Missandei
Ellaria Sand
Tommen Baratheon
Jaqen H'ghar
Roose Bolton
The High Sparrow
Grand Maester Pycelle
Meryn Trant
Hodor
Grenn
Osha
Rickon Stark
Ros
Gregor Clegane
Janos Slynt
Lancel Lannister
Myrcella Baratheon
Rodrik Cassel
Maester Luwin
Irri
Doreah
Kevan Lannister
Barristan Selmy
Rast
Maester Aemon
Pypar
Alliser Thorne
Othell Yarwyck
Loras Tyrell
Hot Pie
Beric Dondarrion
Podrick Payne
Eddison Tollett
Yara Greyjoy
Selyse Florent
Little Sam
Grey Worm
Qyburn
Olenna Tyrell
Shireen Baratheon
Meera Reed
Jojen Reed
Thoros of Myr
Yohn Royce
Olly
Mace Tyrell
The Waif
Bowen Marsh
Aragorn
Arwen
Bilbo
Boromir
Celeborn
Denethor
Elrond
Eomer
Eowyn
Faramir
Frodo
Galadriel
Gandalf
Gimli
Gollum
Legolas
Merry
Mouth of Sauron
Old Man Willow
Pippin
Radagast
Sam
Saruman
Sauron
Shelob
Theoden
Tom Bombadil
Treebeard
Witch king
Wormtongue
Adon
Methrammar Aerasume
Sernius Alathar
Alaundo
Alias
Alicia Kendrick
Arganth Snarrl
Khelben Arunsun
Jorus Azuremantle
Berg'inyon Baenre
Dantrag Baenre
Gromph Baenre
Liriel Baenre
Quenthel Baenre
Triel Baenre
Yvonnel Baenre
Balduron
Bruenor Battlehammer
Akabar Bel Akash
Belhifet
Aballister Bonaduce
Erevis Cale
Captain Deudermont
Catti-brie
Clacker
Companions of the Hall
Elaith Craulnober
Cyric
Danica Maupoissant
Montolio Debrouchee
Briza Do'Urden
Dinin Do'Urden
Malice Do'Urden
Maya Do'Urden
Nalfein Do'Urden
Shi'nayne Do'Urden
Vartha Do'Urden
Vierna Do'Urden
Drizzt Do'Urden
Dove Falconhand
Dragonbait
Gareth Dragonsbane
Elk Tribe
Ellifain
Elminster
Artemis Entreri
Errtu
Galaeron Nihmedu
Volothamp Geddarm
Halisstra Melarn
Halueth Never
Harkle Harpell
Taern Hornblade
Imoen
Ingeloakastimizilian
Innovindil
Ivan and Pikel Bouldershoulder
Jander Sunstar
Jarlaxle
Kelemvor Lyonsbane
Kierkan Rufo
Manshoon
Obould Many-Arrows
Minder the Golem
Minsc
Pharaun Mizzrym
Arilyn Moonblade
Narnra Shalace
Nasher Alagondar
Taegan Nightwind
Nimor Imphraezl
Thibbledorf Pwent
Regis Rumblebelly
Rizzen Do'Urden
Sammaster
Seven Sisters
Shandril Shessair
Alustriel Silverhand
The Simbul
Storm Silverhand
Sylune
Szass Tam
Tarathiel
Araevin Teshurr
Danilo Thann
Urlgen Threefist
Valas Hune
Vangerdahast
Wulfgar
Finder Wyvernspur
Yharaskrik
Zaknafein Do'Urden
Johnny Depp
Arnold Schwarzenegger
Jim Carrey
Emma Watson
Daniel Radcliffe
Leonardo DiCaprio
Tom Cruise
Brad Pitt
Charles Chaplin
Morgan Freeman
Tom Hanks
Hugh Jackman
Matt Damon
Sylvester Stallone
Will Smith
Clint Eastwood
Cameron Diaz
George Clooney
Steven Spielberg
Harrison Ford
Robert De Niro
Al Pacino
Robert Downey Jr.
Russell Crowe
Liam Neeson
Kate Winslet
Mark Wahlberg
Natalie Portman
Pierce Brosnan
Sean Connery
Orlando Bloom
Dwayne Johnson
Jackie Chan
Angelina Jolie
Adam Sandler
Scarlett Johansson
Heath Ledger
Anne Hathaway
Jessica Alba
Edward Norton
Keira Knightley
Bradley Cooper
Will Ferrell
Julia Roberts
Nicolas Cage
Daniel Craig
Keanu Reeves
Ian McKellen
Halle Berry
Bruce Willis
Samuel L. Jackson
Ben Stiller
Tommy Lee Jones
Antonio Banderas
Denzel Washington
Steve Carell
Shia LaBeouf
Megan Fox
James Franco
Mel Gibson
Vin Diesel
Tim Allen
Robin Williams
Kevin Spacey
Jason Biggs
Seann William Scott
Jean-Claude Van Damme
Zach Galifianakis
Owen Wilson
Christian Bale
Peter Jackson
Sandra Bullock
Bruce Lee
Drew Barrymore
Macaulay Culkin
Jack Nicholson
Bill Murray
Sigourney Weaver
Jake Gyllenhaal
Kamal Haasan
Jason Statham
Jet Li
Kate Beckinsale
Rowan Atkinson
Marlon Brando
John Travolta
Channing Tatum
Ben Affleck
Shah Rukh Khan
Jennifer Aniston
Emma Stone
Chris Hemsworth
James McAvoy
James Cameron
Amitabh Bachchan
Brendan Fraser
Rachel McAdams
Tom Hiddleston
Aamir Khan
Rajinikanth

48
funcs/other/generators.py Normal file
View File

@ -0,0 +1,48 @@
import numpy as np
import random
def make_pairs(corpus):
for i in range(len(corpus)-1):
yield (corpus[i], corpus[i+1])
def nameGen():
names = open('names.txt', encoding='utf8').read()
corpus = list(names)
pairs = make_pairs(corpus)
word_dict = {}
for word_1, word_2 in pairs:
if word_1 in word_dict.keys():
word_dict[word_1].append(word_2)
else:
word_dict[word_1] = [word_2]
first_word = random.choice(corpus)
while first_word.islower() or first_word == " " or first_word == "-" or first_word == "\n":
first_word = random.choice(corpus)
chain = [first_word]
done = False
while done == False:
new_letter = random.choice(word_dict[chain[-1]])
chain.append(new_letter)
if new_letter == "\n":
done = True
genName = "".join(chain)
print("Generated "+genName+"\n")
return(genName)
def tavernGen():
fp = ["The Silver","The Golden","The Staggering","The Laughing","The Prancing","The Gilded","The Running","The Howling","The Slaughtered","The Leering","The Drunken","The Leaping","The Roaring","The Frowning","The Lonely","The Wandering","The Mysterious","The Barking","The Black","The Gleaming","The Tap-Dancing","The Sad","The Sexy","The Artificial","The Groovy","The Merciful","The Confused","The Pouting","The Horny","The Okay","The Friendly","The Hungry","The Handicapped","The Fire-breathing","The One-Eyed","The Psychotic","The Mad","The Evil","The Idiotic"]
sp = ["Eel","Dolphin","Dwarf","Pegasus","Pony","Rose","Stag","Wolf","Lamb","Demon","Goat","Spirit","Horde","Jester","Mountain","Eagle","Satyr","Dog","Spider","Star","Dad","Rat","Jeremy","Mouse","Unicorn","Pearl","Ant","Crab","Penguin","Octopus","Lawyer","Ghost","Toad","Handjob","Immigrant","SJW","Dragon","Bard","Sphinx","Soldier","Salmon","Owlbear","Kite","Frost Giant","'̶̧̗̣̰̞̜̤̦̖͗̈́̏͊͒͜+̴͎̰͓̱̻̝̬̼͕̥͍̪͕̮͙͂͝*̶̲̓̊̏'̷̥̺͈̞͒̆̏͋̀̐̇͆̓͊͠'̷͖̱̟̟͉̝̪̮͕̃͑́̍͆̓̌͒̄͛̇͘̚ͅ!̷̡̻̈́#̸̳̰̿̿̏͐̏̓̌̚̚͠¨̷̟͙̱͎̟̱̅̀͋̇͗͂͋͋̕͘´̴̡̡͎͔̦̜̟̼̠̰̤͋́̀̓́̄́̏͂̀͜.̸̛̭͍̮̜͑̋̀̋̈́̇̆̆̌_̸̡̥̜̞̝̮̑͑̓̓̇͜͜^̴̡̢͕̠̖̤̺̭̮̙͕̼̳̺̼͋̿̏̎̑͑̊̀̅͐̚͝͝","Arsonist"]
tp = [" Tavern"," Inn","","","","","","","","",""]
genTav = random.choice(fp)+" "+random.choice(sp)+random.choice(tp)
print("Generated "+genTav+"\n")
return(genTav)

28
funcs/other/movie.py Normal file
View File

@ -0,0 +1,28 @@
import imdb
import random
def movieFunc():
print("Running !movie")
print("Creating IMDb object")
ia = imdb.IMDb()
print("Picking a movie")
movs = open("movies.txt", "r")
movlist = movs.read().split("\n")
mov = random.choice(movlist)
movs.close()
print("Searching")
s_result = ia.search_movie(mov)
print("Picking the movie")
movie = s_result[0]
ia.update(movie)
cast = movie['cast']
pcast = ""
for x in range(3):
if cast[x]:
pcast += cast[x]['name']+", "
print("Successfully ran !movie")
print("")
return(movie['title'], movie['plot'][0].split("::")[0], movie['cover url'].replace("150","600").replace("101","404"), pcast[:-2])

1167
funcs/other/movies.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,2 @@
{
}

34
funcs/swfuncs/skills.json Normal file
View File

@ -0,0 +1,34 @@
{
"Astrogation" : "Intellect",
"Computers" : "Intellect",
"Cool" : "Presence",
"Vigilance" : "Willpower",
"Mechanics" : "Intellect",
"Melee" : "Brawn",
"Perception" : "Cunning",
"Piloting - Space" : "Agility",
"Ranged - Heavy" : "Agility",
"Ranged - Light" : "Agility",
"Athletics" : "Brawn",
"Coercion" : "Willpower",
"Coordination" : "Agility",
"Charm" : "Presence",
"Medicine" : "Intellect",
"Negotiation" : "Presence",
"Piloting - Planetary" : "Agility",
"Stealth" : "Agility",
"Skullduggery" : "Cunning",
"Brawl" : "Brawn",
"Discipline" : "Willpower",
"Gunnery" : "Agility",
"Core Worlds" : "Intellect",
"Outer Rim" : "Intellect",
"Underworld" : "Intellect",
"Leadership" : "Presence",
"Lore" : "Intellect",
"Resilience" : "Brawn",
"Streetwise" : "Cunning",
"Survival" : "Cunning",
"Xenology" : "Intellect",
"Lightsaber" : "Brawn"
}

31
funcs/swfuncs/skills.txt Normal file
View File

@ -0,0 +1,31 @@
Astrogation
Computers
Cool
Vigilance
Mechanics
Melee
Perception
Piloting - Space
Ranged - Heavy
Ranged - Light
Athletics
Coercion
Coordination
Charm
Medicine
Negotiation
Piloting - Planetary
Stealth
Skullduggery
Brawl
Discipline
Gunnery
Core Worlds
Outer Rim
Underworld
Leadership
Lore
Resilience
Streetwise
Survival
Xenology

182
funcs/swfuncs/swchar.py Normal file
View File

@ -0,0 +1,182 @@
import json
import string
def getName(user : str):
with open("characters.json", "r") as f:
data = json.load(f)
if user in data:
return data[user]["Name"]
else:
return user
def setUpDict(cmd : dict):
if bool(dict):
keys = list(cmd)
values = list(cmd.values())
result = ""
if type(values[0]) is dict:
return ", ".join(values)
else:
for x in range(len(keys)):
if x%3 != 2:
result += "**" + keys[x] + "**" + ": " + str(values[x]) + " "
else:
result += "**" + keys[x] + "**" + ": " + str(values[x]) + "\n"
return result
else:
return "There doesn't seem to be anything here..."
def lookUp(data : dict, key : str, cmd : str = ""):
if cmd == " ":
cmd = ""
elif cmd != "":
while cmd[0] == " ":
cmd = cmd[1:]
if cmd == "":
break
if key in data:
if cmd == "":
if type(data[key]) is dict:
return setUpDict(data[key])
else:
return data[key]
elif cmd[0] == '+':
try:
cmd = cmd[1:]
while cmd[0] == ' ':
cmd = cmd[1:]
except:
return "Can't do that"
if type(data[key]) is int:
try:
newValue = data[key] + int(cmd)
data[key] = newValue
return data
except:
return "Can't add that"
else:
return "Can't add that"
else:
while cmd[0] == ' ':
cmd = cmd[1:]
try:
cmd = type(data[key])(cmd)
data[key] = cmd
return data
except:
return "Wrong data type"
else:
return key + " doesn't exist"
def characterSheet(character : dict):
divider = "\n----------\n"
name = character["Name"]
text1 = "Species: "+character["Species"]+"\nCareer: "+character["Career"]
text2 = setUpDict(character["Characteristics"])
text3 = setUpDict(character["Skills"])
return name, text1+"\n\n"+text2+divider+text3
def charData(user : str,cmd : str):
with open("characters.json", "r") as f:
data = json.load(f)
key = string.capwords(cmd.split(" ")[0])
cmd = cmd[len(key):]
if cmd == " ":
cmd = ""
elif cmd != "":
while cmd[0] == " ":
cmd = cmd[1:]
if cmd == "":
break
if user in data:
if key in data[user]:
if type(data[user][key]) is dict:
if cmd == "":
return setUpDict(data[user][key])
else:
newKey = string.capwords(cmd.split(" ")[0])
newcmd = cmd[len(newKey):]
lookUpResult = lookUp(data[user][key],newKey,newcmd)
if type(lookUpResult) is dict:
data[user][key] = lookUpResult
with open("characters.json", "w") as f:
json.dump(data,f,indent = 4)
return "Changed " + data[user]["Name"] + "'s " + key
else:
return lookUpResult
else:
if cmd == "":
return data[user][key]
elif cmd[0] == '+':
try:
cmd = cmd[1:]
while cmd[0] == ' ':
cmd = cmd[1:]
except:
return "Can't do that"
if type(data[user][key]) is int:
try:
data[user][key] += int(cmd)
return "Added " + cmd + " to " + user + "'s " + key
except:
return "Can't add that"
else:
return "Can't add that"
else:
data[user][key] = cmd
with open("characters.json", "w") as f:
json.dump(data,f,indent = 4)
return "Changed " + data[user]["Name"] + "'s " + key +" to " + cmd
else:
return "Couldn't find that data. Are you sure you spelled it correctly?"
else:
return "You don't have a character. You can make one with !swchar"
def parseChar(user : str, cmd : str):
with open("characters.json", "r") as f:
data = json.load(f)
if cmd == " ":
cmd = ""
elif cmd != "":
while cmd[0] == " ":
cmd = cmd[1:]
if cmd == "":
break
if cmd == "":
if user in data:
return characterSheet(data[user])
else:
with open("templates.json", "r") as f:
templates = json.load(f)
newChar = templates["Character"]
data[user] = newChar
with open("characters.json", "w") as f:
json.dump(data,f,indent = 4)
return "", "Character for " + user + " created"
else:
return "", charData(user,cmd)
def lightsaberChar(user : str):
with open("characters.json", "r") as f:
data = json.load(f)
if user in data:
return data[user]["Lightsaber Characteristic"]
def userHasChar(user : str):
with open("characters.json", "r") as f:
data = json.load(f)
return user in data

169
funcs/swfuncs/swroll.py Normal file
View File

@ -0,0 +1,169 @@
import random
import re
import string
import json
import swchar
with open("skills.json", "r") as f:
skillData = json.load(f)
def roll(abi : int = 1, prof : int = 0, dif : int = 3, cha : int = 0, boo : int = 0, setb : int = 0, force : int = 0):
result = ""
for x in range(abi):
result += random.choice(["","S","S","SS","A","A","SA","AA"])
for x in range(prof):
result += random.choice(["","S","S","SS","SS","A","SA","SA","SA","AA","AA","R"])
for x in range(dif):
result += random.choice(["","F","FF","H","H","H","HH","FH"])
for x in range(cha):
result += random.choice(["","F","F","FF","FF","H","H","FH","FH","HH","HH","D"])
for x in range(boo):
result += random.choice(["","","S","SA","AA","A"])
for x in range(setb):
result += random.choice(["","","F","F","H","H"])
for x in range (force):
result += random.choice(["B","B","B","B","B","B","BB","L","L","Ll","LL","LL"])
return result
def simplify(result : str):
simp = ""
success = (result.count('S') + result.count('R')) - (result.count('F') + result.count('D'))
advantage = result.count('A') - result.count('H')
result = re.sub("S|A|F|H","",result)
if success > 0:
for x in range(success):
simp += "S"
elif success < 0:
for x in range(abs(success)):
simp += "F"
if advantage > 0:
for x in range(advantage):
simp += "A"
elif advantage < 0:
for x in range(abs(advantage)):
simp += "H"
simp += result
return simp
def resultToEmoji(result : str):
emoji = ""
for char in result:
if char == 'S':
emoji += "<:success:690971244971163718> "
if char == 'A':
emoji += "<:advantage:690970761611051079> "
if char == 'R':
emoji += "<:swtriumph:690971267486187643> "
if char == 'F':
emoji += "<:failure:690970957786906664> "
if char == 'H':
emoji += "<:threat:690971009469382656> "
if char == 'D':
emoji += "<:despair:690971200163414238> "
if char == 'L':
emoji += "<:light:691010089905029171>"
if char == 'B':
emoji += "<:dark:691010101901000852>"
return emoji
def diceToEmoji(dice : list):
emoji = ""
for x in range(dice[0]):
emoji += "<:ability:690974213397282826> "
for x in range(dice[1]):
emoji += "<:proficiency:690973435354153071> "
for x in range(dice[2]):
emoji += "<:difficulty:690973992470708296> "
for x in range(dice[3]):
emoji += "<:challenge:690973419906400306> "
for x in range(dice[4]):
emoji += "<:boost:690972178216386561> "
for x in range(dice[5]):
emoji += "<:setback:690972157890658415> "
for x in range(dice[6]):
emoji += "<:force:690973451883774013> "
return emoji
def getDice(user : str, skill : str):
return "yes"
def parseRoll(user : str,cmd : str = ""):
cmd = re.sub(' +',' ',cmd.upper()) + " "
if cmd[0] == " ":
cmd = cmd[1:]
commands = cmd.split(" ")
if commands[0] == "":
rollParameters = [1,0,3,0,0,0,0]
else:
rollParameters = [0,0,0,0,0,0,0]
if string.capwords(commands[0]) in skillData:
if swchar.userHasChar:
skillLevel = swchar.charData(user,"Skills " + string.capwords(commands[0]))
if string.capwords(commands[0]) == "Lightsaber":
charLevel = swchar.charData(user,"Characteristics " + swchar.lightsaberChar(user))
else:
charLevel = swchar.charData(user,"Characteristics " + skillData[string.capwords(commands[0])])
abilityDice = abs(charLevel-skillLevel)
proficiencyDice = min(skillLevel,charLevel)
commands = [str(abilityDice)] + [str(proficiencyDice)] + commands[1:]
else:
return "You don't have a user. You can make one with !swchar"
elif string.capwords(commands[0]) in ["Ranged","Piloting"]:
if string.capwords(commands[0]) == "Ranged":
return "Did you mean \"Ranged - Heavy\" or \"Ranged - Light\""
else:
return "Did you mean \"Piloting - Planetary\" or \"Piloting - Space\""
try:
for x in range(len(commands)):
if commands[x-1] != "":
if commands[x-1][0] == "A":
rollParameters[0] = int(commands[x-1].replace("A",""))
elif commands[x-1][0] == "P":
rollParameters[1] = int(commands[x-1].replace("P",""))
elif commands[x-1][0] == "D":
rollParameters[2] = int(commands[x-1].replace("D",""))
elif commands[x-1][0] == "C":
rollParameters[3] = int(commands[x-1].replace("C",""))
elif commands[x-1][0] == "B":
rollParameters[4] = int(commands[x-1].replace("B",""))
elif commands[x-1][0] == "S":
rollParameters[5] = int(commands[x-1].replace("S",""))
elif commands[x-1][0] == "F":
rollParameters[6] = int(commands[x-1].replace("F",""))
else:
rollParameters[x-1] = int(commands[x-1])
except:
return "Invalid input!"
rollResults = roll(rollParameters[0],rollParameters[1],rollParameters[2],rollParameters[3],rollParameters[4],rollParameters[5],rollParameters[6])
simplified = simplify(rollResults)
name = swchar.getName(user)
if simplified != rollResults:
return name + " rolls " + diceToEmoji(rollParameters) + "\nResult: " + resultToEmoji(rollResults) + "\nSimplified: " + resultToEmoji(simplify(rollResults))
else:
return name + " rolls " + diceToEmoji(rollParameters) + "\nResult: " + resultToEmoji(rollResults)

View File

@ -0,0 +1,73 @@
{
"Character": {
"Name": "New Character",
"Species": "",
"Career": "",
"Specialization Trees": [],
"Soak": 0,
"Wound Threshold": 0,
"Wounds": 0,
"Strain Threshold": 0,
"Strain": 0,
"Defense, Ranged": 0,
"Defense, Melee": 0,
"Force Rating": 0,
"Characteristics": {
"Brawn": 0,
"Agility": 0,
"Intellect": 0,
"Cunning": 0,
"Willpower": 0,
"Presence": 0
},
"Skills": {
"Astrogation": 0,
"Athletics": 0,
"Brawl": 0,
"Charm": 0,
"Coercion": 0,
"Computers": 0,
"Cool": 0,
"Coordination": 0,
"Core Worlds": 0,
"Discipline": 0,
"Gunnery": 0,
"Leadership": 0,
"Lightsaber": 0,
"Lore": 0,
"Mechanics": 0,
"Medicine": 0,
"Melee": 0,
"Negotiation": 0,
"Outer Rim": 0,
"Perception": 0,
"Piloting - Planetary": 0,
"Piloting - Space": 0,
"Ranged - Heavy": 0,
"Ranged - Light": 0,
"Resilience": 0,
"Skullduggery": 0,
"Stealth": 0,
"Streetwise": 0,
"Survival": 0,
"Underworld": 0,
"Vigilance": 0,
"Xenology": 0
},
"Lightsaber Characteristic": "Brawn",
"Obligations": {},
"Morality": {
"Emotional Weakness": "",
"Emotional Strength": "",
"Conflict": "",
"Morality": ""
},
"Credits": 0,
"Equipment": [],
"Armor": "",
"Critical Injuries": {},
"Weapons": {},
"Talents": {},
"Force Powers": {}
}
}