From 390f062e0a3e2c76f4101abed8946df957d4856b Mon Sep 17 00:00:00 2001 From: zack Date: Thu, 23 Apr 2026 18:35:11 -0400 Subject: [PATCH] adding in flask --- __pycache__/app.cpython-312.pyc | Bin 0 -> 557 bytes __pycache__/ose.cpython-312.pyc | Bin 0 -> 17314 bytes app.py | 11 ++ main.py | 59 ++++---- ose.py | 238 ++++++++++++++++++++++++++++++++ requirements.txt | 1 + templates/sheet.html | 27 ++++ 7 files changed, 309 insertions(+), 27 deletions(-) create mode 100644 __pycache__/app.cpython-312.pyc create mode 100644 __pycache__/ose.cpython-312.pyc create mode 100644 app.py create mode 100755 ose.py create mode 100644 requirements.txt create mode 100644 templates/sheet.html diff --git a/__pycache__/app.cpython-312.pyc b/__pycache__/app.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..84ed64dbbf852688f6d9117c35e3df691f56cdbc GIT binary patch literal 557 zcmYLF!AcxK5UuW>S!a!th#+JkNOB2IKu7eXhzAMc$&0r|7$!TFtZ`;%=;;l+qOhW% zf1rMXtb+gHC6Iv72#F+@E?J3pk4%Xq-E2{d{tG;pFQJ}az|Gj-r`G+Zr5JS@2 zB6125L@b6Y&J5!*OL&zhqAD10K#o?IJc3aBW>F&{W6uu zG<)N5ZLh^)zN4Q>Y(yvng-I5N3j55jJ*oj%R2YlBd4f|=!}UNmi$(jOiX+JK9$bnp ze~{P&&)U$I!d&f+=5<6hTUSYZ!L(!YY8ti4$(Tgdl#NZ(&!tUIWtkv1t6uhfzn&)O z?}oJ<|E)~3cWKLy@ROhBI8&>KGOQ_-GasuAh*uN66iEl7{UwU$~ewcQ|cV-<|4k{-Lhf{w! OXG=W+e0;zLivI!Z@PE_* literal 0 HcmV?d00001 diff --git a/__pycache__/ose.cpython-312.pyc b/__pycache__/ose.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bc4aa9a614edf0cc606b650ae79faa9fd276296e GIT binary patch literal 17314 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 literal 0 HcmV?d00001 diff --git a/app.py b/app.py new file mode 100644 index 0000000..26f379e --- /dev/null +++ b/app.py @@ -0,0 +1,11 @@ +#!/usr/bin/python3 + +from ose import * +from flask import Flask, render_template + +app = Flask(__name__) + +@app.route('/') +def index(): + htmlBody = returnSheets('test') + return render_template("sheet.html", htmlBody=htmlBody) diff --git a/main.py b/main.py index a9ed162..36c1f85 100755 --- a/main.py +++ b/main.py @@ -3,22 +3,22 @@ import random armor= { 'None' : 9, 'Leather' : 7, 'Leather, Shield' : 6, 'Chain' : 5, 'Chain, Shield' : 4, 'Plate' : 3, 'Plate, Shield' : 2 } weapons = [ - { 'name' : 'battle axe', 'type' : 'melee', 'damage-dice' : 8}, - { 'name' : 'crossbow', 'type' : 'missle', 'damage-dice' : 6, 'ammo' : '20 bolts'}, - { 'name' : 'hand axe', 'type' : 'melee', 'damage-dice' : 6 }, - { 'name' : 'mace', 'type' : 'melee', 'damage-dice' : 6 , 'traits' : [ 'blunt' ] }, - { 'name' : 'pole arm', 'type' : 'melee', 'damage-dice' : 10 }, - { 'name' : 'short bow', 'type' : 'missle', 'damage-dice' : 6, 'ammo' : '20 arrows'}, - { 'name' : 'short sword', 'type' : 'melee', 'damage-dice' : 6 }, - { 'name' : 'silver dagger', 'type' : 'melee', 'damage-dice' : 4 }, - { 'name' : 'sling', 'type' : 'missle', 'damage-dice' : 4, 'ammo' : '20 stones', 'traits' : [ 'blunt' ] }, - { 'name' : 'staff', 'type' : 'melee', 'damage-dice' : 4 , 'traits' : [ 'blunt', 'slow' ] }, - { 'name' : 'spear', 'type' : 'melee', 'damage-dice' : 6 }, - { 'name' : 'sword', 'type' : 'melee', 'damage-dice' : 8 }, - { 'name' : 'war hammer', 'type' : 'melee', 'damage-dice' : 6 , 'traits' : [ 'blunt' ] } + { 'name' : 'battle axe', 'damage-dice' : 8, 'traits' : [ 'melee', 'slow', 'two-handed' ] }, + { 'name' : 'club', 'damage-dice' : 4, 'traits' : [ 'melee', 'blunt' ] }, + { 'name' : 'crossbow', 'damage-dice' : 6, 'traits' : [ 'missile', 'reload','slow','two-handed'], 'ammo' : '20 bolts'}, + { 'name' : 'hand axe', 'damage-dice' : 6, 'traits' : [ 'melee', 'missile'] }, + { 'name' : 'mace', 'damage-dice' : 6, 'traits' : [ 'melee', 'blunt' ] }, + { 'name' : 'pole arm', 'damage-dice' : 10, 'traits' : [ 'melee', 'brace', 'slow', 'two-handed' ] }, + { 'name' : 'short bow', 'damage-dice' : 6, 'traits' : [ 'missile', 'two-handed' ], 'ammo' : '20 arrows'}, + { 'name' : 'short sword', 'damage-dice' : 6, 'traits' : [ 'melee' ] }, + { 'name' : 'silver dagger','damage-dice' : 4, 'traits' : [ 'melee', 'missile' ] }, + { 'name' : 'sling', 'damage-dice' : 4, 'traits' : [ 'missile', 'blunt' ], 'ammo' : '20 stones'}, + { 'name' : 'staff', 'damage-dice' : 4, 'traits' : [ 'melee', 'blunt', 'slow', 'two-handed' ] }, + { 'name' : 'spear', 'damage-dice' : 6, 'traits' : [ 'melee', 'missile', 'brace' ] }, + { 'name' : 'sword', 'damage-dice' : 8, 'traits' : [ 'melee' ] }, + { 'name' : 'war hammer', 'damage-dice' : 6, 'traits' : [ 'melee', 'blunt' ] } ] - # Player Character Classes class Adventurer: def __init__(self, level=1, attributes={}) -> None: @@ -35,8 +35,15 @@ class Adventurer: self.torches = roll_dice(1,6) self.rations = roll_dice(1,6) self.equipment = [ 'backpack', 'tinderbox', 'waterskin' ] - self.weapons = [] - self.armor = [] + # all armor, individual classes may have overrides + self.possible_armor = list(armor.keys()) + # all weapons, individual classes may have overrides + self.possible_weapons = weapons + self.possible_melee_weapons = list(filter(lambda d: 'melee' in d['traits'], weapons)) + self.possible_missile_weapons = list(filter(lambda d: 'missile' in d['traits'], weapons)) + # each character should get 1 melee and 1 random (missle or melee) + self.weapons = [ random.choice(self.possible_melee_weapons), random.choice(self.possible_weapons) ] + self.armor = random.choice(self.possible_armor) def __str__(self): return f"{self.player_class}" @@ -53,8 +60,8 @@ class Adventurer: sheet.append('{0: <26}'.format(f"| Rations: {self.rations}")) sheet.append('{0: <26}'.format(f"| Armor: {self.armor}")) sheet.append('{0: <26}'.format(f"| Weapons:")) - sheet.append('{0: <26}'.format(f"| {self.weapons[0]}")) - sheet.append('{0: <26}'.format(f"| {self.weapons[1]}")) + sheet.append('{0: <26}'.format(f"| {self.weapons[0]['name'].title()}")) + sheet.append('{0: <26}'.format(f"| {self.weapons[1]['name'].title()}")) return sheet def get_attributes(self): @@ -78,9 +85,7 @@ class Fighter(Adventurer): Adventurer.__init__(self, level, attributes) self.player_class = "fighter" self.hp = roll_dice(self.level, 8) - self.armor = random.choice(list(armor.keys())) self.ac = armor[self.armor] - self.weapons = [ "sword", "dagger" ] class MagicUser(Adventurer): prime_requisite = "intelligence" @@ -89,9 +94,10 @@ class MagicUser(Adventurer): Adventurer.__init__(self, level, attributes) self.player_class = "magic user" self.hp = roll_dice(self.level, 4) - self.armor = random.choice(list(armor.keys())) + self.armor = "None" self.ac = armor[self.armor] - self.weapons = [ "sword", "dagger" ] + self.weapons = [ list(filter(lambda d: 'silver dagger' in d['name'],weapons))[0], { "name" : "" } ] + class Cleric(Adventurer): prime_requisite = "wisdom" @@ -102,7 +108,10 @@ class Cleric(Adventurer): self.hp = roll_dice(self.level, 6) self.armor = random.choice(list(armor.keys())) self.ac = armor[self.armor] - self.weapons = [ "sword", "dagger" ] + # clerics can only wield blunt weapons + self.possible_melee_weapons = list(filter(lambda d: 'blunt' in d['traits'] and 'melee' in d['traits'], weapons)) + self.possible_weapons = list(filter(lambda d: 'blunt' in d['traits'], weapons)) + self.weapons = [ random.choice(self.possible_melee_weapons), random.choice(self.possible_weapons) ] class Thief(Adventurer): prime_requisite = "dexterity" @@ -113,7 +122,6 @@ class Thief(Adventurer): self.hp = roll_dice(self.level, 4) self.armor = random.choice(list(armor.keys())) self.ac = armor[self.armor] - self.weapons = [ "sword", "dagger" ] class Dwarf(Adventurer): prime_requisite = "strength" @@ -124,7 +132,6 @@ class Dwarf(Adventurer): self.hp = roll_dice(self.level, 8) self.armor = random.choice(list(armor.keys())) self.ac = armor[self.armor] - self.weapons = [ "sword", "dagger" ] class Elf(Adventurer): prime_requisite = "intellgence" @@ -135,7 +142,6 @@ class Elf(Adventurer): self.hp = roll_dice(self.level, 6) self.armor = random.choice(list(armor.keys())) self.ac = armor[self.armor] - self.weapons = [ "sword", "dagger" ] class Halfling(Adventurer): prime_requisite = "dexterity" @@ -146,7 +152,6 @@ class Halfling(Adventurer): self.hp = roll_dice(self.level, 6) self.armor = random.choice(list(armor.keys())) self.ac = armor[self.armor] - self.weapons = [ "sword", "dagger" ] # Player Class Selector class ClassSelector(): diff --git a/ose.py b/ose.py new file mode 100755 index 0000000..d767a88 --- /dev/null +++ b/ose.py @@ -0,0 +1,238 @@ +#!/usr/bin/python3 +import random + +armor= { 'None' : 9, 'Leather' : 7, 'Leather, Shield' : 6, 'Chain' : 5, 'Chain, Shield' : 4, 'Plate' : 3, 'Plate, Shield' : 2 } +weapons = [ + { 'name' : 'battle axe', 'damage-dice' : 8, 'traits' : [ 'melee', 'slow', 'two-handed' ] }, + { 'name' : 'club', 'damage-dice' : 4, 'traits' : [ 'melee', 'blunt' ] }, + { 'name' : 'crossbow', 'damage-dice' : 6, 'traits' : [ 'missile', 'reload','slow','two-handed'], 'ammo' : '20 bolts'}, + { 'name' : 'hand axe', 'damage-dice' : 6, 'traits' : [ 'melee', 'missile'] }, + { 'name' : 'mace', 'damage-dice' : 6, 'traits' : [ 'melee', 'blunt' ] }, + { 'name' : 'pole arm', 'damage-dice' : 10, 'traits' : [ 'melee', 'brace', 'slow', 'two-handed' ] }, + { 'name' : 'short bow', 'damage-dice' : 6, 'traits' : [ 'missile', 'two-handed' ], 'ammo' : '20 arrows'}, + { 'name' : 'short sword', 'damage-dice' : 6, 'traits' : [ 'melee' ] }, + { 'name' : 'silver dagger','damage-dice' : 4, 'traits' : [ 'melee', 'missile' ] }, + { 'name' : 'sling', 'damage-dice' : 4, 'traits' : [ 'missile', 'blunt' ], 'ammo' : '20 stones'}, + { 'name' : 'staff', 'damage-dice' : 4, 'traits' : [ 'melee', 'blunt', 'slow', 'two-handed' ] }, + { 'name' : 'spear', 'damage-dice' : 6, 'traits' : [ 'melee', 'missile', 'brace' ] }, + { 'name' : 'sword', 'damage-dice' : 8, 'traits' : [ 'melee' ] }, + { 'name' : 'war hammer', 'damage-dice' : 6, 'traits' : [ 'melee', 'blunt' ] } +] + +# Player Character Classes +class Adventurer: + def __init__(self, level=1, attributes={}) -> None: + # using a get() method to pull an attribute else use a default value, https://python-academy.org/en/handbook/get + self.player_class = None + self.level = level + self.strength = attributes.get('strength', roll_dice(3,6)) + self.intelligence = attributes.get('intelligence', roll_dice(3,6)) + self.wisdom = attributes.get('wisdom', roll_dice(3,6)) + self.dexterity = attributes.get('dexterity', roll_dice(3,6)) + self.constitution = attributes.get('constitution', roll_dice(3,6)) + self.charisma = attributes.get('charisma', roll_dice(3,6)) + self.hp = 1 + self.torches = roll_dice(1,6) + self.rations = roll_dice(1,6) + self.equipment = [ 'backpack', 'tinderbox', 'waterskin' ] + # all armor, individual classes may have overrides + self.possible_armor = list(armor.keys()) + # all weapons, individual classes may have overrides + self.possible_weapons = weapons + self.possible_melee_weapons = list(filter(lambda d: 'melee' in d['traits'], weapons)) + self.possible_missile_weapons = list(filter(lambda d: 'missile' in d['traits'], weapons)) + # each character should get 1 melee and 1 random (missle or melee) + self.weapons = [ random.choice(self.possible_melee_weapons), random.choice(self.possible_weapons) ] + self.armor = random.choice(self.possible_armor) + + def __str__(self): + return f"{self.player_class}" + + def character_sheet(self): + sheet = [] + sheet.append('{0: <26}'.format(f"| {self.player_class.title()} - Level {self.level}")) + for key, val in self.get_attributes().items(): + key_string = "| " + '{0:12}'.format(f"{key}").capitalize() + f" {val}" + sheet += ['{0: <26}'.format(key_string)] + sheet.append('| ----------------------- ') + sheet.append('{0: <26}'.format(f"| HP: {self.hp} AC: {self.ac}")) + sheet.append('{0: <26}'.format(f"| Torches: {self.torches}")) + sheet.append('{0: <26}'.format(f"| Rations: {self.rations}")) + sheet.append('{0: <26}'.format(f"| Armor: {self.armor}")) + sheet.append('{0: <26}'.format(f"| Weapons:")) + sheet.append('{0: <26}'.format(f"| {self.weapons[0]['name'].title()}")) + sheet.append('{0: <26}'.format(f"| {self.weapons[1]['name'].title()}")) + return sheet + + def get_attributes(self): + attribute_list = ['strength', 'intelligence', 'wisdom', 'dexterity', 'constitution', 'charisma'] + return {k: self.__dict__[k] for k in attribute_list} + + def get_best_prime_attribute(self): + attribute_list = [ 'strength', 'intelligence', 'wisdom', 'dexterity' ] + prime_attributes = {k: self.__dict__[k] for k in attribute_list} + # return highest, found this at https://stackoverflow.com/a/280156 + return max(prime_attributes, key=prime_attributes.get) + + def roll_equipment(self): + print("testing!") + + +class Fighter(Adventurer): + prime_requisite = "strength" + requirements = None + def __init__(self, level, attributes={}) -> None: + Adventurer.__init__(self, level, attributes) + self.player_class = "fighter" + self.hp = roll_dice(self.level, 8) + self.ac = armor[self.armor] + +class MagicUser(Adventurer): + prime_requisite = "intelligence" + requirements = None + def __init__(self, level, attributes={}) -> None: + Adventurer.__init__(self, level, attributes) + self.player_class = "magic user" + self.hp = roll_dice(self.level, 4) + self.armor = "None" + self.ac = armor[self.armor] + self.weapons = [ list(filter(lambda d: 'silver dagger' in d['name'],weapons))[0], { "name" : "" } ] + + +class Cleric(Adventurer): + prime_requisite = "wisdom" + requirements = None + def __init__(self, level, attributes={}) -> None: + Adventurer.__init__(self, level, attributes) + self.player_class = "cleric" + self.hp = roll_dice(self.level, 6) + self.armor = random.choice(list(armor.keys())) + self.ac = armor[self.armor] + # clerics can only wield blunt weapons + self.possible_melee_weapons = list(filter(lambda d: 'blunt' in d['traits'] and 'melee' in d['traits'], weapons)) + self.possible_weapons = list(filter(lambda d: 'blunt' in d['traits'], weapons)) + self.weapons = [ random.choice(self.possible_melee_weapons), random.choice(self.possible_weapons) ] + +class Thief(Adventurer): + prime_requisite = "dexterity" + requirements = None + def __init__(self, level, attributes={}) -> None: + Adventurer.__init__(self, level, attributes) + self.player_class = "thief" + self.hp = roll_dice(self.level, 4) + self.armor = random.choice(list(armor.keys())) + self.ac = armor[self.armor] + +class Dwarf(Adventurer): + prime_requisite = "strength" + requirements = {'constitution' : 9 } + def __init__(self, level, attributes={}) -> None: + Adventurer.__init__(self, level, attributes) + self.player_class = "dwarf" + self.hp = roll_dice(self.level, 8) + self.armor = random.choice(list(armor.keys())) + self.ac = armor[self.armor] + +class Elf(Adventurer): + prime_requisite = "intellgence" + requirements = {'intelligence' : 9 } + def __init__(self, level, attributes={}) -> None: + Adventurer.__init__(self, level, attributes) + self.player_class = "elf" + self.hp = roll_dice(self.level, 6) + self.armor = random.choice(list(armor.keys())) + self.ac = armor[self.armor] + +class Halfling(Adventurer): + prime_requisite = "dexterity" + requirements = {'constitution' : 9, 'dexterity' : 9 } + def __init__(self, level, attributes={}) -> None: + Adventurer.__init__(self, level, attributes) + self.player_class = "halfling" + self.hp = roll_dice(self.level, 6) + self.armor = random.choice(list(armor.keys())) + self.ac = armor[self.armor] + +# Player Class Selector +class ClassSelector(): + def __init__(self, player: Adventurer) -> None: + self.player = player + # https://stackoverflow.com/questions/3862310/how-to-find-all-the-subclasses-of-a-class-given-its-name + # pull classes that do not have requirements + self.available_classes = [cls for cls in Adventurer.__subclasses__() if not cls.requirements] + # pull classes that do have requirements + self.classes_with_reqs = [cls for cls in Adventurer.__subclasses__() if cls.requirements] + # run function to randomly select an adventurer class + self.selected_class = self.selection() + + def return_class_by_best_attribute(self): + # for adventurer classes in available classes, return the one where that classes' prime requisite is equal to the players best attribute + return [adv_class for adv_class in self.available_classes if adv_class.prime_requisite == self.player.get_best_prime_attribute()][0] + + def return_classes_with_requirements(self): + p_attrs = self.player.get_attributes() + possible_classes = [] + for c in self.classes_with_reqs: + match_count = 0 + for r in c.requirements: + if p_attrs[r] >= c.requirements[r]: + match_count += 1 + if match_count >= len(c.requirements): + possible_classes.append(c) + return possible_classes + + def selection(self): + best_prime_attribute = self.player.get_best_prime_attribute() + # create an array of possible player classes, add the best choice per player's best core attributes + possible_classes = [ self.return_class_by_best_attribute() ] + possible_classes += self.return_classes_with_requirements() + # randomly select class + selected_class = random.choice(possible_classes) + return selected_class + +class PartyGenerator(): + def __init__(self, party_size=4) -> None: + self.size = party_size + self.adventurers = [] + self.adventurer_types = [] + + def gen_party(self): + while len(self.adventurers) < self.size: + new_player = Adventurer() + attempts = 0 + while new_player.player_class not in self.adventurer_types: + attempts += 1 + selected_class = ClassSelector(new_player).selection() + new_player = selected_class(new_player.level, new_player.get_attributes()) + # i couldnt randomly generate a scenario where a character couldn't be added, but it seems possible, so this is the hard cut off + if (new_player.player_class not in self.adventurer_types) or (attempts > 10): + self.adventurers.append(new_player) + self.adventurer_types.append(new_player.player_class) + + def get_character_sheets(self): + sheet_string = "" + for i in range(15): + for j in range(len(self.adventurers)): + adv = self.adventurers[j] + sheet_string += adv.character_sheet()[i] + sheet_string += '|\n' + return sheet_string + + def __str__(self): + return f"{self.adventurers}" + +# functions +def roll_dice(count, sides): + return sum(random.randint(1,sides) for _ in range(count)) + +def returnSheets(foo): + print('foo') + new_party = PartyGenerator() + new_party.gen_party() + return new_party.get_character_sheets() + +def main(): + sheet_string = returnSheets(foo) + +if __name__ == "__main__": + main() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..980a7fc --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +flash diff --git a/templates/sheet.html b/templates/sheet.html new file mode 100644 index 0000000..588a46e --- /dev/null +++ b/templates/sheet.html @@ -0,0 +1,27 @@ + + + + + + + FlaskTest + + + + + +
+
+

+

{{htmlBody}}
+

+
+
+ + + + +