Rename Kanjin to Kanjin-Engine

Current focus build.
This commit is contained in:
KansaiGaijin
2022-01-15 15:43:08 +13:00
committed by GitHub
parent 687a5c9dc4
commit d051d815be

554
Kanjin-Engine Normal file
View File

@@ -0,0 +1,554 @@
# This file contains all classes for player, objects, and scenes.
# All interactable items will also be created here.
# The game engine can be found at the bottom.
import time
from random import randint
from functions import startGame, typingPrint, typingInput
from enum import Enum, auto
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):
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
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 current_stats(self):
"""Prints a display of the user's current statistics."""
typingPrint("Your current stats are:\n", time)
typingPrint(f'Hit Points: {self.currentHP}/{self.maxHP}\n', time)
typingPrint(f'Strength: {self.stats["Strength"]}\n', time)
typingPrint(f'Dexterity: {self.stats["Dexterity"]}\n', time)
typingPrint(f'Constitution: {self.stats["Constitution"]}\n', time)
typingPrint(f'Intelligence: {self.stats["Intelligence"]}\n', time)
typingPrint(f'Charisma: {self.stats["Charisma"]}\n', time)
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)
# typingPrint("Adjusting for your race and class bonuses.\n", time)
# print(' ')
# time.sleep(2)
self.dicerolls()
self.allocation()
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 dicerolls(self):
"""Rolling 4d6 to get stat value for PC"""
rolls = []
# roll 4d6
for roll in range(4):
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)
return str(val)
def allocation(self):
# Display rolls and instructions
stats = []
attributes = ["Strength", "Dexterity", "Constitution", "Intelligence", "Wisdom", "Charisma"]
for _ in range(6):
stats.append((Player.dicerolls(self)))
print("Please assign a stat to a selected attribute by entering the number then the attribute.\n"
"For example, '10 strength' will assign the stat 10 to your strength, if you have a 10 showing.\n"
"Type 'Finish' when you think you're ready to view your allocation before replacing or continuing.\n")
print("Please select a stat and an attribute")
print("Your rolled stats are:\n" + ', '.join(stats) + "\n")
print("Your attributes are:\n" + ', '.join(attributes) + "\n")
# Allocate
while len(stats) != 0:
input_text = input("> ").title()
words = input_text.split()
print(words[0], words[1], len(stats))
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])
print("The remaining options are:\n")
print(stats)
print(attributes)
elif words[0] in ["fin", "end", "finish", "cont", "continue"]:
print(self.stats)
break
else:
print("Error")
break
class Scene(object):
def enter(self):
print(self.name) # works
print(self.descrip) # works
# this applies to all classes under Scene, but Zed does it differently
class Engine(object):
def __init__(self, scene_map):
self.name = "name"
self.descrip = "descrip"
self.scene_map = scene_map
# gets the game's map from instance "mymap" at bottom of this file
def play(self):
current_scene = self.scene_map.opening_scene()
last_scene = self.scene_map.next_scene('Finished')
# see the Map object: runs function named opening_scene()
# this runs only once
# this STARTS THE GAME
# this (below) is supposed to be an infinite loop (but mine is not)
while not last_scene:
next_scene_name = current_scene.enter()
current_scene = self.scene_map.next_scene(next_scene_name)
print("\n--------")
current_scene.enter()
# note: will throw error if no new scene passed in by next line:
next_scene_name = current_scene.action()
# get the name of the next scene from the action() function that
# runs in the current scene - what it returns
current_scene = self.scene_map.next_scene(next_scene_name)
# here we use that val returned by current scene to go to
# the next scene, running function in Map
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")
class Begin(Scene):
name = "Welcome to Kanjin"
descrip = "Chocolate"
descTrue = "You return to the cave entrance."
descFalse = "You are standing at the entryway to a cave."
has_visited = True
def enter(self):
typingPrint(f'\n===================\n', time)
typingPrint(f'{Begin.name}', time)
typingPrint(f'\n===================\n', time)
if self.has_visited:
typingPrint(f'\n{self.descTrue}\n'
f'\n', time)
else:
typingPrint(f'===========\n{self.descFalse}\n', time)
Begin.has_visited = True
user.new_char()
action = "begin"
if action == "begin":
typingPrint("result", time)
return "pod"
class CaveEntrance(Scene):
name = "Cave Entrance"
descTrue = "You are standing at the entryway to a cave."
descFalse = "You return to the cave entrance."
has_visited = False
def enter(self):
typingPrint(f'\n===========\n{self.name}', time)
if not self.has_visited:
typingPrint(self.descTrue, time)
else:
typingPrint(self.descTrue, time)
action = input(">> ")
if action == "shoot!":
print("result")
return "death"
elif action == "dodge":
print("result")
return "pod"
else:
print("error")
return "central corridor"
# def action(self):
# pass
class A1(Scene):
def __init__(self):
self.name = "Laser Weapon Armory"
self.descrip = "Shelves and cases line the walls of this room. Weapons of every description " \
"fill the shelves and cases. There is a digital keypad set into the wall."
def enter(self):
print(f'\n===========\n'
f'{self.name}'
f'\n===========\n'
f'{self.descrip}')
def action(self):
pass
# class Death(Scene):
#
# def __init__(self):
# self.name = "You have died!"
# self.descrip = "Your spirit leaves swiftly as your body collapses."
#
# quips = [
# "You died. You kinda suck at this.",
# "Your Mom would be proud...if she were smarter.",
# "Such a loser.",
# "I have a small puppy that's better at this.",
# "You're worse than your Dad's jokes."
# ]
#
# def enter(self):
# print(Death.quips[randint(0, len(self.quips) - 1)])
# exit(1)
#
# def action(self):
# pass
#
#
# class TheBridge(Scene):
#
# def __init__(self):
# self.name = "The Bridge"
# self.descrip = "Clearly this is a central command station of the spaceship. A wide view screen shows the" \
# " stars against a black curtain of empty space."
#
# def enter(self):
# print(f'\n===========\n'
# f'{self.name}'
# f'\n===========\n'
# f'{self.descrip}')
#
# def action(self):
# pass
class EscapePod(Scene):
name = "Escape Pod"
with open('pod.txt') as d:
descrip = d.read()
def enter(self):
print(f'\n===========\n'
f'{self.name}'
f'\n===========\n'
f'{self.descrip}')
action = input(">> ")
if action == "shoot!":
print("result")
return "death"
elif action == "dodge":
print("result")
return "pod"
else:
print("error")
return "central corridor"
def action(self):
pass
# Map tells us where we are and where we can go
# it does not make us move - Engine does that
class Map(object):
scenes = {
'Cave entrance': CaveEntrance(),
'A1': A1(),
# 'death': Death(),
# 'bridge': TheBridge(),
'pod': EscapePod(),
"begin": Begin()
}
def __init__(self, start_scene_key):
self.start_scene_key = start_scene_key
# above we make a local var named start_scene_key
# start_scene_key remains unchanged throughout the game
def next_scene(self, scene_name):
val = Map.scenes.get(scene_name)
# above is how we get value out of the dictionary named scenes
return val
# this function can be called repeatedly in the game,
# unlike opening_scene, which is called only ONCE
def opening_scene(self):
return self.next_scene(self.start_scene_key)
# this function exists only for starting, using the first
# string we passed in ('corridor')
# it combines the previous 2 functions and is called only once
# (called in Engine)
# print("\nType one of the following words: pod, corridor, bridge, armory, death.")
seed = "begin" # or input("> ")
# this is for testing only - get the "seed" for the map
mymap = Map(seed) # instantiate a new Map object w/ one arg
mygame = Engine(mymap) # instantiate a new Engine object w/ one arg
mygame.play() # call function from that Engine instance