refactored character and ability generation;stubbed out attack matrices
This commit is contained in:
parent
49adedbab9
commit
1e862d3b61
159
app.py
159
app.py
@ -3,11 +3,12 @@ from flask_cors import CORS
|
||||
from flask_restx import Api, Resource
|
||||
|
||||
from models import dice_model, ability_model, hp_model, character_model, encounter_model, ma_model
|
||||
from schemas import DiceSchema, CharacterSchema, EncounterSchema, MentalAttackSchema
|
||||
from schemas import DiceSchema, CharacterSchema, EncounterSchema, MentalAttackSchema, AbilitySchema
|
||||
|
||||
from encounters import EncounterTable
|
||||
from mentattack import MentalAttackMatrix
|
||||
from mutations import Mutations
|
||||
from cybermods import CyberMods
|
||||
|
||||
import random
|
||||
|
||||
@ -26,7 +27,7 @@ character = api.namespace('character', description='Character operations')
|
||||
encounter = api.namespace('encounter', description='Encounter operations')
|
||||
|
||||
ability_model = ability.model('Ability', ability_model)
|
||||
# TODO: Add ability schema
|
||||
ability_schema = AbilitySchema()
|
||||
|
||||
hp_model = hp.model('HP', hp_model)
|
||||
# TODO: Add hitpoint schema
|
||||
@ -65,12 +66,14 @@ class RollAbility(Resource):
|
||||
@ability.expect(ability_model)
|
||||
def post(self):
|
||||
data = api.payload
|
||||
errors = ability_schema.validate(data)
|
||||
if errors:
|
||||
return errors, 400
|
||||
|
||||
chartype = data.get('chartype')
|
||||
if chartype == 'human':
|
||||
geometry = 8
|
||||
else:
|
||||
geometry = 6
|
||||
return roll_dices(4, geometry, True), 200
|
||||
attribute = data.get('ability')
|
||||
|
||||
return roll_ability_scores(chartype, attribute), 200
|
||||
|
||||
|
||||
@api.route('/roll/hp', methods=['POST'])
|
||||
@ -180,24 +183,22 @@ class GenerateCharacter(Resource):
|
||||
if errors:
|
||||
return errors, 400
|
||||
chartype = data.get('chartype')
|
||||
char_emphasis = data.get('emphasis')
|
||||
|
||||
character_sheet = {}
|
||||
ability_scores = roll_ability_scores(chartype)
|
||||
character_sheet['abilities'] = ability_scores
|
||||
character_sheet['hp'] = roll_hp(chartype, ability_scores['constitution'])
|
||||
character_sheet['gold'] = roll_dices(4, 4, False).get('result') * 10
|
||||
character_sheet['domar'] = roll_dices(2, 4, False).get('result') * 5
|
||||
|
||||
if chartype == 'human':
|
||||
geometry = 8
|
||||
else:
|
||||
geometry = 6
|
||||
scores = roll_ability_scores(chartype)
|
||||
assigned_abilities = assign_ability_scores(scores, char_emphasis)
|
||||
character_sheet['abilities'] = assigned_abilities
|
||||
character_sheet['hp'] = roll_hp(chartype, assigned_abilities['constitution'])
|
||||
character_sheet['gold'] = roll_dices(4, 4, False).get('result')
|
||||
character_sheet['domar'] = roll_dices(2, 4, False).get('result')
|
||||
|
||||
if chartype == 'mutant':
|
||||
if chartype == 'humanoid' or chartype == 'mutant':
|
||||
character_sheet['mutations'] = (
|
||||
roll_mutations(assigned_abilities['constitution'], assigned_abilities['intelligence'])
|
||||
roll_mutations(ability_scores['constitution'], ability_scores['intelligence'])
|
||||
)
|
||||
|
||||
if chartype == 'cyborg':
|
||||
character_sheet['cybermods'] = (
|
||||
roll_cybermods()
|
||||
)
|
||||
|
||||
return character_sheet, 200
|
||||
@ -234,43 +235,30 @@ def roll_dices(dice_count, dice_sides, discard_lowest):
|
||||
return result
|
||||
|
||||
|
||||
def roll_ability_scores(chartype):
|
||||
if chartype == 'human':
|
||||
geometry = 8
|
||||
def roll_ability_scores(chartype, attribute=None):
|
||||
if attribute is None or attribute == "all":
|
||||
ability_list = ['p-strength', 'm-strength', 'constitution', 'dexterity', 'charisma', 'intelligence']
|
||||
else:
|
||||
geometry = 6
|
||||
ability_list = [attribute]
|
||||
|
||||
scores = []
|
||||
for _ in range(6):
|
||||
scores.append(roll_dices(4, geometry, True)['result'])
|
||||
|
||||
return scores
|
||||
|
||||
|
||||
def assign_ability_scores(scores, char_emphasis):
|
||||
ability_scores = {}
|
||||
if char_emphasis == 'physical':
|
||||
ability_list = ['p-strength', 'constitution', 'dexterity',
|
||||
'charisma', 'intelligence', 'm-strength']
|
||||
for ab in ability_list:
|
||||
max_score = max(scores)
|
||||
ability_scores[ab] = max_score
|
||||
scores.remove(max_score)
|
||||
|
||||
elif char_emphasis == 'mental':
|
||||
ability_list = ['m-strength', 'intelligence', 'charisma',
|
||||
'constitution', 'dexterity', 'p-strength']
|
||||
for ab in ability_list:
|
||||
max_score = max(scores)
|
||||
ability_scores[ab] = max_score
|
||||
scores.remove(max_score)
|
||||
|
||||
else:
|
||||
ability_list = ['p-strength', 'constitution', 'dexterity',
|
||||
'charisma', 'intelligence', 'm-strength']
|
||||
random.shuffle(scores)
|
||||
for ab, score in zip(ability_list, scores):
|
||||
ability_scores[ab] = score
|
||||
for abil in ability_list:
|
||||
if ((chartype == 'human') and
|
||||
((abil == 'intelligence') or
|
||||
(abil == 'charisma') or
|
||||
(abil == 'constitution'))):
|
||||
roll = roll_dices(4, 6, False) # humans are special
|
||||
if (abil == 'constitution') and roll["result"] > 18:
|
||||
roll["capped"] = True
|
||||
roll["result"] = 18
|
||||
if (abil == 'intelligence' or abil == 'charisma') and roll["result"] > 21:
|
||||
roll["capped"] = True
|
||||
roll["result"] = 21
|
||||
ability_scores[abil] = roll["result"]
|
||||
else:
|
||||
roll = roll_dices(4, 6, True) # nothing else is special
|
||||
ability_scores[abil] = roll["result"]
|
||||
|
||||
return ability_scores
|
||||
|
||||
@ -283,6 +271,57 @@ def roll_hp(chartype, conscore):
|
||||
return roll_dices(conscore, geometry, False).get('result')
|
||||
|
||||
|
||||
def roll_cybermods():
|
||||
"""
|
||||
Cybermods are similar to mutations, except that they are artificial changes to the body,
|
||||
where mutations are 'natural' changes to the body. Fewer cybermods are possible than with
|
||||
mutations. So, you make one roll of 1d4, and then parse up the score between the two
|
||||
types of mods, as you see fit. If no emphasis is specified, the score will be split as evenly
|
||||
as possible. If the score is 1, then a physical mod will be the default.
|
||||
:return: table of cybermods (in json format)
|
||||
"""
|
||||
cybermods_table = {}
|
||||
|
||||
cybermods_count = roll_dices(1, 4, False)["result"]
|
||||
phys_cnt = split_number(cybermods_count)[0]
|
||||
ment_cnt = split_number(cybermods_count)[1]
|
||||
|
||||
mental_cybermods_scores = []
|
||||
physical_cybermods_scores = []
|
||||
|
||||
for _ in range(ment_cnt):
|
||||
mscore = roll_dices(1, 10, False).get('result')
|
||||
if mscore in mental_cybermods_scores:
|
||||
mscore = roll_dices(1, 10, False).get('result')
|
||||
mental_cybermods_scores.append(mscore)
|
||||
|
||||
for _ in range(phys_cnt):
|
||||
pscore = roll_dices(1, 10, False).get('result')
|
||||
if pscore in physical_cybermods_scores:
|
||||
pscore = roll_dices(1, 10, False).get('result')
|
||||
physical_cybermods_scores.append(pscore)
|
||||
|
||||
cyb = CyberMods()
|
||||
mcyb = []
|
||||
pcyb = []
|
||||
|
||||
for score in mental_cybermods_scores:
|
||||
modification = cyb.get_mental_cybermod(score)
|
||||
mcyb.append(modification)
|
||||
|
||||
if len(mcyb) != 0:
|
||||
cybermods_table['mental'] = mcyb
|
||||
|
||||
for score in physical_cybermods_scores:
|
||||
modification = cyb.get_physical_cybermod(score)
|
||||
pcyb.append(modification)
|
||||
|
||||
if len(pcyb) != 0:
|
||||
cybermods_table['physical'] = pcyb
|
||||
|
||||
return cybermods_table
|
||||
|
||||
|
||||
def roll_mutations(conscore, intscore):
|
||||
"""
|
||||
:param conscore: modifier for physical mutation determination
|
||||
@ -301,8 +340,7 @@ def roll_mutations(conscore, intscore):
|
||||
for _ in range(mental_mutations_cnt):
|
||||
mscore = roll_dices(1, 100, False).get('result') + intscore
|
||||
if mscore in mental_mutations_scores:
|
||||
mscore = mscore - 3
|
||||
|
||||
mscore = roll_dices(1, 100, False).get('result') + intscore
|
||||
if mscore > 100:
|
||||
mscore = 100
|
||||
mental_mutations_scores.append(mscore)
|
||||
@ -310,8 +348,7 @@ def roll_mutations(conscore, intscore):
|
||||
for _ in range(physical_mutations_cnt):
|
||||
pscore = roll_dices(1, 100, False).get('result') + conscore
|
||||
if pscore in physical_mutations_scores:
|
||||
pscore = pscore - 3
|
||||
|
||||
pscore = roll_dices(1, 100, False).get('result') + conscore
|
||||
if pscore > 100:
|
||||
pscore = 100
|
||||
physical_mutations_scores.append(pscore)
|
||||
@ -335,5 +372,11 @@ def roll_mutations(conscore, intscore):
|
||||
return mutations_table
|
||||
|
||||
|
||||
def split_number(n):
|
||||
first_split = n // 2 # this will split the number in two equal parts, if it is even
|
||||
second_split = n % 2 + first_split # this will add one to one part if the number is odd
|
||||
return first_split, second_split
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run()
|
||||
|
33
cybermods.py
Normal file
33
cybermods.py
Normal file
@ -0,0 +1,33 @@
|
||||
import pandas as pd
|
||||
|
||||
|
||||
class CyberMods(object):
|
||||
def __init__(self):
|
||||
self.raw_cybermods_table = {
|
||||
'Score': list(range(1, 11)),
|
||||
'Physical': ['Replacement Limb', 'Replacement Sense Organ', 'Attribute Enhancement',
|
||||
'Additional Limb', 'Additional Sense Organ', 'Attachment Interface',
|
||||
'Energy Emitter', 'Energy Absorption', 'Nano-tech Collective', 'YOU INVENT ONE'],
|
||||
'Mental': ['Replacement Brain', 'Transmitter', 'Receiver', 'Energy Detection', 'Knowledge Base',
|
||||
'Pacify Android', 'Control Machine', 'Tech Recognition', 'Fabrication', 'YOU INVENT ONE']
|
||||
}
|
||||
|
||||
self.cybermods_table = pd.DataFrame(self.raw_cybermods_table)
|
||||
|
||||
def get_physical_cybermod(self, score):
|
||||
cybermod = self.cybermods_table.loc[self.cybermods_table['Score'] == score, 'Physical']
|
||||
return cybermod.iloc[0] if not cybermod.empty else None
|
||||
|
||||
def get_mental_cybermod(self, score):
|
||||
cybermod = self.cybermods_table.loc[self.cybermods_table['Score'] == score, 'Mental']
|
||||
return cybermod.iloc[0] if not cybermod.empty else None
|
||||
|
||||
def get_table_shape(self):
|
||||
return self.cybermods_table.shape
|
||||
|
||||
def get_table_row_count(self):
|
||||
return self.cybermods_table.shape[0]
|
||||
|
||||
def get_table_column_count(self):
|
||||
return self.cybermods_table.shape[1]
|
||||
|
@ -3,7 +3,7 @@ from flask_restx import fields
|
||||
# Common fields
|
||||
chartype_field = fields.String(
|
||||
required=False, default="human",
|
||||
description='Character type. Allowed values: "human", "mutant", "android", "robot"')
|
||||
description='Character type. Allowed values: "human", "humanoid", "mutant", "cyborg", "android"')
|
||||
|
||||
# Dice model
|
||||
dice_model = {
|
||||
@ -14,7 +14,8 @@ dice_model = {
|
||||
|
||||
# Ability model
|
||||
ability_model = {
|
||||
'chartype': chartype_field
|
||||
'chartype': chartype_field,
|
||||
'ability': fields.String(required=False, description='The ability to roll. Not required. Defaults "generic"'),
|
||||
}
|
||||
|
||||
# Hp model
|
||||
@ -31,10 +32,6 @@ ma_model = {
|
||||
|
||||
character_model = {
|
||||
'chartype': chartype_field,
|
||||
'emphasis': fields.String(
|
||||
required=False,
|
||||
default="random",
|
||||
description='The attribute emphasis of your character. Choices: "physical", "mental", "random"')
|
||||
}
|
||||
|
||||
encounter_model = {
|
||||
|
12
physattack.py
Normal file
12
physattack.py
Normal file
@ -0,0 +1,12 @@
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
|
||||
|
||||
class WeaponClassAttackMatrix:
|
||||
def __init__(self):
|
||||
data = {}
|
||||
|
||||
|
||||
class HitDiceAttackMatrix:
|
||||
def __init__(self):
|
||||
data = {}
|
27
schemas.py
27
schemas.py
@ -1,5 +1,11 @@
|
||||
from marshmallow import Schema, fields, validate
|
||||
|
||||
chartype_field = fields.String(
|
||||
required=True,
|
||||
validate=validate.OneOf(["human", "humanoid", "mutant", "cyborg", "android"]),
|
||||
description='The characters type of being'
|
||||
)
|
||||
|
||||
|
||||
class DiceSchema(Schema):
|
||||
quantity = fields.Int(required=True, validate=validate.Range(min=1), description='The number of dice to roll')
|
||||
@ -8,15 +14,17 @@ class DiceSchema(Schema):
|
||||
|
||||
|
||||
class CharacterSchema(Schema):
|
||||
chartype = fields.String(
|
||||
required=True,
|
||||
validate=validate.OneOf(["human", "mutant", "android", "robot"]),
|
||||
description='The characters type of being'
|
||||
)
|
||||
emphasis = fields.String(
|
||||
required=True,
|
||||
validate=validate.OneOf(["physical", "mental", "random"]),
|
||||
description='Valid inputs: physical, mental, random'
|
||||
chartype = chartype_field
|
||||
|
||||
|
||||
class AbilitySchema(Schema):
|
||||
chartype = chartype_field
|
||||
ability = fields.String(
|
||||
required=False,
|
||||
default="generic",
|
||||
validate=validate.OneOf(
|
||||
["m-strength", "p-strength", "intelligence", "charisma", "constitution", "dexterity", "all"]),
|
||||
description='One of the six character attributes from the character sheet'
|
||||
)
|
||||
|
||||
|
||||
@ -45,4 +53,3 @@ class MentalAttackSchema(Schema):
|
||||
validate=validate.Range(min=-100, max=100),
|
||||
description='Roll modifier for mental attack'
|
||||
)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user