Rewrite README to focus on game usage, remove personal content and license
This commit is contained in:
@@ -1,340 +0,0 @@
|
|||||||
from functions import *
|
|
||||||
from enum import Enum, auto
|
|
||||||
from random import randint
|
|
||||||
from scenes import entry
|
|
||||||
|
|
||||||
|
|
||||||
class Player:
|
|
||||||
"""Character Creation"""
|
|
||||||
|
|
||||||
# Default Character
|
|
||||||
def __init__(self, name, gender, age, race, job):
|
|
||||||
# Personality
|
|
||||||
self.name = name
|
|
||||||
self.gender = gender
|
|
||||||
self.age = age
|
|
||||||
self.race = race
|
|
||||||
self.job = job
|
|
||||||
# Health
|
|
||||||
self.currentHP = 100
|
|
||||||
self.maxHP = 100
|
|
||||||
# Levels
|
|
||||||
self.level = 1
|
|
||||||
self.exp = 0
|
|
||||||
self.maxEXP = 100
|
|
||||||
# Magic
|
|
||||||
self.spells_known = []
|
|
||||||
self.spells_ready = []
|
|
||||||
# Equipment
|
|
||||||
self.weapon = rock
|
|
||||||
self.armor = tornRags
|
|
||||||
# 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}
|
|
||||||
# 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 = {rock: {"Count": 1,
|
|
||||||
"object": Weapon,
|
|
||||||
"equipped": True
|
|
||||||
},
|
|
||||||
tornRags: {"Count": 1,
|
|
||||||
"object": Armor,
|
|
||||||
"equipped": True
|
|
||||||
},
|
|
||||||
GP1: {"Count": 10,
|
|
||||||
"object": Money,
|
|
||||||
"equipped": False
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
# @property
|
|
||||||
# def dexMod(self):
|
|
||||||
# return self.mods["Dexterity"]
|
|
||||||
|
|
||||||
def getModifier(self):
|
|
||||||
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(self):
|
|
||||||
# Race
|
|
||||||
if self.race == "elf":
|
|
||||||
self.stats["Dexterity"] += 2
|
|
||||||
self.stats["Intelligence"] += 2
|
|
||||||
elif self.race == "human":
|
|
||||||
self.stats["Strength"] += 2
|
|
||||||
self.stats["Constitution"] += 2
|
|
||||||
elif self.race == "dwarf":
|
|
||||||
self.stats["Constitution"] += 2
|
|
||||||
self.stats["Strength"] += 2
|
|
||||||
|
|
||||||
# Job
|
|
||||||
elif self.job == "warrior":
|
|
||||||
self.stats["Strength"] += 2
|
|
||||||
self.stats["Constitution"] += 1
|
|
||||||
elif self.job == "ranger":
|
|
||||||
self.stats["Dexterity"] += 2
|
|
||||||
self.stats["Charisma"] += 1
|
|
||||||
elif self.job == "mage":
|
|
||||||
self.stats["Intelligence"] += 2
|
|
||||||
self.stats["Charisma"] += 1
|
|
||||||
|
|
||||||
def introduce(self):
|
|
||||||
typingPrint("Adjusting for your race and class bonuses." + "\n", time)
|
|
||||||
time.sleep(1)
|
|
||||||
typingPrint(f'Welcome {self.name}, to Kanjin: An RPG Text Adventure.\n', time)
|
|
||||||
|
|
||||||
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'Charisma: {self.stats["Charisma"]}')
|
|
||||||
|
|
||||||
def current_equip(self):
|
|
||||||
"""Prints a list of items currently equipped."""
|
|
||||||
typingPrint(f"You have equipped:\n {self.armor.name}\n"
|
|
||||||
f" {self.armor.description}"
|
|
||||||
f"\n{self.weapon.name}\n"
|
|
||||||
f" {self.weapon.description}\n", time)
|
|
||||||
|
|
||||||
def new_char(self):
|
|
||||||
"""Outputs final stats, armour, and inventory"""
|
|
||||||
typingPrint("We will now generate random stats for your character.\n", time)
|
|
||||||
self.introduce()
|
|
||||||
print(' ')
|
|
||||||
time.sleep(2)
|
|
||||||
self.rollStats()
|
|
||||||
self.set_stats()
|
|
||||||
print(' ')
|
|
||||||
self.getModifier()
|
|
||||||
self.current_stats()
|
|
||||||
print(' ')
|
|
||||||
time.sleep(2)
|
|
||||||
self.current_equip()
|
|
||||||
print(' ')
|
|
||||||
current_inventory()
|
|
||||||
print(' ')
|
|
||||||
|
|
||||||
def rollStats(self):
|
|
||||||
"""Rolls stats 4d6kh3"""
|
|
||||||
# Roll stats
|
|
||||||
typingPrint("Rolling for Strength...\n", time)
|
|
||||||
self.dice_rolls("Strength")
|
|
||||||
typingPrint(f'Strength: {self.stats["Strength"]}\n', time)
|
|
||||||
time.sleep(1)
|
|
||||||
typingPrint("Rolling for Dexterity...\n", time)
|
|
||||||
self.dice_rolls("Dexterity")
|
|
||||||
typingPrint(f'Dexterity: {self.stats["Dexterity"]}\n', time)
|
|
||||||
time.sleep(1)
|
|
||||||
typingPrint("Rolling for Constitution...\n", time)
|
|
||||||
self.dice_rolls("Constitution")
|
|
||||||
typingPrint(f'Constitution: {self.stats["Constitution"]}\n', time)
|
|
||||||
time.sleep(1)
|
|
||||||
typingPrint("Rolling for Intelligence...\n", time)
|
|
||||||
self.dice_rolls("Intelligence")
|
|
||||||
typingPrint(f'Intelligence: {self.stats["Intelligence"]}\n', time)
|
|
||||||
time.sleep(1)
|
|
||||||
typingPrint("Rolling for Wisdom...\n", time)
|
|
||||||
self.dice_rolls("Wisdom")
|
|
||||||
typingPrint(f'Wisdom: {self.stats["Wisdom"]}\n', time)
|
|
||||||
time.sleep(1)
|
|
||||||
typingPrint("Rolling for Charisma...\n", time)
|
|
||||||
self.dice_rolls("Charisma")
|
|
||||||
typingPrint(f'Charisma: {self.stats["Charisma"]}\n', time)
|
|
||||||
time.sleep(1)
|
|
||||||
|
|
||||||
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 dice_rolls(self, attribute):
|
|
||||||
"""Rolling 4d6 to get stats for PC"""
|
|
||||||
rolls = []
|
|
||||||
# roll 4d6
|
|
||||||
for roll in range(4):
|
|
||||||
r = randint(1, 6)
|
|
||||||
rolls.append(r)
|
|
||||||
# Drop the lowest number
|
|
||||||
del rolls[rolls.index(min(rolls))]
|
|
||||||
self.stats[attribute] += sum(rolls)
|
|
||||||
return attribute
|
|
||||||
|
|
||||||
|
|
||||||
# Inventory list
|
|
||||||
def current_inventory():
|
|
||||||
"""Prints a list of items in your backpack that aren't equipped to your person."""
|
|
||||||
typingPrint(f'In your rucksack you have:\n', time)
|
|
||||||
for item_key, item_value in user.inventory.items():
|
|
||||||
for key, value in item_value.items():
|
|
||||||
if key == "equipped" and value == False:
|
|
||||||
typingPrint(f'{item_key.name}\n'
|
|
||||||
f' {item_key.description}\n', time)
|
|
||||||
|
|
||||||
|
|
||||||
# Equipment list
|
|
||||||
def equipped():
|
|
||||||
"""Print currently equipped, print a list of held armor pieces,
|
|
||||||
if input matches a held item, replace equipped condition"""
|
|
||||||
|
|
||||||
print(f"You currently have equipped: {user.armor}\n")
|
|
||||||
print("Would you like to equip something new? Y/N")
|
|
||||||
answer = input(">> ").lower().strip()
|
|
||||||
if answer == "n" or answer == "no":
|
|
||||||
pass
|
|
||||||
if answer == "y" or answer == "yes":
|
|
||||||
answer = input(
|
|
||||||
"Which which item from your inventory would you like to equip?" + "\n" + ">> ").lower().strip()
|
|
||||||
for item_key, item_value in user.inventory.items():
|
|
||||||
# item_info = dict
|
|
||||||
for key, value in item_value.items():
|
|
||||||
# Leather armor[items], "object"[key], Armor[value]
|
|
||||||
if key == "object" and value == Armor:
|
|
||||||
print("\n", item_key)
|
|
||||||
else:
|
|
||||||
print("I'm sorry, I didn't understand that." + "\n" + "Would you like to equip something new? Y/N")
|
|
||||||
|
|
||||||
|
|
||||||
class DamageType(Enum):
|
|
||||||
SLASHING = auto()
|
|
||||||
CRUSHING = auto()
|
|
||||||
PIERCING = auto()
|
|
||||||
FIRE = auto()
|
|
||||||
WATER = auto()
|
|
||||||
LIGHTNING = auto()
|
|
||||||
|
|
||||||
|
|
||||||
class DamageMod(Enum):
|
|
||||||
STRENGTH = auto()
|
|
||||||
DEXTERITY = auto()
|
|
||||||
CONSTITUTION = auto()
|
|
||||||
INTELLIGENCE = auto()
|
|
||||||
WISDOM = auto()
|
|
||||||
CHARISMA = auto()
|
|
||||||
|
|
||||||
|
|
||||||
class Item:
|
|
||||||
"""The base class for all items"""
|
|
||||||
|
|
||||||
def __init__(self, name, description, value, magical):
|
|
||||||
self.name = name
|
|
||||||
self.description = description
|
|
||||||
self.value = value
|
|
||||||
self.magical = magical
|
|
||||||
|
|
||||||
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):
|
|
||||||
self.name = name
|
|
||||||
self.amt = amt
|
|
||||||
self.magical = magical
|
|
||||||
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)
|
|
||||||
|
|
||||||
|
|
||||||
class Weapon(Item):
|
|
||||||
"""The base class for all weapons"""
|
|
||||||
|
|
||||||
def __init__(self, name, description, value, damage1H, damage2H, dmgType, dmgMod, vers, thrown, magical):
|
|
||||||
self.damage1H = damage1H
|
|
||||||
self.damage2H = damage2H
|
|
||||||
self.dmgType = dmgType
|
|
||||||
self.dmgMod = dmgMod
|
|
||||||
self.vers = vers
|
|
||||||
self.thrown = thrown
|
|
||||||
super().__init__(name, description, value, magical)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f"{self.name}\n=====\n{self.description}\nValue: {self.value}" \
|
|
||||||
f"\nDamage: One Handed - {self.damage1H}" \
|
|
||||||
f"\nDamage: Two Handed - {self.damage2H}\n" \
|
|
||||||
f"Damage Type: {self.dmgType}\nMagical: {self.magical}.\n"
|
|
||||||
|
|
||||||
|
|
||||||
class Armor(Item):
|
|
||||||
"""The base class for all armor"""
|
|
||||||
|
|
||||||
def __init__(self, name, description, value, grade, ac, disadvantage, dmgRes, magical):
|
|
||||||
self.grade = grade
|
|
||||||
self.ac = ac
|
|
||||||
self.stealthDis = disadvantage
|
|
||||||
self.dmgRes = dmgRes
|
|
||||||
super().__init__(name, description, value, magical)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
if self.stealthDis:
|
|
||||||
return f"{self.name}\n=====\n{self.description}\nValue: {self.value}\n" \
|
|
||||||
f"AC: {self.ac}\nMagical: {self.magical}"
|
|
||||||
elif not self.stealthDis:
|
|
||||||
return f"{self.name}\n=====\n{self.description}\nValue: {self.value}\n" \
|
|
||||||
f"AC: {self.ac}\nDisadvantage on Stealth checks: {self.stealthDis}\nMagical: {self.magical}"
|
|
||||||
|
|
||||||
|
|
||||||
# Different types of coins
|
|
||||||
GP1 = Money("Gold", 1, False)
|
|
||||||
SP1 = Money("Silver", 1, False)
|
|
||||||
CP1 = Money("Copper", 1, False)
|
|
||||||
|
|
||||||
rock = Weapon(
|
|
||||||
name="Rock",
|
|
||||||
description="A fist-sized rock, suitable for bludgeoning.",
|
|
||||||
value="No value",
|
|
||||||
damage1H=randint(1, 6),
|
|
||||||
damage2H=0,
|
|
||||||
dmgType=DamageType.CRUSHING,
|
|
||||||
dmgMod=DamageMod.STRENGTH,
|
|
||||||
vers=False,
|
|
||||||
thrown=True,
|
|
||||||
magical=False
|
|
||||||
)
|
|
||||||
tornRags = Armor(
|
|
||||||
name="Torn Rags",
|
|
||||||
description="A ripped and worn-out outfit.",
|
|
||||||
value=0,
|
|
||||||
grade="Light",
|
|
||||||
ac=0,
|
|
||||||
disadvantage=True,
|
|
||||||
dmgRes="None",
|
|
||||||
magical=False
|
|
||||||
)
|
|
||||||
|
|
||||||
# user = Player(*startGame())
|
|
||||||
user = Player("Jamie", "Male", 29, "Elf", "Mage")
|
|
||||||
# user.new_char()
|
|
||||||
entry()
|
|
||||||
31
README.md
31
README.md
@@ -1,13 +1,30 @@
|
|||||||
# Kanjin-Text-RPG
|
# Kanjin-Text-RPG
|
||||||
An RPG text adventure game based of the Dungeons and Dragons SRD.
|
|
||||||
|
|
||||||
This game is being used as a learning experience for myself to practice code and learn by doing.
|
A text adventure RPG based on the Dungeons & Dragons 5e SRD.
|
||||||
It started as a text only RPG, diverged into using QtPy5, then to Pygame with Pygame GUI and as of this point (15/01/2022) is back to text only but being rebuilt with the use of a game engine parsing map data as per ex. 43 of Zed Shaw's book 'Learn Python the Hard Way'.
|
|
||||||
|
|
||||||
When running the code, make sure the pregen character is hashed out and you're running the startGame() function. If you're play testng, hash out this function and use a pregen to skip past character creation.
|
## Running
|
||||||
|
|
||||||
While still very much a large work in progress, I am comfortable with the direction the build is taking. Focusing mostly on getting the framework completed, the later steps will be to add more story and scenes, then finally to work on a bit more graphic design.
|
```bash
|
||||||
|
python main.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Pure Python stdlib — no dependencies required.
|
||||||
|
|
||||||
|
## Playing
|
||||||
|
|
||||||
|
The game uses a directed graph of scenes with directional exits (north, south, east, west). Type `help` at any prompt for a full command list. Basic commands:
|
||||||
|
|
||||||
|
- `go [direction]` — move between scenes
|
||||||
|
- `look around` — see what's in the area
|
||||||
|
- `take [item]` / `loot [container]` — pick up items
|
||||||
|
- `examine [item]` — inspect an item
|
||||||
|
- `inventory` / `equipment` / `stats` — review your character
|
||||||
|
- `cast [spell]` / `rest` — spellcasting and recovery
|
||||||
|
|
||||||
|
## Character creation
|
||||||
|
|
||||||
|
Choose **"Create a new character"** for full creation with stat allocation, or **"Pre-Gen Character"** to pick one of three ready-to-play characters (Elven Wizard, Human Barbarian, Dwarven Cleric).
|
||||||
|
|
||||||
|
During playtesting, you can skip character creation by replacing `startGame()` in `main.py` with a pre-generated character and assigning stats directly (see `main.py:274-290` and `function_list.py:14-94`).
|
||||||
|
|
||||||
Taking many cues, pieces of advice, and explanation; this code is still 100% done and made by myself (Caveat: 29/10/2022 have brought in an Alex to assist.)
|
|
||||||
|
|
||||||
The code has no licence and as such is not free, is not available for modification, reduplication, sale, or any other use without explicit permission from myself.
|
|
||||||
|
|||||||
Reference in New Issue
Block a user