Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 20 additions & 8 deletions builtin.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
from __future__ import annotations #needed for Node type hints
from __future__ import annotations # needed for Node type hints


# Base player classes

class Player:
def __init__(self):
self.hp = 100
self.xp = 0
self.coins_earned = 0

def summary(self):
return f'hp: {self.hp} xp: {self.xp}'
return f'hp: {self.hp} xp: {self.xp} coins: {self.coins_earned}'
Comment on lines +10 to +13
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!



# Base connection classes
Expand All @@ -23,28 +26,33 @@ def on_select(self):
def __str__(self):
return str(self.from_node) + " -> " + str(self.to_node)


# Breaking connections can only be used once
class BreakingConnection(Connection):
def __init__(self, from_node: Node, to_node: Node):
super().__init__(from_node, to_node)

def on_select(self):
self.from_node.connections.remove(self)

def __str__(self):
return str(self.from_node) + " \-> " + str(self.to_node)
return str(self.from_node) + " \\-> " + str(self.to_node)


# Base node classes

class Node:
def __init__(self, title: str, desc: str):
def __init__(self, title: str, desc: str, coins: str):
super().__init__()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't need super().init(), because this class is not inheriting anything (It's a base class)

self.title = title
self.desc = desc
self.coins = int(coins)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think coins should be stored explicitly in just the player, not the Node itself

# self.player = player
self.connections: list[Connection] = []

def on_select(self):
print(self.desc)
# self.player.coins_earned += self.coins

def add_connection(self, other: Node, type: Connection = Connection):
self.connections += [type(self, other)]
Expand All @@ -66,24 +74,28 @@ class Location(Node):

# Actions include the player for reference (augment player attributes)
class Action(Node):
def __init__(self, title: str, desc: str, player: Player):
def __init__(self, title: str, desc: str, coins: str, player: Player):
self.player = player
super().__init__(title, desc)
super().__init__(title, desc, coins)

def on_select(self):
print(self.player.summary())
self.player.coins_earned += self.coins
super(Action, self).on_select()
Comment on lines +77 to +84
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like how you added currency onto the Action class!



class Fight(Action):
def on_select(self):
self.player.hp -= 25
self.player.xp += 10
self.player.coins_earned += 50

super().on_select()


class Run(Action):
def on_select(self):
self.player.coins_earned += 10
self.player.xp = max(self.player.xp - 10, 0)

super().on_select()
super().on_select()
40 changes: 24 additions & 16 deletions crpg.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
from typing import Callable # for connection function type hints
from typing import Callable # for connection function type hints
from setup import start
import re
from builtin import Connection, BreakingConnection, Node, Location, Fight, Run, Player
from builtin import Connection, BreakingConnection, Node, Location, Fight, Run, Player, Action


# the base crpg game

class Game:
def __init__(self, player: Player = Player(), starting_location: Location = None):
self.name = start()
self.current: Node = starting_location
self.player = player
self.name: str = None
self.name: str
Comment on lines +11 to +14
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these changes belong in another PR


self.nodes: set[Node] = set()

self.add_node(self.current)

