First real release

Still pretty rough though...
This commit is contained in:
Alan Mason 2012-09-28 02:19:19 -06:00
parent f274b980dc
commit 2cdea60982
2 changed files with 161 additions and 104 deletions

BIN
SpellBurner.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

View file

@ -1,7 +1,7 @@
# Burning Wheel - Spell Burner
# By 2Shirt (Alan Mason)
#
# Version 0.14a
# Version 1.0
from tkinter import *
from tkinter import ttk
from math import ceil, floor, log
@ -144,19 +144,26 @@ facetsMaBu = {
weaponLength = ['Shortest', 'Short', 'Long', 'Longer', 'Longest']
def getFacetTypes():
def get_facet_types():
"""Return types of Facets as as list"""
return sorted(facetsMaBu.keys())
def getFacetOptions(facet):
return sorted(facetsMaBu[facet].keys())
def get_facet_options(type):
"""Return options of facet type 'type' as as list"""
return sorted(facetsMaBu[type].keys())
def getFacetActions(facet, option):
def get_facet_actions(facet, option):
"""Return actions of facet 'type', 'option' as an int()"""
return facetsMaBu[facet][option]['Actions']
def getFacetOb(facet, option):
def get_facet_ob(facet, option):
"""Return obstacle of facet['type']['option'] as an int()"""
return facetsMaBu[facet][option]['Ob']
def getElementWeaponStats(elements, origins, aoes):
def get_weapon_stats(elements, origins, aoes):
"""Return weapon stats, as a hash
based on list(elements), list(origins), & list(aoes)"""
weaponStats = {}
for e in elements:
try:
@ -184,7 +191,8 @@ def getElementWeaponStats(elements, origins, aoes):
pass
return weaponStats
def generateRange(min, max):
def generate_range(min, max):
""" Return a list of int()'s from min to max (inclusive)"""
rangeList = []
if min > max:
# Uh....
@ -196,7 +204,10 @@ def generateRange(min, max):
rangeList.append(str(i))
return rangeList
def roundMath(x):
def round_math(x):
"""Round to the nearest int()
(e.g. 1.5 -> 2.0, 2.5 -> 3.0, 2.4 -> 2.0)"""
if (x - floor(x) >= 0.5):
return floor(x) + 1
else:
@ -204,14 +215,16 @@ def roundMath(x):
class Facet():
def reset(self, *args):
"""Reset facet for a new spell"""
self.actions.set('0')
self.ob.set('0')
self.option.set('')
self.type.set(self.default)
self.optionSelect['values'] = []
self.updateOptions()
self.update_options()
def destroy(self, *args):
"""Destroy facet for a new spell"""
try:
self.obCombobox.destroy()
except AttributeError:
@ -222,9 +235,10 @@ class Facet():
self.actionsLabel.destroy()
self.actionsValueLabel.destroy()
def updateOptions(self, *args):
def update_options(self, *args):
"""update obCombobox based on selected facet type"""
try:
self.optionSelect['values'] = getFacetOptions(self.type.get())
self.optionSelect['values'] = get_facet_options(self.type.get())
except KeyError:
pass
self.actions.set('0')
@ -236,9 +250,10 @@ class Facet():
self.obValueLabel.grid(column=6, row=self.row, sticky=W)
except AttributeError:
pass
self.frame.updateAll()
self.frame.update_all()
def updateStats(self, *args):
def update_stats(self, *args):
"""update Actions on Ob based on selected facet type & option"""
if self.option.get() == 'Anima':
try:
self.obValueLabel.destroy()
@ -248,29 +263,30 @@ class Facet():
self.obCombobox = ttk.Combobox(self.frame, textvariable=self.ob, width=2)
self.obCombobox['values'] = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
self.obCombobox.state(['readonly'])
self.obCombobox.bind('<<ComboboxSelected>>', self.frame.updateAll)
self.obCombobox.bind('<<ComboboxSelected>>', self.frame.update_all)
self.obCombobox.grid(column=6, row=self.row, sticky=W)
else:
try:
self.obCombobox.destroy()
except AttributeError:
pass
self.ob.set(getFacetOb(self.type.get(), self.option.get()))
self.ob.set(get_facet_ob(self.type.get(), self.option.get()))
self.obValueLabel = ttk.Label(self.frame, textvariable=self.ob)
self.obValueLabel.grid(column=6, row=self.row, sticky=W)
self.actions.set(getFacetActions(self.type.get(), self.option.get()))
self.frame.updateAll()
self.actions.set(get_facet_actions(self.type.get(), self.option.get()))
self.frame.update_all()
def createWidgets(self):
def create_widgets(self):
"""Create widgets upon instantiation"""
self.typeSelect = ttk.Combobox(self.frame, textvariable=self.type, width=18)
self.typeSelect['values'] = getFacetTypes()
self.typeSelect['values'] = get_facet_types()
self.typeSelect.state(['readonly'])
self.typeSelect.bind('<<ComboboxSelected>>', self.updateOptions)
self.typeSelect.bind('<<ComboboxSelected>>', self.update_options)
self.typeSelect.grid(column=1, row=self.row, columnspan=2, sticky=(W, E))
self.optionSelect = ttk.Combobox(self.frame, textvariable=self.option)
self.optionSelect.state(['readonly'])
self.optionSelect.bind('<<ComboboxSelected>>', self.updateStats)
self.optionSelect.bind('<<ComboboxSelected>>', self.update_stats)
self.optionSelect.grid(column=3, row=self.row, columnspan=2, sticky=(W, E))
self.obLabel = ttk.Label(self.frame, text='Ob:', width=3)
@ -285,16 +301,28 @@ class Facet():
self.actionsValueLabel = ttk.Label(self.frame, textvariable=self.actions, width=3)
self.actionsValueLabel.grid(column=8, row=self.row, sticky=W)
def getActions(self):
def get_actions(self):
"""return Actions as float()
Will return 0.0 if facet type/option not set"""
return float(self.actions.get())
def getOb(self):
def get_ob(self):
"""return Ob as int()
Will return 0 if facet type/option not set"""
return float(self.ob.get())
def getOption(self):
def get_option(self):
"""return facet option as str()
Will return '' if facet type not set"""
return str(self.option.get())
def getType(self):
def get_type(self):
"""return facet type as str()
Will return '' if facet type not set"""
return str(self.type.get())
def __init__(self, frame, row, default=''):
@ -308,32 +336,34 @@ class Facet():
self.option = StringVar()
self.type = StringVar()
self.type.set(default)
self.createWidgets()
self.create_widgets()
try:
self.optionSelect['values'] = getFacetOptions(self.type.get())
self.optionSelect['values'] = get_facet_options(self.type.get())
except KeyError:
pass
class Distiller():
def updateStats(self, *args):
def update_stats(self, *args):
"""Update Actions/Ob totals based on facet selections"""
self.obTmp = 0
self.actionsTmp = 0
for x in self.tobedistilled:
try:
self.obTmp += x.getOb()
self.actionsTmp += x.getActions()
self.obTmp += x.get_ob()
self.actionsTmp += x.get_actions()
except AttributeError:
for y in x:
self.obTmp += y.getOb()
self.actionsTmp += y.getActions()
self.obTmp += y.get_ob()
self.actionsTmp += y.get_actions()
if self.final:
self.ob.set(str(max(1,roundMath(self.obTmp/2))))
self.actions.set(str(max(1,roundMath(self.actionsTmp/2))))
self.ob.set(str(max(1,round_math(self.obTmp/2))))
self.actions.set(str(max(1,round_math(self.actionsTmp/2))))
else:
self.ob.set(str(self.obTmp/2))
self.actions.set(str(self.actionsTmp/2))
def createWidgets(self):
def create_widgets(self):
"""Create widgets upon instantiation"""
ttk.Separator(self.frame, orient=HORIZONTAL).grid(column=1, row=self.row, columnspan=8, sticky=(W, E))
self.titleLabel = ttk.Label(self.frame, text=self.title, justify='right')
@ -353,10 +383,16 @@ class Distiller():
ttk.Separator(self.frame, orient=HORIZONTAL).grid(column=1, row=self.row + 2, columnspan=8, sticky=(W, E))
def getActions(self):
def get_actions(self):
"""return Actions as float()
Will return 0.0 if facet type/option not set"""
return float(self.actions.get())
def getOb(self):
def get_ob(self):
"""return Ob as float()
Will return 0.0 if facet type/option not set"""
return float(self.ob.get())
def __init__(self, frame, row, title, tobedistilled, final=False, *args):
@ -367,15 +403,19 @@ class Distiller():
self.final = final
self.actions = StringVar()
self.ob = StringVar()
self.createWidgets()
self.updateStats()
self.create_widgets()
self.update_stats()
class MajorisSigil():
def addSigil(self, *args):
def add_sigil(self, *args):
"""Add an additional Majoris Sigil
(and remove the '+' Button in the process)"""
self.addButton.destroy()
self.frame.addMajorisSigil()
self.frame.add_majoris_sigil()
def destroy(self, *args):
"""destroy widgets for new Spell"""
self.addButton.destroy()
self.toggle.destroy()
self.obCombobox.destroy()
@ -383,6 +423,7 @@ class MajorisSigil():
self.actionsEntry.destroy()
def reset(self, *args):
"""Reset widgets for new Spell"""
self.enabled.set(False)
self.ob.set('')
self.obCombobox['values'] = ('')
@ -393,10 +434,11 @@ class MajorisSigil():
self.addButton.destroy()
except:
pass
self.addButton = ttk.Button(self.frame, text='+', command=self.addSigil, width=3)
self.addButton = ttk.Button(self.frame, text='+', command=self.add_sigil, width=3)
self.addButton.grid(column=1, row=self.row)
def toggleSigil(self, *args):
def toggle_sigil(self, *args):
"""Enable or Disable this Majoris Sigil"""
if self.enabled.get():
self.ob.set('1')
self.obCombobox.state(['!disabled'])
@ -410,9 +452,10 @@ class MajorisSigil():
self.obCombobox.state(['disabled'])
self.actionsEntry.delete(0,'end')
self.actionsEntry.state(['disabled'])
self.frame.updateAll()
self.frame.update_all()
def validateMultiplier(self, *args):
def validate_multiplier(self, *args):
"""Handle monkey input for Actions Multiplier"""
try:
if (float(self.actionsEntry.get()) < 10):
self.actionsEntry.delete(0,'end')
@ -426,24 +469,22 @@ class MajorisSigil():
except TypeError:
self.actionsEntry.delete(0,'end')
self.actionsEntry.insert(0, '10')
self.frame.updateAll()
self.frame.update_all()
return 1
def correctMultiplier(self, *args):
self.frame.updateAll()
def createWidgets(self):
self.addButton = ttk.Button(self.frame, text='+', command=self.addSigil, width=3)
def create_widgets(self):
"""Create widgets upon instantiation"""
self.addButton = ttk.Button(self.frame, text='+', command=self.add_sigil, width=3)
self.addButton.grid(column=1, row=self.row)
self.toggle = Checkbutton(self.frame, text='Majoris', command=self.toggleSigil,
self.toggle = Checkbutton(self.frame, text='Majoris', command=self.toggle_sigil,
variable=self.enabled, onvalue=True, offvalue=False)
self.toggle.grid(column=2, row=self.row, sticky=W)
self.obCombobox = ttk.Combobox(self.frame, textvariable=self.ob, width=2)
self.obCombobox.state(['readonly'])
self.obCombobox['values'] = ('')
self.obCombobox.bind('<<ComboboxSelected>>', self.frame.updateAll)
self.obCombobox.bind('<<ComboboxSelected>>', self.frame.update_all)
self.obCombobox.grid(column=3, row=self.row, sticky=W)
self.obCombobox.state(['disabled'])
@ -451,17 +492,23 @@ class MajorisSigil():
self.actionsLabel.grid(column=4, row=self.row, sticky=W)
self.actionsEntry = ttk.Entry(self.frame, validate='focusout',
validatecommand=self.validateMultiplier, width=5)
validatecommand=self.validate_multiplier, width=5)
self.actionsEntry.grid(column=5, row=self.row, sticky=W)
self.actionsEntry.state(['disabled'])
def getMultiplier(self):
def get_multiplier(self):
"""return Actions Multiplier as float()
Will return 0.0 if Majoris Sigil is not set"""
if self.enabled.get():
return float(self.actionsEntry.get())
else:
return 1.0
def getOb(self):
def get_ob(self):
"""return Ob as int()
Will return 0 if Majoris Sigil is not set"""
if self.enabled.get():
return int(self.ob.get())
else:
@ -475,10 +522,11 @@ class MajorisSigil():
self.enabled = BooleanVar()
self.enabled.set(False)
self.ob = StringVar()
self.createWidgets()
self.create_widgets()
class WeaponStats():
def updateDisplay(self, *args):
def update_display(self, *args):
"""Display weapon stats only if required facets are chosen"""
if self.enabled:
if not(self.prev):
self.line = ttk.Separator(self.frame, orient=HORIZONTAL)
@ -520,25 +568,28 @@ class WeaponStats():
except AttributeError:
pass
def updateStats(self, *args):
def update_stats(self, *args):
"""Update weapon stats
based on facets: 'Element', 'Origin', and 'Area of Effect'"""
# Initialize
self.prev = self.enabled & True # Not link?
self.enabled = True
self.spell = {}
self.tmp = {}
for f in self.frame.facets:
if f.getOption() == '':
if f.get_option() == '':
pass
elif f.getType() in self.spell:
if f.getOption() in self.spell[f.getType()]:
self.spell[f.getType()][f.getOption()] += 1
elif f.get_type() in self.spell:
if f.get_option() in self.spell[f.get_type()]:
self.spell[f.get_type()][f.get_option()] += 1
else:
self.spell[f.getType()][f.getOption()] = 1
self.spell[f.get_type()][f.get_option()] = 1
else:
self.spell[f.getType()] = {}
self.spell[f.getType()][f.getOption()] = 1
self.spell[f.get_type()] = {}
self.spell[f.get_type()][f.get_option()] = 1
try:
if self.spell[f.getType()][f.getOption()] > 1:
if self.spell[f.get_type()][f.get_option()] > 1:
self.frame.valid = False
except KeyError:
pass
@ -554,7 +605,7 @@ class WeaponStats():
# Update Stats
if self.enabled:
self.tmp = getElementWeaponStats(
self.tmp = get_weapon_stats(
list(self.spell['Element']),
list(self.spell['Origin']),
list(self.spell['Area of Effect'])
@ -580,7 +631,7 @@ class WeaponStats():
self.frame.valid = False
# Update display
self.updateDisplay()
self.update_display()
def __init__(self, frame, row, *args):
self.frame = frame
@ -595,7 +646,8 @@ class WeaponStats():
self.wVA = StringVar()
class App(ttk.Frame):
def addExtraFacet(self, *args):
def add_extra_facet(self, *args):
"""Add an extra Facet (limit 10)"""
self.facets.append(Facet(self, self.extrafacetStartRow+len(self.facets[5:])))
# Update Distiller
@ -603,25 +655,28 @@ class App(ttk.Frame):
(self.distiller1, self.distiller2, self.facets[4:]),
final=True
)
self.configureGrid()
self.configure_grid()
def addMajorisSigil(self, *args):
def add_majoris_sigil(self, *args):
"""Add an additional Majoris Sigil (limit 10)"""
if len(self.majorisSigils) < self.majorisMaxRows:
self.majorisSigils.append(MajorisSigil(self, self.majorisStartRow + len(self.majorisSigils)))
self.configureGrid()
self.configure_grid()
def configureGrid(self, *args):
def configure_grid(self, *args):
"""Update window"""
try:
self.extraFacetButton.destroy()
except:
pass
if len(self.facets[5:]) < self.extraFacetMaxRows:
self.extraFacetButton = ttk.Button(self, text='+', command=self.addExtraFacet, width=3)
self.extraFacetButton = ttk.Button(self, text='+', command=self.add_extra_facet, width=3)
self.extraFacetButton.grid(column=1, row=19)
for child in self.winfo_children(): child.grid_configure(padx=2, pady=2)
def reset(self, *args):
"""Reset all for a new Spell"""
for f in self.facets[0:5]:
f.reset()
for f in self.facets[5:]:
@ -635,14 +690,15 @@ class App(ttk.Frame):
self.minorisValue.set(0)
self.compressValue.set(0)
self.extendValue.set(0)
self.updateAll()
self.configureGrid()
self.update_all()
self.configure_grid()
def updateAll(self, *args):
def update_all(self, *args):
"""Update all stats for this Spell"""
### Distillations ###
self.distiller1.updateStats()
self.distiller2.updateStats()
self.distiller3.updateStats()
self.distiller1.update_stats()
self.distiller2.update_stats()
self.distiller3.update_stats()
### Final Spell ###
# Init Variables
@ -660,11 +716,11 @@ class App(ttk.Frame):
self.majActTotal = 1
self.majObTotal = 0
for m in self.majorisSigils:
self.majObTotal += m.getOb()
self.majActTotal *= m.getMultiplier()
self.majObTotal += m.get_ob()
self.majActTotal *= m.get_multiplier()
# After Final Distillation
self.subTotalAct = roundMath(self.distiller3.getActions())
self.subTotalOb = roundMath(self.distiller3.getOb())
self.subTotalAct = round_math(self.distiller3.get_actions())
self.subTotalOb = round_math(self.distiller3.get_ob())
# Before rounding
self.preAct = max(1, self.subTotalAct)*self.majActTotal*0.5**self.numCs
self.preEs = self.subTotalOb
@ -724,9 +780,9 @@ class App(ttk.Frame):
# Set limits
if self.numCap == 0:
self.capValue.set(False)
self.minorisCombobox['values'] = generateRange(self.minMin, self.maxMin)
self.compressCombobox['values'] = generateRange(self.minCs, self.maxCs)
self.extendCombobox['values'] = generateRange(self.minEs, self.maxEs)
self.minorisCombobox['values'] = generate_range(self.minMin, self.maxMin)
self.compressCombobox['values'] = generate_range(self.minCs, self.maxCs)
self.extendCombobox['values'] = generate_range(self.minEs, self.maxEs)
# Misc Checks
if self.preOb < ceil((self.preEs)/2):
@ -741,8 +797,8 @@ class App(ttk.Frame):
self.finalActions.set(self.postAct)
### Weapon Stats ###
self.weapon.updateStats()
self.configureGrid()
self.weapon.update_stats()
self.configure_grid()
### Warnings ###
if self.valid:
@ -753,7 +809,8 @@ class App(ttk.Frame):
else:
self.warningLabelText.set('[HOUSE RULED]')
def createWidgets(self):
def create_widgets(self):
"""Create widgets upon instantiation"""
# 1st Distillation
self.facets.append(Facet(self, 0, 'Element'))
self.facets.append(Facet(self, 1, 'Impetus'))
@ -773,7 +830,7 @@ class App(ttk.Frame):
# 3rd Distillation
self.facets.append(Facet(self, 10, 'Area of Effect'))
self.extraFacetButton = ttk.Button(self, text='+', command=self.addExtraFacet, width=3)
self.extraFacetButton = ttk.Button(self, text='+', command=self.add_extra_facet, width=3)
self.extraFacetButton.grid(column=1, row=19)
self.distiller3 = Distiller(self, 20, 'Final Distillation',
@ -785,7 +842,7 @@ class App(ttk.Frame):
self.sigilsLabel = ttk.Label(self, text='Sigils').grid(column=1, row=24)
# Adjustments - Cap & Minoris Sigil(S)
self.capCheckbutton = Checkbutton(self, text='Cap', command=self.updateAll,
self.capCheckbutton = Checkbutton(self, text='Cap', command=self.update_all,
variable=self.capValue, onvalue=True, offvalue=False)
self.capCheckbutton.grid(column=2, row=25, sticky=W)
@ -794,8 +851,8 @@ class App(ttk.Frame):
self.minorisCombobox = ttk.Combobox(self, textvariable=self.minorisValue, width=2)
self.minorisCombobox.state(['readonly'])
self.minorisCombobox['values'] = generateRange(0, 10)
self.minorisCombobox.bind('<<ComboboxSelected>>', self.updateAll)
self.minorisCombobox['values'] = generate_range(0, 10)
self.minorisCombobox.bind('<<ComboboxSelected>>', self.update_all)
self.minorisCombobox.grid(column=5, row=25, sticky=W)
# Adjustments - Majoris Sigil(S)
@ -807,8 +864,8 @@ class App(ttk.Frame):
self.compressCombobox = ttk.Combobox(self, textvariable=self.compressValue, width=2)
self.compressCombobox.state(['readonly'])
self.compressCombobox['values'] = generateRange(0, 10)
self.compressCombobox.bind('<<ComboboxSelected>>', self.updateAll)
self.compressCombobox['values'] = generate_range(0, 10)
self.compressCombobox.bind('<<ComboboxSelected>>', self.update_all)
self.compressCombobox.grid(column=3, row=36, sticky=W)
self.extendLabel = ttk.Label(self, text='Extensions')
@ -816,8 +873,8 @@ class App(ttk.Frame):
self.extendCombobox = ttk.Combobox(self, textvariable=self.extendValue, width=2)
self.extendCombobox.state(['readonly'])
self.extendCombobox['values'] = generateRange(0, 10)
self.extendCombobox.bind('<<ComboboxSelected>>', self.updateAll)
self.extendCombobox['values'] = generate_range(0, 10)
self.extendCombobox.bind('<<ComboboxSelected>>', self.update_all)
self.extendCombobox.grid(column=5, row=36, sticky=W)
# Final Spell Results
@ -864,7 +921,7 @@ class App(ttk.Frame):
menu_file.add_command(label='Close', command=quit)
menu_settings.add_checkbutton(label='Advanced Limiting',
variable=self.advanceLimits, onvalue=True, offvalue=False,
command=self.updateAll
command=self.update_all
)
self.capValue = BooleanVar()
@ -885,9 +942,9 @@ class App(ttk.Frame):
self.finalActions = StringVar()
self.finalActionsValue = 1
self.majorisSigils = []
self.createWidgets()
self.updateAll()
self.configureGrid()
self.create_widgets()
self.update_all()
self.configure_grid()
root = Tk()
root.title('Spell Burner')