massive, madman refactoring. What was I thinking?
This commit is contained in:
parent
0e97185ce8
commit
4d92acf3ee
455
app.py
455
app.py
@ -1,455 +0,0 @@
|
||||
from flask import Flask
|
||||
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, mutation_model, \
|
||||
check_model
|
||||
from schemas import DiceSchema, CharacterSchema, EncounterSchema, MentalAttackSchema, AbilitySchema, HPSchema, \
|
||||
MutationSchema, CheckSchema
|
||||
|
||||
from encounters import EncounterTable
|
||||
from mentattack import MentalAttackMatrix
|
||||
from mutations import Mutations
|
||||
from cybermods import CyberMods
|
||||
|
||||
import random
|
||||
|
||||
app = Flask(__name__)
|
||||
CORS(app)
|
||||
|
||||
app.config.SWAGGER_UI_JSONEDITOR = True
|
||||
app.config['SWAGGER_UI_JSONEDITOR'] = True
|
||||
api = Api(app, version='1.0', title='Gamma World Dice', description='Rolled Dice As A Service')
|
||||
|
||||
dice = api.namespace('dice', description='Dice operations')
|
||||
ability = api.namespace('ability', description='Ability operations')
|
||||
hp = api.namespace('hp', description='HP operations')
|
||||
ma = api.namespace('ma', description='Mental Attack operations')
|
||||
mut = api.namespace('mut', description='Mutation operations')
|
||||
character = api.namespace('character', description='Character operations')
|
||||
encounter = api.namespace('encounter', description='Encounter operations')
|
||||
check = api.namespace('check', description='Check operations')
|
||||
|
||||
check_model = check.model('Check', check_model )
|
||||
check_schema = CheckSchema()
|
||||
|
||||
ability_model = ability.model('Ability', ability_model)
|
||||
ability_schema = AbilitySchema()
|
||||
|
||||
mutation_model = mut.model('Mutation', mutation_model)
|
||||
mutation_schema = MutationSchema()
|
||||
|
||||
hp_model = hp.model('HP', hp_model)
|
||||
hp_schema = HPSchema()
|
||||
|
||||
dice_model = dice.model('Dice', dice_model)
|
||||
dice_schema = DiceSchema()
|
||||
|
||||
ma_model = ma.model('MA', ma_model)
|
||||
ma_schema = MentalAttackSchema()
|
||||
|
||||
character_model = character.model('Character', character_model)
|
||||
character_schema = CharacterSchema()
|
||||
|
||||
encounter_model = encounter.model('Encounter', encounter_model)
|
||||
encounter_schema = EncounterSchema()
|
||||
|
||||
|
||||
@api.route('/roll/dice', methods=['POST'])
|
||||
class RollDice(Resource):
|
||||
@dice.expect(dice_model)
|
||||
def post(self):
|
||||
data = api.payload
|
||||
errors = dice_schema.validate(data)
|
||||
if errors:
|
||||
return errors, 400
|
||||
quantity = data.get('quantity')
|
||||
geometry = data.get('geometry')
|
||||
discard_lowest = data.get('discard_lowest')
|
||||
if quantity is None or geometry is None:
|
||||
return {"message": "Required dice data not provided"}, 400
|
||||
return roll_dices(quantity, geometry, discard_lowest), 200
|
||||
|
||||
|
||||
@api.route('/roll/ability', methods=['POST'])
|
||||
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')
|
||||
attribute = data.get('ability')
|
||||
|
||||
return roll_ability_scores(chartype, attribute), 200
|
||||
|
||||
|
||||
@api.route('/roll/hp', methods=['POST'])
|
||||
class RollHP(Resource):
|
||||
@hp.expect(hp_model)
|
||||
def post(self):
|
||||
data = api.payload
|
||||
errors = hp_schema.validate(data)
|
||||
if errors:
|
||||
return errors, 400
|
||||
chartype = data.get('chartype')
|
||||
conscore = data.get('conscore')
|
||||
if conscore is None:
|
||||
return {"message": "A constitution score is required"}, 400
|
||||
if chartype == 'human':
|
||||
geometry = 8
|
||||
else:
|
||||
geometry = 6
|
||||
return roll_dices(conscore, geometry, False), 200
|
||||
|
||||
|
||||
@api.route('/roll/encounter', methods=['POST'])
|
||||
class RollEncounter(Resource):
|
||||
@encounter.expect(encounter_model)
|
||||
def post(self):
|
||||
data = api.payload
|
||||
errors = encounter_schema.validate(data)
|
||||
if errors:
|
||||
return errors, 400
|
||||
|
||||
terrain = data.get('terrain').lower()
|
||||
roll = roll_dices(1, 20, False).get('result')
|
||||
et = EncounterTable()
|
||||
creature = et.get_encounter(roll, terrain)
|
||||
if creature is None:
|
||||
creature = "All clear!"
|
||||
|
||||
return {"encounter": creature}, 200
|
||||
|
||||
|
||||
@api.route('/roll/attack/mental', methods=['POST'])
|
||||
class RollMentalAttack(Resource):
|
||||
@ma.expect(ma_model)
|
||||
def post(self):
|
||||
data = api.payload
|
||||
errors = ma_schema.validate(data)
|
||||
if errors:
|
||||
return errors, 400
|
||||
|
||||
ams = data.get('ams')
|
||||
dms = data.get('dms')
|
||||
modifier = data.get('modifier')
|
||||
|
||||
result = {}
|
||||
mam = MentalAttackMatrix()
|
||||
needed = mam.get_attack_score(ams, dms)
|
||||
result["needed"] = needed
|
||||
outcome = None
|
||||
if needed < 2:
|
||||
outcome = "Automatic Success!"
|
||||
elif needed > 20:
|
||||
outcome = "Absolutely No Chance!"
|
||||
else:
|
||||
raw_roll = roll_dices(1, 20, False).get('result')
|
||||
if modifier != 0:
|
||||
result["original-roll"] = raw_roll
|
||||
result["modifier"] = modifier
|
||||
rolled = raw_roll + modifier # negative modifiers will subtract themselves naturally
|
||||
result["adjusted-roll"] = rolled
|
||||
else:
|
||||
rolled = raw_roll
|
||||
result["original-roll"] = rolled
|
||||
|
||||
if (rolled >= 20) and (needed <= 16):
|
||||
outcome = "Devastating Success!"
|
||||
elif needed <= rolled:
|
||||
outcome = "Attack Successful!"
|
||||
elif needed > rolled:
|
||||
outcome = "Attack Failed!"
|
||||
|
||||
result["outcome"] = outcome
|
||||
|
||||
return result, 200
|
||||
|
||||
|
||||
@api.route('/roll/check', methods=['POST'])
|
||||
class RollCheck(Resource):
|
||||
@check.expect(check_model)
|
||||
def post(self):
|
||||
data = api.payload
|
||||
errors = check_schema.validate(data)
|
||||
if errors:
|
||||
return errors, 400
|
||||
|
||||
ability_score = data.get('ability_score')
|
||||
multiplier = data.get('multiplier')
|
||||
|
||||
threshold = ability_score * multiplier
|
||||
rolled = roll_dices(1, 100, False).get('result')
|
||||
if rolled < threshold:
|
||||
return {'threshold': threshold, 'rolled': rolled, 'success': True}, 200
|
||||
else:
|
||||
return {'threshold': threshold, 'rolled': rolled, 'success': False}, 200
|
||||
|
||||
|
||||
@api.route('/roll/tohit', methods=['GET'])
|
||||
class RollToHit(Resource):
|
||||
@staticmethod
|
||||
def get():
|
||||
return roll_dices(1, 20, False), 200
|
||||
|
||||
|
||||
@api.route('/roll/chance', methods=['GET'])
|
||||
class RollChance(Resource):
|
||||
@staticmethod
|
||||
def get():
|
||||
return roll_dices(1, 100, False), 200
|
||||
|
||||
|
||||
@api.route('/coinflip', methods=['GET'])
|
||||
class RollCoinflip(Resource):
|
||||
@staticmethod
|
||||
def get():
|
||||
return random.choice(['Heads', 'Tails']), 200
|
||||
|
||||
|
||||
@api.route('/roll/mutations', methods=['POST'])
|
||||
class RollMutations(Resource):
|
||||
@mut.expect(mutation_model)
|
||||
def post(self):
|
||||
data = api.payload
|
||||
errors = mutation_schema.validate(data)
|
||||
if errors:
|
||||
return errors, 400
|
||||
|
||||
conscore = data.get('conscore')
|
||||
intscore = data.get('intscore')
|
||||
|
||||
return roll_mutations(conscore, intscore), 200
|
||||
|
||||
|
||||
@api.route('/character/generate', methods=['POST'])
|
||||
class GenerateCharacter(Resource):
|
||||
@character.expect(character_model)
|
||||
def post(self):
|
||||
data = api.payload
|
||||
errors = character_schema.validate(data)
|
||||
if errors:
|
||||
return errors, 400
|
||||
chartype = data.get('chartype')
|
||||
|
||||
character_sheet = {}
|
||||
if chartype == 'mutant':
|
||||
character_sheet['animal-stock'] = (roll_mutant_animal())
|
||||
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 == 'humanoid' or chartype == 'mutant':
|
||||
character_sheet['mutations'] = (
|
||||
roll_mutations(ability_scores['constitution'], ability_scores['intelligence'])
|
||||
)
|
||||
|
||||
if chartype == 'cyborg':
|
||||
character_sheet['cybermods'] = (
|
||||
roll_cybermods()
|
||||
)
|
||||
|
||||
return character_sheet, 200
|
||||
|
||||
|
||||
def roll_dices(dice_count, dice_sides, discard_lowest):
|
||||
roll_results = []
|
||||
discarded = []
|
||||
for _ in range(dice_count):
|
||||
roll_results.append(random.randint(1, dice_sides))
|
||||
if discard_lowest and len(roll_results) > 0:
|
||||
discarded.append(min(roll_results))
|
||||
roll_results.remove(min(roll_results))
|
||||
|
||||
if discarded:
|
||||
net_dice_count = dice_count - 1
|
||||
mnemonic = str(dice_count) + "(-1)d" + str(dice_sides)
|
||||
else:
|
||||
mnemonic = str(dice_count) + 'd' + str(dice_sides)
|
||||
net_dice_count = dice_count
|
||||
|
||||
result = {
|
||||
'dice-set': {
|
||||
'mnemonic': mnemonic,
|
||||
'min-roll': net_dice_count,
|
||||
'max-roll': dice_sides * net_dice_count
|
||||
},
|
||||
'rolls': roll_results,
|
||||
'result': sum(roll_results)
|
||||
}
|
||||
if discarded:
|
||||
result['discarded'] = discarded
|
||||
|
||||
return result
|
||||
|
||||
|
||||
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:
|
||||
ability_list = [attribute]
|
||||
|
||||
ability_scores = {}
|
||||
|
||||
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
|
||||
|
||||
|
||||
def roll_hp(chartype, conscore):
|
||||
if chartype == 'human':
|
||||
geometry = 8
|
||||
else:
|
||||
geometry = 6
|
||||
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)[1] # This ends up being the higher of the two numbers
|
||||
ment_cnt = split_number(cybermods_count)[0]
|
||||
cybermods_table['count'] = {'mental': ment_cnt, 'physical': phys_cnt}
|
||||
|
||||
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
|
||||
:param intscore: modifier for mental mutation determination
|
||||
:return: table of mutations (in json form)
|
||||
"""
|
||||
mutations_table = {}
|
||||
|
||||
mental_mutations_cnt = roll_dices(1, 4, False).get('result')
|
||||
physical_mutations_cnt = roll_dices(1, 4, False).get('result')
|
||||
mutations_table['count'] = {'mental': mental_mutations_cnt, 'physical': physical_mutations_cnt}
|
||||
|
||||
mental_mutations_scores = get_score_list(mental_mutations_cnt, intscore)
|
||||
mutations_table['mental'] = get_mutations(mental_mutations_scores)
|
||||
|
||||
physical_mutations_scores = get_score_list(physical_mutations_cnt, conscore)
|
||||
mutations_table['physical'] = get_mutations(physical_mutations_scores)
|
||||
|
||||
return mutations_table
|
||||
|
||||
|
||||
def get_mutations(scorelist):
|
||||
mut_table = Mutations()
|
||||
mut_list = []
|
||||
for score in scorelist:
|
||||
mutation = mut_table.get_mental_mutation(score)
|
||||
mut_list.append(mutation)
|
||||
return mut_list
|
||||
|
||||
|
||||
def get_score_list(count, modifier):
|
||||
tmp_scores = []
|
||||
for _ in range(count):
|
||||
roll = roll_dices(1, 100, False).get('result') + modifier
|
||||
if roll in tmp_scores:
|
||||
roll = roll_dices(1, 100, False).get('result') + modifier
|
||||
if roll > 100:
|
||||
roll = 100
|
||||
tmp_scores.append(roll)
|
||||
|
||||
return tmp_scores
|
||||
|
||||
|
||||
def roll_mutant_animal():
|
||||
creature = dict()
|
||||
|
||||
animal_stock = ['badger', 'racoon', 'hound', 'wolf', 'big-cat', 'fox',
|
||||
'spider', 'lizard', 'ant', 'hornet', 'hawk', 'ostrich', 'emu', 'crocodile',
|
||||
'snake', 'rabbit', 'rat', 'bear', 'elephant', 'platypus', 'bull', 'horse', 'goat', 'bat',
|
||||
'silverfish', 'cockroach', 'turtle', 'gibbon', 'penguin', 'orangutan', 'chimpanzee',
|
||||
'housefly', 'lobster', 'crab', 'prawn', 'pig', 'chicken', 'duck', 'parrot', 'mouse',
|
||||
'heron', 'weasel', 'squirrel', 'pigeon', 'crow', 'house-cat', 'shark', 'dolphin', 'narwhal',
|
||||
'buffalo']
|
||||
|
||||
posture = ['upright', 'prone', 'mixed']
|
||||
|
||||
creature['stock'] = random.choice(animal_stock)
|
||||
creature['posture'] = random.choice(posture)
|
||||
|
||||
if creature['posture'] == 'upright' or creature['posture'] == 'mixed':
|
||||
creature['arms'] = random.choice(list(range(2, 4, 2))) # if you're upright 4 is the limit
|
||||
creature['legs'] = random.choice(list(range(2, 6, 2))) # same with legs
|
||||
|
||||
if creature['posture'] == 'prone':
|
||||
creature['legs'] = random.choice(list(range(4, 8, 2))) # if you're prone, you only get legs
|
||||
|
||||
return creature
|
||||
|
||||
|
||||
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()
|
0
app/__init__.py
Normal file
0
app/__init__.py
Normal file
205
app/app.py
Normal file
205
app/app.py
Normal file
@ -0,0 +1,205 @@
|
||||
import random
|
||||
|
||||
from flask import Flask
|
||||
from flask_cors import CORS
|
||||
from flask_restx import Api, Resource
|
||||
|
||||
from app.functions.build_character_sheet import build_character_sheet
|
||||
from app.functions.roll_ability_scores import roll_ability_scores
|
||||
from app.functions.roll_ability_check import roll_ability_check
|
||||
from app.functions.roll_dices import roll_dices
|
||||
from app.functions.roll_encounter import roll_encounter
|
||||
from app.functions.roll_mental_attack import roll_mental_attack
|
||||
from app.functions.roll_mutations import roll_mutations
|
||||
from app.models.models import dice_model, ability_model, hp_model, character_model, encounter_model, ma_model, \
|
||||
mutation_model, \
|
||||
check_model
|
||||
from app.schemas.schemas import DiceSchema, CharacterSchema, EncounterSchema, MentalAttackSchema, AbilitySchema, \
|
||||
HPSchema, \
|
||||
MutationSchema, CheckSchema
|
||||
|
||||
app = Flask(__name__)
|
||||
CORS(app)
|
||||
|
||||
app.config.SWAGGER_UI_JSONEDITOR = True
|
||||
app.config['SWAGGER_UI_JSONEDITOR'] = True
|
||||
api = Api(app, version='1.0', title='Gamma World Dice', description='Rolled Dice As A Service')
|
||||
|
||||
dice = api.namespace('dice', description='Dice operations')
|
||||
ability = api.namespace('ability', description='Ability operations')
|
||||
hp = api.namespace('hp', description='HP operations')
|
||||
ma = api.namespace('ma', description='Mental Attack operations')
|
||||
mut = api.namespace('mut', description='Mutation operations')
|
||||
character = api.namespace('character', description='Character operations')
|
||||
encounter = api.namespace('encounter', description='Encounter operations')
|
||||
check = api.namespace('check', description='Check operations')
|
||||
|
||||
check_model = check.model('Check', check_model)
|
||||
check_schema = CheckSchema()
|
||||
|
||||
ability_model = ability.model('Ability', ability_model)
|
||||
ability_schema = AbilitySchema()
|
||||
|
||||
mutation_model = mut.model('Mutation', mutation_model)
|
||||
mutation_schema = MutationSchema()
|
||||
|
||||
hp_model = hp.model('HP', hp_model)
|
||||
hp_schema = HPSchema()
|
||||
|
||||
dice_model = dice.model('Dice', dice_model)
|
||||
dice_schema = DiceSchema()
|
||||
|
||||
ma_model = ma.model('MA', ma_model)
|
||||
ma_schema = MentalAttackSchema()
|
||||
|
||||
character_model = character.model('Character', character_model)
|
||||
character_schema = CharacterSchema()
|
||||
|
||||
encounter_model = encounter.model('Encounter', encounter_model)
|
||||
encounter_schema = EncounterSchema()
|
||||
|
||||
|
||||
@api.route('/roll/dice', methods=['POST'])
|
||||
class RollDice(Resource):
|
||||
@dice.expect(dice_model)
|
||||
def post(self):
|
||||
data = api.payload
|
||||
errors = dice_schema.validate(data)
|
||||
if errors:
|
||||
return errors, 400
|
||||
quantity = data.get('quantity')
|
||||
geometry = data.get('geometry')
|
||||
discard_lowest = data.get('discard_lowest')
|
||||
if quantity is None or geometry is None:
|
||||
return {"message": "Required dice data not provided"}, 400
|
||||
return roll_dices(quantity, geometry, discard_lowest), 200
|
||||
|
||||
|
||||
@api.route('/roll/ability', methods=['POST'])
|
||||
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')
|
||||
attribute = data.get('ability')
|
||||
|
||||
return roll_ability_scores(chartype, attribute), 200
|
||||
|
||||
|
||||
@api.route('/roll/hp', methods=['POST'])
|
||||
class RollHP(Resource):
|
||||
@hp.expect(hp_model)
|
||||
def post(self):
|
||||
data = api.payload
|
||||
errors = hp_schema.validate(data)
|
||||
if errors:
|
||||
return errors, 400
|
||||
chartype = data.get('chartype')
|
||||
conscore = data.get('conscore')
|
||||
if conscore is None:
|
||||
return {"message": "A constitution score is required"}, 400
|
||||
if chartype == 'human':
|
||||
geometry = 8
|
||||
else:
|
||||
geometry = 6
|
||||
return roll_dices(conscore, geometry, False), 200
|
||||
|
||||
|
||||
@api.route('/roll/encounter', methods=['POST'])
|
||||
class RollEncounter(Resource):
|
||||
@encounter.expect(encounter_model)
|
||||
def post(self):
|
||||
data = api.payload
|
||||
errors = encounter_schema.validate(data)
|
||||
if errors:
|
||||
return errors, 400
|
||||
|
||||
terrain = data.get('terrain').lower()
|
||||
return roll_encounter(terrain), 200
|
||||
|
||||
|
||||
@api.route('/roll/attack/mental', methods=['POST'])
|
||||
class RollMentalAttack(Resource):
|
||||
@ma.expect(ma_model)
|
||||
def post(self):
|
||||
data = api.payload
|
||||
errors = ma_schema.validate(data)
|
||||
if errors:
|
||||
return errors, 400
|
||||
|
||||
ams = data.get('ams')
|
||||
dms = data.get('dms')
|
||||
modifier = data.get('modifier')
|
||||
|
||||
return roll_mental_attack(ams, dms, modifier), 200
|
||||
|
||||
|
||||
@api.route('/roll/check', methods=['POST'])
|
||||
class RollCheck(Resource):
|
||||
@check.expect(check_model)
|
||||
def post(self):
|
||||
data = api.payload
|
||||
errors = check_schema.validate(data)
|
||||
if errors:
|
||||
return errors, 400
|
||||
|
||||
ability_score = data.get('ability_score')
|
||||
multiplier = data.get('multiplier')
|
||||
|
||||
return roll_ability_check(ability_score, multiplier), 200
|
||||
|
||||
|
||||
@api.route('/roll/tohit', methods=['GET'])
|
||||
class RollToHit(Resource):
|
||||
@staticmethod
|
||||
def get():
|
||||
return roll_dices(1, 20, False), 200
|
||||
|
||||
|
||||
@api.route('/roll/chance', methods=['GET'])
|
||||
class RollChance(Resource):
|
||||
@staticmethod
|
||||
def get():
|
||||
return roll_dices(1, 100, False), 200
|
||||
|
||||
|
||||
@api.route('/coinflip', methods=['GET'])
|
||||
class RollCoinflip(Resource):
|
||||
@staticmethod
|
||||
def get():
|
||||
return random.choice(['Heads', 'Tails']), 200
|
||||
|
||||
|
||||
@api.route('/roll/mutations', methods=['POST'])
|
||||
class RollMutations(Resource):
|
||||
@mut.expect(mutation_model)
|
||||
def post(self):
|
||||
data = api.payload
|
||||
errors = mutation_schema.validate(data)
|
||||
if errors:
|
||||
return errors, 400
|
||||
|
||||
conscore = data.get('conscore')
|
||||
intscore = data.get('intscore')
|
||||
|
||||
return roll_mutations(conscore, intscore), 200
|
||||
|
||||
|
||||
@api.route('/character/generate', methods=['POST'])
|
||||
class GenerateCharacter(Resource):
|
||||
@character.expect(character_model)
|
||||
def post(self):
|
||||
data = api.payload
|
||||
errors = character_schema.validate(data)
|
||||
if errors:
|
||||
return errors, 400
|
||||
chartype = data.get('chartype')
|
||||
return build_character_sheet(chartype), 200
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run()
|
0
app/functions/__init__.py
Normal file
0
app/functions/__init__.py
Normal file
36
app/functions/build_character_sheet.py
Normal file
36
app/functions/build_character_sheet.py
Normal file
@ -0,0 +1,36 @@
|
||||
from app.functions.roll_dices import roll_dices
|
||||
from app.functions.roll_ability_scores import roll_ability_scores
|
||||
from app.functions.roll_cybermods import roll_cybermods
|
||||
from app.functions.roll_mutations import roll_mutations
|
||||
|
||||
from app.functions.roll_hp import roll_hp
|
||||
from app.functions.generate_profile import generate_profile
|
||||
from app.functions.roll_mutant_animal import roll_mutant_animal
|
||||
|
||||
|
||||
def build_character_sheet(chartype):
|
||||
character_sheet = dict()
|
||||
|
||||
character_sheet['profile'] = generate_profile(chartype)
|
||||
|
||||
if chartype == 'mutant':
|
||||
character_sheet['animal-stock'] = (roll_mutant_animal())
|
||||
|
||||
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 == 'humanoid' or chartype == 'mutant':
|
||||
character_sheet['mutations'] = (
|
||||
roll_mutations(ability_scores['constitution'], ability_scores['intelligence'])
|
||||
)
|
||||
|
||||
if chartype == 'cyborg':
|
||||
character_sheet['cybermods'] = (
|
||||
roll_cybermods()
|
||||
)
|
||||
|
||||
return character_sheet
|
16
app/functions/generate_profile.py
Normal file
16
app/functions/generate_profile.py
Normal file
@ -0,0 +1,16 @@
|
||||
import random
|
||||
from app.functions.get_character_age import get_age
|
||||
|
||||
|
||||
def generate_profile(chartype):
|
||||
profile = {
|
||||
'name': "Anon",
|
||||
'sex': random.choice(['male', 'female', 'male', 'female', 'male', 'female']),
|
||||
'age': get_age(chartype)
|
||||
}
|
||||
if chartype == 'human':
|
||||
profile['hair'] = random.choice(['black', 'brown', 'auburn', 'blonde', 'copper', 'brass', 'blue', 'bald'])
|
||||
profile['eyes'] = random.choice(['blue', 'brown', 'green', 'hazel', 'gray'])
|
||||
profile['skintone'] = random.choice(['dark', 'olive', 'medium', 'light', 'pale'])
|
||||
|
||||
return profile
|
36
app/functions/get_character_age.py
Normal file
36
app/functions/get_character_age.py
Normal file
@ -0,0 +1,36 @@
|
||||
import random
|
||||
|
||||
|
||||
def get_age(chartype):
|
||||
ages = {
|
||||
"human": {
|
||||
'youth': (14, 18),
|
||||
'young': (19, 38),
|
||||
'midage': (39, 58),
|
||||
'veteran': (59, 72)
|
||||
},
|
||||
"humanoid": {
|
||||
'youth': (8, 19),
|
||||
'young': (20, 48),
|
||||
'midage': (49, 68),
|
||||
'veteran': (69, 82)
|
||||
},
|
||||
"mutant": {
|
||||
'youth': (8, 13),
|
||||
'young': (14, 28),
|
||||
'midage': (29, 48),
|
||||
'veteran': (49, 62)
|
||||
},
|
||||
"cyborg": {
|
||||
'youth': (14, 18),
|
||||
'young': (19, 38),
|
||||
'midage': (39, 58),
|
||||
'veteran': (59, 72)
|
||||
}
|
||||
}
|
||||
|
||||
char_range = ages[chartype]
|
||||
age_group = random.choice(list(char_range.keys()))
|
||||
age_range = char_range[age_group]
|
||||
|
||||
return random.choice(age_range)
|
10
app/functions/get_mutations.py
Normal file
10
app/functions/get_mutations.py
Normal file
@ -0,0 +1,10 @@
|
||||
from app.tables.mutations import Mutations
|
||||
|
||||
|
||||
def get_mutations(scorelist):
|
||||
mut_table = Mutations()
|
||||
mut_list = []
|
||||
for score in scorelist:
|
||||
mutation = mut_table.get_mental_mutation(score)
|
||||
mut_list.append(mutation)
|
||||
return mut_list
|
14
app/functions/get_score_list.py
Normal file
14
app/functions/get_score_list.py
Normal file
@ -0,0 +1,14 @@
|
||||
from app.functions.roll_dices import roll_dices
|
||||
|
||||
|
||||
def get_score_list(count, modifier):
|
||||
tmp_scores = []
|
||||
for _ in range(count):
|
||||
roll = roll_dices(1, 100, False).get('result') + modifier
|
||||
if roll in tmp_scores:
|
||||
roll = roll_dices(1, 100, False).get('result') + modifier
|
||||
if roll > 100:
|
||||
roll = 100
|
||||
tmp_scores.append(roll)
|
||||
|
||||
return tmp_scores
|
10
app/functions/roll_ability_check.py
Normal file
10
app/functions/roll_ability_check.py
Normal file
@ -0,0 +1,10 @@
|
||||
from app.functions.roll_dices import roll_dices
|
||||
|
||||
|
||||
def roll_ability_check(score, multiplier):
|
||||
threshold = score * multiplier
|
||||
rolled = roll_dices(1, 100, False).get('result')
|
||||
if rolled < threshold:
|
||||
return {'threshold': threshold, 'rolled': rolled, 'success': True}, 200
|
||||
else:
|
||||
return {'threshold': threshold, 'rolled': rolled, 'success': False}, 200
|
29
app/functions/roll_ability_scores.py
Normal file
29
app/functions/roll_ability_scores.py
Normal file
@ -0,0 +1,29 @@
|
||||
from app.functions.roll_dices import roll_dices
|
||||
|
||||
|
||||
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:
|
||||
ability_list = [attribute]
|
||||
|
||||
ability_scores = {}
|
||||
|
||||
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
|
55
app/functions/roll_cybermods.py
Normal file
55
app/functions/roll_cybermods.py
Normal file
@ -0,0 +1,55 @@
|
||||
from app.functions.roll_dices import roll_dices
|
||||
from app.tables.cybermods import CyberMods
|
||||
from app.functions.split_number import split_number
|
||||
|
||||
|
||||
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)[1] # This ends up being the higher of the two numbers
|
||||
ment_cnt = split_number(cybermods_count)[0]
|
||||
cybermods_table['count'] = {'mental': ment_cnt, 'physical': phys_cnt}
|
||||
|
||||
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
|
32
app/functions/roll_dices.py
Normal file
32
app/functions/roll_dices.py
Normal file
@ -0,0 +1,32 @@
|
||||
import random
|
||||
|
||||
|
||||
def roll_dices(dice_count, dice_sides, discard_lowest):
|
||||
roll_results = []
|
||||
discarded = []
|
||||
for _ in range(dice_count):
|
||||
roll_results.append(random.randint(1, dice_sides))
|
||||
if discard_lowest and len(roll_results) > 0:
|
||||
discarded.append(min(roll_results))
|
||||
roll_results.remove(min(roll_results))
|
||||
|
||||
if discarded:
|
||||
net_dice_count = dice_count - 1
|
||||
mnemonic = str(dice_count) + "(-1)d" + str(dice_sides)
|
||||
else:
|
||||
mnemonic = str(dice_count) + 'd' + str(dice_sides)
|
||||
net_dice_count = dice_count
|
||||
|
||||
result = {
|
||||
'dice-set': {
|
||||
'mnemonic': mnemonic,
|
||||
'min-roll': net_dice_count,
|
||||
'max-roll': dice_sides * net_dice_count
|
||||
},
|
||||
'rolls': roll_results,
|
||||
'result': sum(roll_results)
|
||||
}
|
||||
if discarded:
|
||||
result['discarded'] = discarded
|
||||
|
||||
return result
|
9
app/functions/roll_encounter.py
Normal file
9
app/functions/roll_encounter.py
Normal file
@ -0,0 +1,9 @@
|
||||
from app.functions.roll_dices import roll_dices
|
||||
from app.tables.encounters import EncounterTable
|
||||
|
||||
|
||||
def roll_encounter(terrain):
|
||||
roll = roll_dices(1, 20, False).get('result')
|
||||
et = EncounterTable()
|
||||
creature = et.get_encounter(roll, terrain)
|
||||
return {"encounter": creature}
|
9
app/functions/roll_hp.py
Normal file
9
app/functions/roll_hp.py
Normal file
@ -0,0 +1,9 @@
|
||||
from app.functions.roll_dices import roll_dices
|
||||
|
||||
|
||||
def roll_hp(chartype, conscore):
|
||||
if chartype == 'human':
|
||||
geometry = 8
|
||||
else:
|
||||
geometry = 6
|
||||
return roll_dices(conscore, geometry, False).get('result')
|
35
app/functions/roll_mental_attack.py
Normal file
35
app/functions/roll_mental_attack.py
Normal file
@ -0,0 +1,35 @@
|
||||
from app.functions.roll_dices import roll_dices
|
||||
from app.tables.mentattack import MentalAttackMatrix
|
||||
|
||||
|
||||
def roll_mental_attack(ams, dms, modifier):
|
||||
|
||||
result = {}
|
||||
mam = MentalAttackMatrix()
|
||||
needed = mam.get_attack_score(ams, dms)
|
||||
result["needed"] = needed
|
||||
outcome = None
|
||||
if needed < 2:
|
||||
outcome = "Automatic Success!"
|
||||
elif needed > 20:
|
||||
outcome = "Absolutely No Chance!"
|
||||
else:
|
||||
raw_roll = roll_dices(1, 20, False).get('result')
|
||||
if modifier != 0:
|
||||
result["original-roll"] = raw_roll
|
||||
result["modifier"] = modifier
|
||||
rolled = raw_roll + modifier # negative modifiers will subtract themselves naturally
|
||||
result["adjusted-roll"] = rolled
|
||||
else:
|
||||
rolled = raw_roll
|
||||
result["original-roll"] = rolled
|
||||
|
||||
if (rolled >= 20) and (needed <= 16):
|
||||
outcome = "Devastating Success!"
|
||||
elif needed <= rolled:
|
||||
outcome = "Attack Successful!"
|
||||
elif needed > rolled:
|
||||
outcome = "Attack Failed!"
|
||||
|
||||
result["outcome"] = outcome
|
||||
return result
|
27
app/functions/roll_mutant_animal.py
Normal file
27
app/functions/roll_mutant_animal.py
Normal file
@ -0,0 +1,27 @@
|
||||
import random
|
||||
|
||||
|
||||
def roll_mutant_animal():
|
||||
creature = dict()
|
||||
|
||||
animal_stock = ['badger', 'racoon', 'hound', 'wolf', 'big-cat', 'fox',
|
||||
'spider', 'lizard', 'ant', 'hornet', 'hawk', 'ostrich', 'emu', 'crocodile',
|
||||
'snake', 'rabbit', 'rat', 'bear', 'elephant', 'platypus', 'bull', 'horse', 'goat', 'bat',
|
||||
'silverfish', 'cockroach', 'turtle', 'gibbon', 'penguin', 'orangutan', 'chimpanzee',
|
||||
'housefly', 'lobster', 'crab', 'prawn', 'pig', 'chicken', 'duck', 'parrot', 'mouse',
|
||||
'heron', 'weasel', 'squirrel', 'pigeon', 'crow', 'house-cat', 'shark', 'dolphin', 'narwhal',
|
||||
'buffalo']
|
||||
|
||||
posture = ['upright', 'prone', 'mixed']
|
||||
|
||||
creature['stock'] = random.choice(animal_stock)
|
||||
creature['posture'] = random.choice(posture)
|
||||
|
||||
if creature['posture'] == 'upright' or creature['posture'] == 'mixed':
|
||||
creature['arms'] = random.choice(list(range(2, 4, 2))) # if you're upright 4 is the limit
|
||||
creature['legs'] = random.choice(list(range(2, 6, 2))) # same with legs
|
||||
|
||||
if creature['posture'] == 'prone':
|
||||
creature['legs'] = random.choice(list(range(4, 8, 2))) # if you're prone, you only get legs
|
||||
|
||||
return creature
|
24
app/functions/roll_mutations.py
Normal file
24
app/functions/roll_mutations.py
Normal file
@ -0,0 +1,24 @@
|
||||
from app.functions.get_mutations import get_mutations
|
||||
from app.functions.get_score_list import get_score_list
|
||||
from app.functions.roll_dices import roll_dices
|
||||
|
||||
|
||||
def roll_mutations(conscore, intscore):
|
||||
"""
|
||||
:param conscore: modifier for physical mutation determination
|
||||
:param intscore: modifier for mental mutation determination
|
||||
:return: table of mutations (in json form)
|
||||
"""
|
||||
mutations_table = {}
|
||||
|
||||
mental_mutations_cnt = roll_dices(1, 4, False).get('result')
|
||||
physical_mutations_cnt = roll_dices(1, 4, False).get('result')
|
||||
mutations_table['count'] = {'mental': mental_mutations_cnt, 'physical': physical_mutations_cnt}
|
||||
|
||||
mental_mutations_scores = get_score_list(mental_mutations_cnt, intscore)
|
||||
mutations_table['mental'] = get_mutations(mental_mutations_scores)
|
||||
|
||||
physical_mutations_scores = get_score_list(physical_mutations_cnt, conscore)
|
||||
mutations_table['physical'] = get_mutations(physical_mutations_scores)
|
||||
|
||||
return mutations_table
|
4
app/functions/split_number.py
Normal file
4
app/functions/split_number.py
Normal file
@ -0,0 +1,4 @@
|
||||
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
|
0
app/models/__init__.py
Normal file
0
app/models/__init__.py
Normal file
@ -67,9 +67,26 @@ hp_model = {
|
||||
}
|
||||
|
||||
ma_model = {
|
||||
'ams': fields.Integer(required=True, description='Attacker Mental Strength'),
|
||||
'dms': fields.Integer(required=True, description='Defender Mental Strength'),
|
||||
'modifier': fields.Integer(required=True, description='Modifier For Mental Attack Roll'),
|
||||
'ams': fields.Integer(
|
||||
required=True,
|
||||
min=3,
|
||||
max=18,
|
||||
default=10,
|
||||
description='Attacker Mental Strength'
|
||||
),
|
||||
'dms': fields.Integer(
|
||||
required=True,
|
||||
min=3,
|
||||
max=18,
|
||||
default=10,
|
||||
description='Defender Mental Strength'
|
||||
),
|
||||
'modifier': fields.Integer(
|
||||
required=False,
|
||||
min=-100,
|
||||
max=100,
|
||||
default=0,
|
||||
description='Modifier For Mental Attack Roll'),
|
||||
}
|
||||
|
||||
character_model = {
|
0
app/schemas/__init__.py
Normal file
0
app/schemas/__init__.py
Normal file
0
app/tables/__init__.py
Normal file
0
app/tables/__init__.py
Normal file
Loading…
Reference in New Issue
Block a user