# establish nodes and connections
Expand All @@ -25,7 +27,8 @@ def add_connection(self, from_node: Node, to_node: Node, connection_type: Connec

from_node.add_connection(to_node, connection_type)

def add_twoway_connection(self, node_a: Node, node_b: Node, connection_type_a: Connection = Connection, connection_type_b: Connection = Connection):
def add_twoway_connection(self, node_a: Node, node_b: Node, connection_type_a: Connection = Connection,
connection_type_b: Connection = Connection):
Comment on lines +30 to +31
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spacing is a little off here

assert node_a in self.nodes
assert node_b in self.nodes

Expand All @@ -36,7 +39,7 @@ def add_twoway_connection(self, node_a: Node, node_b: Node, connection_type_a: C
def list_next(self):
_next = self.current.connections
for i, connection in enumerate(_next):
print(f'{i+1}) {connection.to_node}')
print(f'{i + 1}) {connection.to_node}')

# Iterate through graph, ask for choices at each node
def ask(self, query: str):
Expand All @@ -51,18 +54,17 @@ def ask(self, query: str):
choice = int(input(f'{query}'))
except ValueError:
print('Please enter a number. Try again.')
continue
continue

# check for valid choice
if (choice <= len(_next) and choice > 0):
# check for valid choice
if len(_next) >= choice > 0:
break
else:
print('Please enter a valid number. Try again.')

self.current = self.current.advance(choice - 1)

def start(self):
self.name = start()
print(f'Welcome, {self.name}')

while self.player.hp > 0:
Expand All @@ -81,19 +83,21 @@ def generate(filename):
node_mapping: dict[str, Node] = {}
n_types = {
"starting": Location,
"node": Node,
"node": Action,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A node should be of type Node, if you want to add an option for action, you could add it as a separate key: value pair in the map

"location": Location,
"fight": Fight,
"run": Run
}

c_funcs: dict[str, Callable[[Game, Node, Node], None]] = {
"->": lambda game, node_a, node_b: game.add_connection(node_a, node_b),
"\->": lambda game, node_a, node_b: game.add_connection(node_a, node_b, BreakingConnection),
"\\->": lambda game, node_a, node_b: game.add_connection(node_a, node_b, BreakingConnection),
"<->": lambda game, node_a, node_b: game.add_twoway_connection(node_a, node_b),
"<-\->": lambda game, node_a, node_b: game.add_twoway_connection(node_a, node_b, BreakingConnection),
"<-/->": lambda game, node_a, node_b: game.add_twoway_connection(node_a, node_b, Connection, BreakingConnection),
"<-/\->": lambda game, node_a, node_b: game.add_twoway_connection(node_a, node_b, BreakingConnection, BreakingConnection),
"<-\\->": lambda game, node_a, node_b: game.add_twoway_connection(node_a, node_b, BreakingConnection),
"<-/->": lambda game, node_a, node_b: game.add_twoway_connection(node_a, node_b, Connection,
BreakingConnection),
"<-/\\->": lambda game, node_a, node_b: game.add_twoway_connection(node_a, node_b, BreakingConnection,
BreakingConnection),
}

for node in nodes.split("\n"):
Expand All @@ -102,7 +106,11 @@ def generate(filename):
if n_type == "fight" or n_type == "run":
args.append(game.player)

if n_type == "node":
args.append(game.player)

Comment on lines +109 to +111
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nodes should not affect the player. Actions, however, are built explicitly to do just that!

obj = n_types[n_type](*args)
# print(obj)
if n_type == "starting":
game.current = obj

Expand All @@ -124,4 +132,4 @@ def generate(filename):
else:
raise ConnectionError("Invalid .dl connection input")

return game
return game
13 changes: 7 additions & 6 deletions game-1.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,26 @@
player = Player()
starting_location = Location(
"castle",
"You find yourself in the prison cell of an abandoned castle"
"You find yourself in the prison cell of an abandoned castle",
0
)

game = Game(player, starting_location)

# nodes
examine_skeleton = Node("examine skeleton", "You examine the skeleton of a corpse.")
examine_skeleton = Node("examine skeleton", "You examine the skeleton of a corpse.", 10)
game.add_node(examine_skeleton)

open_cell_gate = Node("open cell gate", "The cell gate is unlocked. You push it open.")
open_cell_gate = Node("open cell gate", "The cell gate is unlocked. You push it open.", 1)
game.add_node(open_cell_gate)

dungeon = Location("left corridor", "The corridor leads to a large flight of stairs to the dungeon")
dungeon = Location("left corridor", "The corridor leads to a large flight of stairs to the dungeon", 5)
game.add_node(dungeon)

courtyard = Location("right corridor", "The corridor leads to an open door to the castle's courtyard")
courtyard = Location("right corridor", "The corridor leads to an open door to the castle's courtyard", 1)
game.add_node(courtyard)

dragon_event = Node("scale stairs", "A dragon swoops down from the sky, blocking your path")
dragon_event = Node("scale stairs", "A dragon swoops down from the sky, blocking your path", 10)
game.add_node(dragon_event)

fight_dragon = Fight("fight dragon", "You vanquish the dragon", player)
Expand Down
23 changes: 12 additions & 11 deletions game-2-layout.dl
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
1 | starting | castle | You wake up in the prison cell of an abandoned castle.
2 | node | examine skeleton | You examine the skeleton of a corpse.
3 | node | open cell gate | The cell gate is unlocked. You push it open.
4 | node | left corridor | The corridor leads to an open door to the castle's courtyard.
9 | location | courtyard | You enter the castle's courtyard.
5 | node | right corridor | The corridor leads to a large flight of stairs to the dungeon.
10 | location | dungeon | You enter the castle's dungeon.
6 | node | scale stairs | A dragon swoops down from the sky, blocking your path.
7 | fight | fight dragon | You vanquish the dragon.
8 | run | run from dragon | You run from the dragon.
1 | starting | castle | You wake up in the prison cell of an abandoned castle. | 0
2 | node | examine skeleton | You examine the skeleton of a corpse. | 10
3 | node | open cell gate | The cell gate is unlocked. You push it open. | 10
4 | node | left corridor | The corridor leads to an open door to the castle's courtyard. | 10
9 | location | courtyard | You enter the castle's courtyard. | 10
5 | node | right corridor | The corridor leads to a large flight of stairs to the dungeon. | 10
10 | location | dungeon | You enter the castle's dungeon. | 10
6 | node | scale stairs | A dragon swoops down from the sky, blocking your path. | 10
7 | fight | fight dragon | You vanquish the dragon. | 50
8 | run | run from dragon | You run from the dragon. | 10
11 | node | winner | You have won the game! | 10
---
1 <-> 2
1 -> 3
Expand All @@ -18,5 +19,5 @@
9 -> 6
6 -> 7
6 -> 8
7 -> 4
7 -> 11
8 -> 4
7 changes: 5 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import random
from pyfiglet import Figlet
fonts = ["6x9", "banner", "big", "block", "bubble", "chartr", "chartri", "cour", "digital", "helv", "ivrit", "lean", "mini", "mnemonic", "sbook", "script", "shadow", "slant", "small", "smscript", "smshadow", "smslant", "standard", "term", "times", "xchartr"]

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these changes belong in another PR

fonts = ["6x9", "banner", "big", "block", "bubble", "chartr", "chartri", "cour", "digital", "helv", "ivrit", "lean",
"mini", "mnemonic", "sbook", "script", "shadow", "slant", "small", "smscript", "smshadow", "smslant",
"standard", "term", "times", "xchartr"]


def start():
font_idx = random.randint(0, len(fonts) - 1)
Expand All @@ -15,4 +19,3 @@ def start():
ready = input("> ")
if ready.lower() == "y" or ready.lower() == "yes":
return name