Files
Kanjin/player.py
2025-06-26 21:42:55 +12:00

637 lines
25 KiB
Python

import function_list
from random import randint
from enum_list import *
class Inventory:
def __init__(self):
self.items = []
def add_item(self, item):
self.items.append(item)
print(f"Added {item.name} to inventory.")
def remove_item(self, item):
if item in self.items:
self.items.remove(item)
print(f"Removed {item.name} from inventory.")
else:
print("Item not found in inventory.")
@staticmethod
def current_inventory():
"""Prints a list of items in your backpack that aren't equipped to your person."""
print(f'In your rucksack you have:')
for item_key, item_value in Inventory.items(): # string, dictionary
if item_key not in Equipment.values():
values = item_value.values() # make a variable of all values
values_list = list(values) # turn variable into a list
count_value = values_list[0] # take the first value from list - why?
print(f'{item_key.name} x {count_value}\n'
f' {item_key.description}\n')
@staticmethod
def current_equipment():
"""Prints a list of items that you have equipped in your slots."""
print(f'You are currently wearing:')
for slot, equipment in Equipment.items(): # string, dictionary
if equipment is not None:
if slot == "Attunement":
continue
elif equipment.itemType == ItemType.Weapon:
if equipment.versatile:
print(f'{slot}: {equipment.name} - {equipment.versatiledmg}\n'
f' {equipment.description}\n')
continue
elif equipment.damage1H is not None:
print(f'{slot}: {equipment.name} - {equipment.damage1H}\n'
f' {equipment.description}\n')
elif equipment.damage2H is not None:
print(f'{slot}: {equipment.name} - {equipment.damage2H}\n'
f' {equipment.description}\n')
elif equipment.itemType == ItemType.Armor:
print(f'{slot}: {equipment.name} - AC {equipment.ac}\n'
f' {equipment.description}\n')
elif equipment.itemType == ItemType.Item:
print(f'{slot}: {equipment.name}\n'
f' {equipment.description}\n')
class Player:
"""Character Creation"""
# Default Character
def __init__(self, name, gender, age, race, job):
# Identity
self.name = name
self.gender = gender
self.age = age
self.race = race
self.job = job
# Defence
self.ac = 0
self.elemental_resistance = {DamageType.Fire: False, DamageType.Water: False, DamageType.Lightning: False}
self.physical_resistance = {DamageType.Slashing: False, DamageType.Crushing: False, DamageType.Piercing: False}
# Health (move off Player, keep on Job)
# self.hitDie = self.job.hd
# self.currentHP = 100
# self.maxHP = 100
# Levels
self.level = 1
self.exp = 0
self.maxEXP = 100
# Magic (Not ready yet)
# self.spells_known = []
# self.spells_ready = []
# Equipment
self.weapon = rock
self.armor = tornRags
# Ability Scores
self.stats = {"Strength": 0,
"Dexterity": 0,
"Constitution": 0,
"Intelligence": 0,
"Wisdom": 0,
"Charisma": 0}
# Ability Modifiers
self.mods = {"Strength": 0,
"Dexterity": 0,
"Constitution": 0,
"Intelligence": 0,
"Wisdom": 0,
"Charisma": 0}
# Held items
self.inventory = Inventory
def getModifier(self):
"""Floor calculation to work out skill check modifiers"""
self.mods["Strength"] = -5 + self.stats["Strength"] // 2
self.mods["Dexterity"] = -5 + self.stats["Dexterity"] // 2
self.mods["Constitution"] = -5 + self.stats["Constitution"] // 2
self.mods["Intelligence"] = -5 + self.stats["Intelligence"] // 2
self.mods["Wisdom"] = -5 + self.stats["Wisdom"] // 2
self.mods["Charisma"] = -5 + self.stats["Charisma"] // 2
def set_stats_race(self):
if self.race.lower() == "human":
print("As a Human, two different ability scores of your choice increase by 1.")
selection1 = input("Choose the first ability score to increase by 1.\n"
"1) Strength\n"
"2) Dexterity\n"
"3) Constitution\n"
"4) Intelligence\n"
"5) Wisdom\n"
"6) Charisma\n\n >> ").lower()
while True:
if selection1 in ("1", "strength"):
self.stats["Strength"] += 1
break
elif selection1 in ("2", "dexterity"):
self.stats["Dexterity"] += 1
break
elif selection1 in ("3", "constitution"):
self.stats["Constitution"] += 1
break
elif selection1 in ("4", "intelligence"):
self.stats["Intelligence"] += 1
break
elif selection1 in ("5", "wisdom"):
self.stats["Wisdom"] += 1
break
elif selection1 in ("6", "charisma"):
self.stats["Charisma"] += 1
break
else:
selection1 = input("Sorry, I didn't recognise that. Please select from the following:\n"
"1) Strength\n"
"2) Dexterity\n"
"3) Constitution\n"
"4) Intelligence\n"
"5) Wisdom\n"
"6) Charisma\n >> ").lower()
continue
selection2 = input("Choose the second ability score to increase by 1.\n"
"1) Strength\n"
"2) Dexterity\n"
"3) Constitution\n"
"4) Intelligence\n"
"5) Wisdom\n"
"6) Charisma\n\n >> ").lower()
while True:
if selection2 in ("1", "strength"):
self.stats["Strength"] += 1
break
elif selection2 in ("2", "dexterity"):
self.stats["Dexterity"] += 1
break
elif selection2 in ("3", "constitution"):
self.stats["Constitution"] += 1
break
elif selection2 in ("4", "intelligence"):
self.stats["Intelligence"] += 1
break
elif selection2 in ("5", "wisdom"):
self.stats["Wisdom"] += 1
break
elif selection2 in ("6", "charisma"):
self.stats["Charisma"] += 1
break
else:
selection2 = input("Sorry, I didn't recognise that. Please select from the following:\n"
"1) Strength\n"
"2) Dexterity\n"
"3) Constitution\n"
"4) Intelligence\n"
"5) Wisdom\n"
"6) Charisma\n >> ").lower()
continue
elif self.race.lower() == "elf":
self.stats["Dexterity"] += 2
elif self.race.lower() == "dwarf":
self.stats["Constitution"] += 2
def set_stats_job(self):
if self.job.lower() == "warrior":
self.hitDie = randint(1, 12)
self.maxHP = (12 + self.mods["Constitution"])
self.currentHP = (12 + self.mods["Constitution"])
elif self.job.lower() == "cleric":
self.hitDie = randint(1, 10)
self.maxHP = (10 + self.mods["Constitution"])
self.currentHP = (10 + self.mods["Constitution"])
elif self.job.lower() == "mage":
self.hitDie = randint(1, 8)
self.maxHP = (8 + self.mods["Constitution"])
self.currentHP = (8 + self.mods["Constitution"])
def current_stats(self):
"""Prints a display of the user's current statistics."""
print("Your current stats are:")
print(f'Hit Points: {self.currentHP}/{self.maxHP}')
print(f'Strength: {self.stats["Strength"]}')
print(f'Dexterity: {self.stats["Dexterity"]}')
print(f'Constitution: {self.stats["Constitution"]}')
print(f'Intelligence: {self.stats["Intelligence"]}')
print(f'Wisdom: {self.stats["Wisdom"]}')
print(f'Charisma: {self.stats["Charisma"]}')
def current_equip(self):
"""Prints a list of items currently equipped."""
print(f"You have equipped:\n {self.armor.name}\n"
f" {self.armor.description}"
f"\n{self.weapon.name}\n"
f" {self.weapon.description}")
def drop_item(self, object1):
x = None
for list_key, list_value in self.inventory.items(): # string, dictionary
if object1 in list_key.name.lower(): # if user input is in the inventory list
x = self.inventory.copy()
del x[list_key]
print("Did I drop it?")
return x
# Add the inventory commands to parser // take off Player
def update_inventory(self, x):
self.inventory = x
def loot_object(self, object1):
for scene, room in Map.scenes.items(): # iterate map scenes
if Engine.seed == scene: # set new Engine seed in each room.enter()
for list_key, list_value in room.lootable_items.items(): # string, dictionary
for var, count in list_value.items(): # variable/object, integer
if object1 in list_key: # if user input is in the lootable items
if var in self.inventory: # if object is in inventory
self.inventory[var]["Count"] += count # increase item count
print(f'{var.name} x {count} has been added to your existing stack.')
elif var not in self.inventory[var]: # if variable not in inventory
self.inventory[var] = {"Count": count, # add it in
"object": var.type,
"equipped": False}
print(f'{var.name} x {count} has been added to your rucksack.')
room.lootable_items[object1][var] = 0 # set item to 0
break
else:
print("You don't see one of those to loot.")
break
def add_inventory(self, object1):
for scene, room in Map.scenes.items(): # iterate map scenes
if Engine.seed == scene: # set new Engine seed in each room.enter()
for list_key, list_value in room.available_items.items(): # string, dictionary
for var, count in list_value.items(): # variable/object, integer
if object1 in list_key: # if user input is in the available items
response = input(f'There are {room.available_items[object1][var]}.\n'
f'How many will you take?\n>> ').lower()
if response in ("0", "none"):
break
elif response == "all":
if var in self.inventory:
self.inventory[var]["Count"] += count # increase item count
print(f'{var.name} x {count} has been added to your existing stack.')
room.available_items[object1][var] = 0
elif var not in self.inventory: # if objects not in inventory
self.inventory[var] = {"Count": count, # add it in
"object": var.type,
"equipped": False}
print(f'{var.name} x {count} has been added to your rucksack.')
room.available_items[object1][var] = 0
elif int(response) <= count:
if var in self.inventory:
self.inventory[var]["Count"] += int(response) # increase item count
print(f'{var.name} x {response} has been added to your existing stack.')
room.available_items[object1][var] = \
room.available_items[object1][var] - int(response)
elif var not in self.inventory: # if objects not in inventory
self.inventory[var] = {"Count": response, # add it in
"object": var.type,
"equipped": False}
print(f'{var.name} x {response} has been added to your rucksack.')
room.available_items[object1][var] = \
room.available_items[object1][var] - int(response)
else:
print("You can't take more than exist.")
break
else:
print("You don't see any lying around..")
break
def new_char(self):
"""Outputs final stats, armour, and inventory"""
self.allocation()
self.set_stats_race()
self.set_stats_job()
self.getModifier()
self.current_stats()
print(' ')
function_list.current_equipment()
print(' ')
function_list.current_inventory()
print(' ')
def health_check(self):
"""Print out current/max HP"""
print(f'You have {self.currentHP}/{self.maxHP} HP.')
def take_damage(self, DMGtype, size):
"""Define the damage type and dice size"""
damage = randint(1, size)
if DMGtype in self.elemental_resistance or DMGtype in self.physical_resistance:
damage //= 2
self.currentHP -= damage
return damage
def allocation(self):
while True:
rolls = []
stats = []
attributes = ["Strength", "Dexterity", "Constitution", "Intelligence", "Wisdom", "Charisma"]
while len(stats) != 6:
# roll 4d6
for roll in range(4):
r = randint(1, 6)
if r < 6:
r = randint(1, 6)
rolls.append(r)
# Drop the lowest number and then add to single value
del rolls[rolls.index(min(rolls))]
val = sum(rolls)
stats.append(str(val))
rolls = []
print(f"Please assign a stat to a selected attribute by entering the number then the attribute.\n"
f"For example, '10 strength' will assign 10 to your strength, if you have a 10 available.\n\n"
f"Please select a stat and an attribute.\n\n"
f"Your rolled stats are:\n {', '.join(stats)}\n\n"
f"Your attributes are:\n {', '.join(attributes)}\n")
# Allocate
while len(stats) != 0:
input_text = input(">> ").title()
words = input_text.split()
if len(words) <= 2:
if words[0] in stats and words[1] in attributes:
self.stats[words[1]] += int(words[0])
stats.remove(words[0])
attributes.remove(words[1])
if len(stats) == 1:
self.stats[attributes[0]] += int(stats[0])
print("")
break
print(f"The remaining stats are:\n {', '.join(stats)}\n\n"
f"The remaining attributes are:\n {', '.join(attributes)}")
else:
print("Error. Input was not recognised. Please try again with 'Number' + 'Attribute'.")
continue
else:
print("Error. Input was not recognised. Please try again with 'Number' + 'Attribute'.")
continue
print(f"Your current stats are:\n"
f'Strength: {self.stats["Strength"]}\n'
f'Dexterity: {self.stats["Dexterity"]}\n'
f'Constitution: {self.stats["Constitution"]}\n'
f'Intelligence: {self.stats["Intelligence"]}\n'
f'Wisdom: {self.stats["Wisdom"]}\n'
f'Charisma: {self.stats["Charisma"]}\n')
select = input("Are you happy with this selection? Y/N?\n"
"WARNING: If you select 'N', your dice will be randomly rolled again. Proceed?\n"
" >> ").lower()
if select == "n":
continue
if select == 'y':
break
elif select not in ("y", "n"):
print("Error. Input was not recognised. Please select 'Y' or 'N'.")
select = input("Are you happy with this selection? Y/N?\n"
"WARNING: If you select 'N', your dice will be randomly rolled again. Proceed?\n"
" >> ").lower()
if select == "y":
break
else:
continue
class Item:
"""The base class for all items"""
def __init__(self, name, description, value, magical, itemType, attunement):
self.name = name
self.description = description
self.value = value
self.magical = magical
self.itemType = itemType
self.attunement = attunement
def __repr__(self):
return f"{self.name}\n=====\n{self.description}\nValue: {self.value}\n"
class Money(Item):
"""The currency item used in the world of Kanjin"""
def __init__(self, name, amt, magical, ItemType):
self.name = name
self.amt = amt
self.magical = magical
self.itemType = ItemType
super().__init__(name=self.name,
description=f"A small round coin made of {self.name.lower()} "
f"with the imperial city logo stamped on the face.",
value=self.amt,
magical=self.magical,
ItemType=ItemType.Money,
attunement=False)
class Weapon(Item):
"""The base class for all weapons"""
def __init__(self, name, description, value, slot, damage1H, damage2H, versatiledmg,
dmgType, dmgMod, versatile, thrown, ItemType, magical, attunement):
self.slot = slot
self.damage1H = damage1H
self.damage2H = damage2H
self.versatiledmg = versatiledmg
self.dmgType = dmgType
self.dmgMod = dmgMod
self.versatile = versatile
self.thrown = thrown
self.itemType = ItemType
super().__init__(name, description, value, magical, ItemType, attunement)
def __str__(self):
if self.damage2H is None and self.damage1H is not None:
return f"{self.name}\n=====" \
f"\n{self.description}" \
f"\nValue: {self.value}" \
f"\nDamage: One Handed - {self.damage1H}" \
f"\nDamage Type: {self.dmgType.name.title()}" \
f"\nMagical: {self.magical}" \
f"\nAttunement: {'Required' if self.attunement else 'Not Required'}"
elif self.damage1H is None and self.damage2H is not None:
return f"{self.name}\n=====" \
f"\n{self.description}" \
f"\nValue: {self.value}" \
f"\nDamage: Two Handed - {self.damage2H}" \
f"\nDamage Type: {self.dmgType.name.title()}" \
f"\nMagical: {self.magical}" \
f"\nAttunement: {'Required' if self.attunement else 'Not Required'}"
elif self.versatile:
return f"{self.name}\n=====" \
f"\n{self.description}" \
f"\nValue: {self.value}" \
f"\nDamage: Versatile - {self.versatiledmg}" \
f"\nDamage Type: {self.dmgType.name.title()}" \
f"\nMagical: {self.magical}" \
f"\nAttunement: {'Required' if self.attunement else 'Not Required'}"
else:
return f"{self.name}\n=====" \
f"\n{self.description}" \
f"\nValue: {self.value}" \
f"\nMagical: {self.magical}" \
f"\nAttunement: {'Required' if self.attunement else 'Not Required'}"
class Armor(Item):
"""The base class for all armor"""
def __init__(self, name, description, value, grade, ac, disadvantage, dmgRes, ItemType, magical, attunement):
self.grade = grade
self.ac = ac
self.stealthDis = disadvantage
self.dmgRes = dmgRes
self.itemType = ItemType
super().__init__(name, description, value, magical, ItemType, attunement)
def __repr__(self):
if self.stealthDis:
return f"{self.name}\n" \
f"=====\n" \
f"{self.description}\n" \
f"Value: {self.value}\n" \
f"AC: {self.ac}\n" \
f"Magical: {self.magical}"
elif not self.stealthDis:
return f"{self.name}\n=====" \
f"\n{self.description}\n" \
f"Value: {self.value}\n" \
f"AC: {self.ac}\n" \
f"Disadvantage on Stealth checks: {self.stealthDis}\n" \
f"Magical: {self.magical}\n"
# Different types of coins
GP1 = Money("Gold", 1, False, ItemType.Money)
SP1 = Money("Silver", 1, False, ItemType.Money)
CP1 = Money("Copper", 1, False, ItemType.Money)
# starting equip
rock = Weapon(
name="Rock",
description="A fist-sized rock, suitable for bludgeoning.",
value=None,
slot="Main Hand",
damage1H='1d6',
damage2H=None,
versatiledmg=None,
dmgType=DamageType.Crushing,
dmgMod=DamageMod.Strength,
versatile=False,
thrown=True,
magical=False,
ItemType=ItemType.Weapon,
attunement=True
)
dagger = Weapon(
name="Dagger",
description="Pointy stabby-stab",
value=None,
slot="Main Hand",
damage1H=None,
damage2H=None,
versatiledmg='1d6',
dmgType=DamageType.Slashing,
dmgMod=DamageMod.Dexterity,
versatile=True,
thrown=True,
magical=False,
ItemType=ItemType.Weapon,
attunement=True
)
polearm = Weapon(
name="Polearm",
description="Long Pointy stabby-stab",
value=None,
slot="Two Handed",
damage1H=None,
damage2H="2d6",
versatiledmg=None,
dmgType=DamageType.Piercing,
dmgMod=DamageMod.Strength,
versatile=False,
thrown=True,
magical=False,
ItemType=ItemType.Weapon,
attunement=True
)
tornRags = Armor(
name="Torn Rags",
description="A ripped and worn-out outfit.",
value=None,
grade="Light",
ac=0,
disadvantage=True,
dmgRes="None",
magical=False,
ItemType=ItemType.Armor,
attunement=True
)
paper = Item(
name="Paper",
description="A blank piece of paper",
value=None,
magical=False,
ItemType=ItemType.Item,
attunement=True
)
Inventory = {
rock: {"Count": 1,
"object": Weapon,
},
dagger: {"Count": 1,
"object": Weapon,
},
polearm: {"Count": 1,
"object": Weapon
},
paper: {"Count": 1,
"object": Item
},
tornRags: {"Count": 1,
"object": Armor
},
GP1: {"Count": 10,
"object": Money
},
}
Equipment = {
"Main Hand": rock,
"Off Hand": None,
"Two Handed": None,
"Helm": None,
"Chest": tornRags,
"Wrists": None,
"Feet": None,
"Neck": None,
"Cloak": None,
"Left Ring": None,
"Right Ring": None,
"Other": paper,
"Attunement": 0
}