Last active
August 4, 2023 09:26
-
-
Save horstjens/cc33a268c56c940983b73c6ca2cc0807 to your computer and use it in GitHub Desktop.
toni_artur
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# roguelike | |
import os | |
import random | |
def dice(dicestring): | |
""" | |
1d6 -> random integer between 1 and 6 | |
2d6 -> random integer between 2 and 12 | |
1d20+5 -> random integer between 6 and 26 | |
1D6 -> random integer between | |
""" | |
if dicestring.count("d") != 1: | |
raise ValueError("dicestring does not have one 'd'") | |
left, right = dicestring.split("d") | |
number_of_dice = int(left) | |
if ("+" in right) or ("-" in right): | |
sign = "+" if "+" in right else "-" | |
sides, delta = right.split(sign) | |
sides = int(sides) | |
delta = int(delta) | |
if sign == "-": | |
delta = -delta | |
else: | |
delta = 0 | |
sides = int(right) | |
text = dicestring+": " | |
result = 0 | |
for d in range(number_of_dice): | |
roll = random.randint(1, sides) | |
result += roll | |
if d > 0: | |
text+=f"+{roll}" | |
else: | |
text+= f"{roll}" | |
result += delta | |
if delta != 0: | |
if delta > 0: | |
text += f"+{delta}={result}" | |
else: | |
text += f"{delta}={result}" | |
return result, text | |
# das legend dictionary {key:value, key2:value2, ...} | |
legend = {"#":"wall", | |
".":"floor", | |
"d":"door", | |
"k":"key", | |
"$":"gold", | |
} | |
d1 = """ | |
################################ | |
#.....$...>....................# | |
######......k..................# | |
#$.$.d.........................# | |
################################ | |
""" | |
d2 = """ | |
################################ | |
#.........<...............#....# | |
#....$................#...#....# | |
#..........$......$...#........# | |
################################ | |
""" | |
dungeon = [] | |
for d in (d1, d2): | |
lines = [list(line) for line in d.splitlines() if len(line.strip())>0] | |
dungeon.append(lines) | |
hero = "@" | |
hx,hy,hz = 1,1,0 | |
keys = 0 | |
gold = 0 | |
messages = [] | |
turn = 0 | |
while True: | |
turn += 1 | |
os.system("clear") | |
for y, line in enumerate(dungeon[hz]): | |
for x, char in enumerate(line): | |
if (hx==x) and (hy==y): | |
print(hero, end="") | |
else: | |
print(char, end="") | |
print() | |
# messages printen | |
for m in messages: | |
print(m) | |
messages = [] | |
# user input | |
command = input(f"turn: {turn} dungeon: {hz+1} keys: {keys} gold: {gold}\nYour command: >>>") | |
if command.lower() in ("help","?"): | |
for key, value in legend.items(): | |
print(key, "..........", value) | |
input("press Enter to continue") | |
if command.lower() in ("q", "quit", "exit"): | |
break | |
if command.lower() == "down": | |
if dungeon[hz][hy][hx] == ">": | |
messages.append("You climb the stairs down") | |
hz += 1 | |
continue | |
if command.lower() == "up": | |
if dungeon[hz][hy][hx] == "<": | |
messages.append("You climb the stairs up") | |
hz -= 1 | |
continue | |
dx, dy = 0, 0 | |
if command.lower() == "w": | |
dy = -1 | |
if command.lower() == "a": | |
dx = -1 | |
if command.lower() == "s": | |
dy = 1 | |
if command.lower() == "d": | |
dx = 1 | |
# crash into wall ? | |
target = dungeon[hz][hy+dy][hx+dx] | |
if target in "#": | |
dx, dy = 0, 0 | |
messages.append("You ran into a wall. Ouch!") | |
# door ? | |
if target == "d": | |
if keys == 0: | |
messages.append("You ran into a closed door. Ouch!") | |
else: | |
keys -= 1 | |
messages.append("You heroically opened a door with a key. Cunning!") | |
dungeon[hz][hy+dy][hx+dx] = "." | |
dx, dy = 0, 0 | |
# movement | |
hx += dx | |
hy += dy | |
new_tile = dungeon[hz][hy][hx] | |
# items? | |
# gold? | |
if new_tile == "$": | |
dicestring = f"{hz+1}d20+{hz*2}" | |
amount, text = dice(dicestring) | |
gold += amount | |
messages.append(f"You found gold. Calculation: {text}") | |
dungeon[hz][hy][hx] = "." | |
# key? | |
if new_tile == "k": | |
messages.append("You found a key! Lucky!") | |
keys += 1 | |
dungeon[hz][hy][hx] = "." | |
# stairs ? | |
if new_tile == "<": | |
messages.append("You can go up the stairs by typing 'up'") | |
if new_tile == ">": | |
messages.append("You can go down the stairs by typing 'down'") | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# roguelike | |
import os | |
import random | |
from dice2 import diceroll | |
class Game: | |
zoo = {} | |
hero = None | |
class Monster: | |
number = 0 | |
def __init__(self, x,y,z, name=""): | |
self.number = Monster.number | |
Monster.number += 1 | |
Game.zoo[self.number] = self | |
self.name = name | |
self.friendly = False | |
self.can_strike = True | |
self.can_counterstrike = True | |
self.x = x | |
self.y = y | |
self.z = z | |
self.hp = 10 | |
self.attack = 10 # +2D6 | |
self.defense = 8 # +2D6 | |
self.armor = 5 | |
self.damage = 10 # +2D6 | |
self.speed = 10 # +2D6 | |
def __repr__(self): | |
text = f"{self.__class__.__name__} instance: " | |
for key, value in self.__dict__.items(): | |
text += f"{key}: {value}" | |
text += ", " | |
return text[:-2] # remove the last 2 chars | |
class Hero(Monster): | |
def __init__(self, x,y,z, name): | |
super().__init__(x,y,z,name) | |
self.friendly = True | |
self.char = "@" | |
self.keys = 0 | |
self.gold = 0 | |
self.hp = 20 | |
self.attack = 10 # +2D6 | |
self.defense = 10 # +2D6 | |
self.armor = 8 | |
self.damage = 10 # +2D6 | |
self.speed = 10 # +2D6 | |
self.xp = 0 # experience points | |
self.mp = 0 # mana points | |
self.satuation = 10 | |
class Warden(Monster): | |
def __init__(self, x,y,z): | |
super().__init__(x,y,z, name="Warden") | |
self.attack = 10 | |
self.defense = 3 | |
self.armor = 10 | |
self.damage = 15 | |
self.speed = 1 | |
self.friendly = True | |
self.char = "W" | |
self.hp = 30 | |
def attack(attacker, defender): | |
text = [] | |
# attack vs. defense | |
roll_a, text_a = diceroll(f"2D6+{attacker.attack}") # 2D6 + 10 | |
roll_b, text_b = diceroll(f"2D6+{defender.defense}") # 2D6 + 8 | |
if roll_b >= roll_a: | |
text.append(f"{attacker.name} misses {defender.name} (attack {text_a} <= defense {text_b})") | |
return text | |
text.append(f"{attacker.name} strikes {defender.name} (attack {text_a} > defense {text_b})" ) | |
# damage vs. armor | |
roll_c, text_c = diceroll(f"2D6+{attacker.damage}") | |
roll_d, text_d = diceroll(f"2D6+{defender.armor}") | |
if roll_d >= roll_c: | |
text.append(f"but can not penetrate {defender.name}'s armor (damage {text_c} <= armor {text_d})") | |
return text | |
text.append(f"and inflicts {roll_c-roll_d} damage! (damage {text_c} > armor {text_d})") | |
damage = roll_c - roll_d | |
defender.hp -= damage | |
if defender.hp <= 0: | |
text.append(f"{defender.name} dies! {attacker.name} wins the fight!") | |
else: | |
text.append(f"{defender.name} has {defender.hp} hp left") | |
return text | |
def fight(attacker, defender): | |
text = ["===---- strike! ----===="] | |
text.append(f"{attacker.name} ({attacker.hp} hp) strikes first vs. {defender.name} ({defender.hp} hp)") | |
text.extend(attack(attacker, defender)) | |
if defender.hp > 0: | |
text.append("====---- counterstrike! ----====") | |
text.extend(attack(defender, attacker)) | |
text.append(f"result: {attacker.name}: {attacker.hp} hp, {defender.name}: {defender.hp} hp") | |
return text | |
def clear(): | |
if os.name == 'nt': | |
os.system('cls') | |
else: | |
os.system("clear") | |
# das legend dictionary {key:value, key2:value2, ...} | |
legend = {"#":"wall", | |
".":"floor", | |
"o":"exit", | |
"d":"door", | |
"k":"key", | |
"$":"gold", | |
"@":"hero", | |
"W":"warden", | |
} | |
d1 = """ | |
################################ | |
#@....$...>..................o.# | |
######......k..................# | |
#$.$.d.........................# | |
################################ | |
""" | |
d2 = """ | |
################################ | |
#kWd......<...............#....# | |
####...$..............#...#....# | |
#..........$......$...#........# | |
################################ | |
""" | |
dungeon = [] | |
for d in (d1, d2): | |
lines = [list(line) for line in d.splitlines() if len(line.strip())>0] | |
dungeon.append(lines) | |
# create Monster instances in the dungeon | |
for z, lines in enumerate(dungeon): | |
for y, line in enumerate(lines): | |
for x, char in enumerate(line): | |
if char == "W": | |
Warden(x,y,z) | |
dungeon[z][y][x] = "." | |
# hero? | |
if char == "@": | |
Game.hero = Hero(x,y,z,"heroic You") | |
#print("created hero", x,y,z) | |
#input(">>>") | |
dungeon[z][y][x] = "." | |
messages = [] | |
turn = 0 | |
while True: | |
turn += 1 | |
#os.system("clear") | |
clear() | |
#print(Game.zoo.values()) | |
for y, line in enumerate(dungeon[Game.hero.z]): | |
for x, char in enumerate(line): | |
for monster in Game.zoo.values(): | |
if (monster.z == Game.hero.z) and (monster.y==y) and (monster.x==x): | |
if monster.hp > 0: | |
print(monster.char, end="") | |
break | |
else: | |
print(char, end="") | |
print() | |
# messages printen | |
for m in messages: | |
print(m) | |
messages = [] | |
# game over? | |
if Game.hero.hp <= 0: | |
break | |
# user input | |
status = f"turn: {turn} lvl: {Game.hero.z+1} keys: {Game.hero.keys}" | |
status += f" $: {Game.hero.gold} hp: {Game.hero.hp} mp: {Game.hero.mp}" | |
status += f" xp: {Game.hero.xp}" | |
print(status) | |
command = input("Your command: >>>") | |
if command.lower() == "heal": | |
Game.hero.hp += 5 | |
if command.lower() in ("help","?"): | |
for key, value in legend.items(): | |
print(key, "..........", value) | |
input("press Enter to continue") | |
if command.lower() == "quit": | |
break | |
if (command.lower() == "exit") and (dungeon[Game.hero.z][Game.hero.y][Game.hero.x] == "o"): | |
answer = input("Really leave the dungeon? type 'YES' >>>") | |
if answer == "YES": | |
break | |
if command.lower() == "down": | |
if dungeon[Game.hero.z][Game.hero.y][Game.hero.x] == ">": | |
messages.append("You climb the stairs down") | |
Game.hero.z += 1 | |
continue | |
if command.lower() == "up": | |
if dungeon[Game.hero.z][Game.hero.y][Game.hero.x] == "<": | |
messages.append("You climb the stairs up") | |
Game.hero.z -= 1 | |
continue | |
dx, dy = 0, 0 | |
if command.lower() == "w": | |
dy = -1 | |
if command.lower() == "a": | |
dx = -1 | |
if command.lower() == "s": | |
dy = 1 | |
if command.lower() == "d": | |
dx = 1 | |
# run into enemy? | |
for monster in Game.zoo.values(): | |
if ((monster.number != Game.hero.number) and | |
(monster.z == Game.hero.z) and | |
(monster.y == Game.hero.y + dy) and | |
(monster.x == Game.hero.x + dx) and | |
(monster.hp > 0)): | |
monster.friendly = False | |
messages.extend(fight(Game.hero, monster)) | |
print(Game.hero) | |
dx,dy = 0, 0 | |
# crash into wall ? | |
target = dungeon[Game.hero.z][Game.hero.y+dy][Game.hero.x+dx] | |
if target in "#": | |
dx, dy = 0, 0 | |
messages.append("You ran into a wall. Ouch!") | |
# door ? | |
if target == "d": | |
if Game.hero.keys == 0: | |
messages.append("You ran into a closed door. Ouch!") | |
else: | |
Game.hero.keys -= 1 | |
messages.append("You heroically opened a door with a key. Cunning!") | |
dungeon[Game.hero.z][Game.hero.y+dy][Game.hero.x+dx] = "." | |
dx, dy = 0, 0 | |
# movement | |
Game.hero.x += dx | |
Game.hero.y += dy | |
new_tile = dungeon[Game.hero.z][Game.hero.y][Game.hero.x] | |
# items? | |
# gold? | |
if new_tile == "$": | |
dicestring = f"{Game.hero.z+1}D20+{Game.hero.z*2}" | |
amount, text = diceroll(dicestring) | |
Game.hero.gold += amount | |
messages.append(f"You found gold. Calculation: {text}") | |
dungeon[Game.hero.z][Game.hero.y][Game.hero.x] = "." | |
# key? | |
if new_tile == "k": | |
messages.append("You found a key! Lucky!") | |
Game.hero.keys += 1 | |
dungeon[Game.hero.z][Game.hero.y][Game.hero.x] = "." | |
# exit ? | |
if new_tile == "o": | |
messages.append("Type 'exit' to leave the dungeon (and end the game)") | |
# stairs ? | |
if new_tile == "<": | |
messages.append("You can go up the stairs by typing 'up'") | |
if new_tile == ">": | |
messages.append("You can go down the stairs by typing 'down'") | |
print("Game Over") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# roguelike | |
import os | |
import random | |
from dice2 import diceroll | |
class Game: | |
zoo = {} | |
hero = None | |
dungeon = [] | |
turn = 0 | |
messages = [] | |
class Monster: | |
number = 0 | |
def __init__(self, x,y,z, name=""): | |
self.number = Monster.number | |
Monster.number += 1 | |
Game.zoo[self.number] = self | |
self.name = name | |
self.ally = False | |
self.peaceful = False | |
self.can_strike = True | |
self.can_counterstrike = True | |
self.can_move = True | |
self.x = x | |
self.y = y | |
self.z = z | |
self.hp = 10 | |
self.attack = 10 # +2D6 | |
self.defense = 8 # +2D6 | |
self.armor = 5 | |
self.damage = 10 # +2D6 | |
self.speed = 10 # +2D6 | |
self.sight_range = 5 | |
self.state = "roam" # roam - hunt - flee | |
def __repr__(self): | |
text = f"{self.__class__.__name__} instance: " | |
for key, value in self.__dict__.items(): | |
text += f"{key}: {value}" | |
text += ", " | |
return text[:-2] # remove the last 2 chars | |
def distance_to(self,monster): | |
"""returns None if both monsters | |
are on different dungeon levels. | |
Otherwise, returns distance in dungeon tiles | |
""" | |
if monster.z != self.z: | |
return None | |
delta_x = self.x - monster.x | |
delta_y = self.y - monster.y | |
return int((delta_x**2+delta_y**2)**0.5) | |
def vector_to(self, monster): | |
"""return None if both monsters | |
are on different dungeon levels. | |
Otherwise, returns, dx, dy from self to monster | |
(in dungeon tiles)""" | |
if monster.z != self.z: | |
return None | |
dx = monster.x - self.x | |
dy = monster.y - self.y | |
return dx, dy | |
def foes_nearby(self, distance=1): | |
"""returns a list of foes in radius distance""" | |
result = [] | |
for m in Game.zoo.values(): | |
if m.hp <= 0: | |
continue | |
if m.z != self.z: | |
continue | |
if m.ally == self.ally: | |
continue | |
if m.peaceful: | |
continue | |
if m.number == self.number: | |
continue | |
if self.distance_to(m) <= distance: | |
result.append(m) | |
return result | |
def ai(self): | |
"""returns dx, dy if no enemies are nearby""" | |
#possible directions | |
if not self.can_move: | |
return 0,0 | |
vectors = [] | |
x,y = int(self.x), int(self.y) | |
for dy in (-1,0,1): | |
for dx in (-1,0,1): | |
if any([x+dx < 0, y+dy < 0, | |
x+dx >= len(Game.dungeon[self.z][0]), | |
y+dy >= len(Game.dungeon[self.z])]): | |
continue | |
monsters = [m for m in Game.zoo.values() if all([ | |
m.hp>0, | |
m.number != self.number, | |
m.z == self.z, | |
m.x == x+dx, | |
m.y == y+dy])] | |
if len(monsters) > 0: | |
continue | |
if Game.dungeon[self.z][y+dy][x+dx] in "#d": | |
continue | |
vectors.append((dx,dy)) | |
if len(vectors) <= 1: | |
return 0,0 | |
# choose one of several possible vectors.. | |
if self.peaceful: | |
return random.choice(vectors) | |
# any enemy inside sight radius? choose closest enemy | |
enemies = [m for m in Game.zoo.values() if all([ | |
m.hp > 0, | |
m.number != self.number, | |
m.z == self.z, | |
m.ally != self.ally, | |
])] | |
if len(enemies) == 0: | |
self.state = "roam" | |
return random.choice(vectors) | |
# choose closest enemy to hunt/flee | |
min_distance, opponent = None, None | |
for e in enemies: | |
d = self.distance_to(e) | |
if (min_distance is None) or d < min_distance: | |
min_distance = d | |
opponent = e | |
if (min_distance is None) or (min_distance > self.sight_range): | |
self.state = "roam" | |
return random.choice(vectors) | |
self.state = "hunt" | |
ex,ey = self.vector_to(opponent) | |
normv = (ex/abs(ex) if ex != 0 else 0, ey/abs(ey) if ey != 0 else 0) | |
# 90% chance to hunt, 10% chance do something else | |
if random.random() < 0.9: | |
if normv in vectors: | |
return normv | |
return random.choice(vectors) | |
class Cat(Monster): | |
def __init__(self,x,y,z,name="Kitty"): | |
super().__init__(x,y,z,name) | |
self.ally = True | |
self.char = "°" | |
self.hp = 7 | |
self.attack= 9 | |
self.defense=9 | |
self.damage = -2 | |
self.armor = 0 | |
self.speed = 11 | |
class Hero(Monster): | |
def __init__(self, x,y,z, name): | |
super().__init__(x,y,z,name) | |
#self.friendly = True | |
self.ally = True | |
self.char = "@" | |
self.keys = 0 | |
self.gold = 0 | |
self.hp = 20 | |
self.attack = 10 # +2D6 | |
self.defense = 10 # +2D6 | |
self.armor = 8 | |
self.damage = 10 # +2D6 | |
self.speed = 10 # +2D6 | |
self.xp = 0 # experience points | |
self.mp = 0 # mana points | |
self.satuation = 10 | |
class Rat(Monster): | |
def __init__(self,x,y,z,name="Rat"): | |
super().__init__(x,y,z,name) | |
self.attack = 7 | |
self.defense = 10 | |
self.armor = 0 | |
self.speed = 8 | |
self.char = "R" | |
self.hp = 5 | |
self.damage = -5 | |
class Warden(Monster): | |
def __init__(self, x,y,z): | |
super().__init__(x,y,z, name="Warden") | |
self.can_move = False | |
self.attack = 10 | |
self.defense = 3 | |
self.armor = 10 | |
self.damage = 15 | |
self.speed = 1 | |
self.peaceful = True | |
self.char = "W" | |
self.hp = 30 | |
self.sight_range = 1 | |
def attack(attacker, defender): | |
text = [] | |
# attack vs. defense | |
roll_a, text_a = diceroll(f"2D6+{attacker.attack}") # 2D6 + 10 | |
roll_b, text_b = diceroll(f"2D6+{defender.defense}") # 2D6 + 8 | |
if roll_b >= roll_a: | |
text.append(f"{attacker.name} misses {defender.name} (attack {text_a} <= defense {text_b})") | |
return text | |
text.append(f"{attacker.name} strikes {defender.name} (attack {text_a} > defense {text_b})" ) | |
# damage vs. armor | |
roll_c, text_c = diceroll(f"2D6+{attacker.damage}") | |
roll_d, text_d = diceroll(f"2D6+{defender.armor}") | |
if roll_d >= roll_c: | |
text.append(f"but can not penetrate {defender.name}'s armor (damage {text_c} <= armor {text_d})") | |
return text | |
damage = max(0,roll_c - roll_d) | |
text.append(f"and inflicts {damage} damage! (damage {text_c} > armor {text_d})") | |
defender.hp -= damage | |
if defender.hp <= 0: | |
text.append(f"{defender.name} dies! {attacker.name} wins the fight!") | |
else: | |
text.append(f"{defender.name} has {defender.hp} hp left") | |
return text | |
def fight(attacker, defender): | |
text = ["===---- strike! ----===="] | |
text.append(f"{attacker.name} ({attacker.hp} hp) strikes first vs. {defender.name} ({defender.hp} hp)") | |
text.extend(attack(attacker, defender)) | |
if defender.hp > 0: | |
text.append("====---- counterstrike! ----====") | |
text.extend(attack(defender, attacker)) | |
text.append(f"result: {attacker.name}: {attacker.hp} hp, {defender.name}: {defender.hp} hp") | |
return text | |
def clear(): | |
if os.name == 'nt': | |
os.system('cls') | |
else: | |
os.system("clear") | |
# das legend dictionary {key:value, key2:value2, ...} | |
legend = {"#":"wall", | |
".":"floor", | |
"o":"exit", | |
"d":"door", | |
"k":"key", | |
"$":"gold", | |
"@":"hero", | |
"W":"warden", | |
"R":"rat", | |
"°":"pet", | |
} | |
d1 = """ | |
################################ | |
#@°...$...>...........R......o.# | |
######............R............# | |
#$.$.d...............R.........# | |
################################ | |
""" | |
d2 = """ | |
################################ | |
#$#kW.....<..........RRR..#....# | |
#d####...$............#...#....# | |
#..........$......$...#........# | |
################################ | |
""" | |
def create_dungeon(*levels): | |
for d in levels: | |
lines = [list(line) for line in d.splitlines() if len(line.strip())>0] | |
Game.dungeon.append(lines) | |
# create Monster instances in the Game.dungeon | |
for z, lines in enumerate(Game.dungeon): | |
for y, line in enumerate(lines): | |
for x, char in enumerate(line): | |
match char: | |
case "R": | |
Rat(x,y,z) | |
Game.dungeon[z][y][x] = "." | |
case "@" : | |
Game.hero = Hero(x,y,z,"heroic You") | |
Game.dungeon[z][y][x] = "." | |
case "W": | |
Warden(x,y,z) | |
Game.dungeon[z][y][x] = "." | |
case "°": | |
Cat(x,y,z) | |
Game.dungeon[z][y][x] = "." | |
def paint_dungeon(): | |
clear() | |
#print(Game.zoo.values()) | |
for y, line in enumerate(Game.dungeon[Game.hero.z]): | |
for x, char in enumerate(line): | |
for monster in Game.zoo.values(): | |
if (monster.z == Game.hero.z) and (monster.y==y) and (monster.x==x): | |
if monster.hp > 0: | |
print(monster.char, end="") | |
break | |
else: | |
print(char, end="") | |
print() | |
def player_status(): | |
status = f"turn: {Game.turn} lvl: {Game.hero.z+1} keys: {Game.hero.keys}" | |
status += f" $: {Game.hero.gold} hp: {Game.hero.hp} mp: {Game.hero.mp}" | |
status += f" xp: {Game.hero.xp}" | |
return status | |
def main(): | |
Game.messages = [] | |
message_index = 0 | |
Game.turn = 0 | |
while True: | |
Game.turn += 1 | |
paint_dungeon() | |
# messages printen | |
for m in Game.messages[message_index: len(Game.messages)]: | |
print(m) | |
#messages = [] | |
message_index = len(Game.messages) | |
# game over? | |
if Game.hero.hp <= 0: | |
break | |
# status | |
print(player_status()) | |
# user input | |
command = input("Your command: >>>") | |
if command.lower() == "heal": | |
Game.hero.hp += 5 | |
if command.lower() in ("help","?"): | |
for key, value in legend.items(): | |
print(key, "..........", value) | |
input("press Enter to continue") | |
if command.lower() == "quit": | |
break | |
if (command.lower() == "exit") and (Game.dungeon[Game.hero.z][Game.hero.y][Game.hero.x] == "o"): | |
answer = input("Really leave the dungeon? type 'YES' >>>") | |
if answer == "YES": | |
break | |
if command.lower() == "down": | |
if Game.dungeon[Game.hero.z][Game.hero.y][Game.hero.x] == ">": | |
Game.messages.append("You climb the stairs down") | |
Game.hero.z += 1 | |
continue | |
if command.lower() == "up": | |
if Game.dungeon[Game.hero.z][Game.hero.y][Game.hero.x] == "<": | |
Game.messages.append("You climb the stairs up") | |
Game.hero.z -= 1 | |
continue | |
dx, dy = 0, 0 | |
if command.lower() == "w": | |
dy = -1 | |
if command.lower() == "a": | |
dx = -1 | |
if command.lower() == "s": | |
dy = 1 | |
if command.lower() == "d": | |
dx = 1 | |
# run into / attack Monster? | |
for monster in Game.zoo.values(): | |
if all((monster.hp > 0, | |
monster.number != Game.hero.number, | |
monster.z == Game.hero.z, | |
monster.y == Game.hero.y + dy, | |
monster.x == Game.hero.x + dx, | |
)): | |
if monster.ally: | |
nx,ny = monster.x, monster.y | |
monster.x, monster.y = Game.hero.x, Game.hero.y | |
Game.hero.x, Game.hero.y = nx, ny | |
Game.messages.append("Your swap places with your ally") | |
else: | |
if monster.peaceful: | |
Game.messages.append("You attack a peaceful creature. Not nice!") | |
monster.peaceful = False | |
Game.messages.extend(fight(Game.hero, monster)) | |
dx,dy = 0, 0 | |
break # player can only attack one monster per turn | |
# crash into wall ? | |
target = Game.dungeon[Game.hero.z][Game.hero.y+dy][Game.hero.x+dx] | |
if target in "#": | |
dx, dy = 0, 0 | |
Game.messages.append("You ran into a wall. Ouch!") | |
# door ? | |
if target == "d": | |
if Game.hero.keys == 0: | |
Game.messages.append("You ran into a closed door. Ouch!") | |
else: | |
Game.hero.keys -= 1 | |
Game.messages.append("You heroically opened a door with a key. Cunning!") | |
Game.dungeon[Game.hero.z][Game.hero.y+dy][Game.hero.x+dx] = "." | |
dx, dy = 0, 0 | |
# Player movement | |
Game.hero.x += dx | |
Game.hero.y += dy | |
# other monster movement | |
# ally movement / attack | |
allies = [m for m in Game.zoo.values() if all([ | |
m.hp > 0, | |
m.number != Game.hero.number, | |
m.ally, | |
m.z == Game.hero.z])] | |
for a in allies: | |
enemies = a.foes_nearby() | |
if len(enemies) > 0: | |
opponent = random.choice(enemies) | |
Game.messages.append(f"Your ally {a.name} attacks a foe!") | |
Game.messages.extend(fight(a, opponent)) | |
else: | |
dx,dy = a.ai() | |
a.x += dx | |
a.y += dy | |
# enemy move / attack | |
monsters = [m for m in Game.zoo.values() if all([ | |
m.hp > 0, | |
not m.ally, | |
m.number != Game.hero.number, | |
m.z == Game.hero.z])] | |
for m in monsters: | |
foes = m.foes_nearby() | |
if (len(foes) > 0) and not m.peaceful : | |
opponent = random.choice(foes) | |
if opponent.number == Game.hero.number: | |
text = "You" | |
else: | |
text = "Your ally" | |
Game.messages.append(f"An hostile monster strikes against {text}") | |
Game.messages.extend(fight(m, opponent)) | |
else: | |
dx, dy = m.ai() | |
m.x += dx | |
m.y += dy | |
# movement is done | |
new_tile = Game.dungeon[Game.hero.z][Game.hero.y][Game.hero.x] | |
# items? | |
# gold? | |
if new_tile == "$": | |
dicestring = f"{Game.hero.z+1}D20+{Game.hero.z*2}" | |
amount, text = diceroll(dicestring) | |
Game.hero.gold += amount | |
Game.messages.append(f"You found gold. Calculation: {text}") | |
Game.dungeon[Game.hero.z][Game.hero.y][Game.hero.x] = "." | |
# key? | |
if new_tile == "k": | |
Game.messages.append("You found a key! Lucky!") | |
Game.hero.keys += 1 | |
Game.dungeon[Game.hero.z][Game.hero.y][Game.hero.x] = "." | |
# exit ? | |
if new_tile == "o": | |
Game.messages.append("Type 'exit' to leave the dungeon (and end the game)") | |
# stairs ? | |
if new_tile == "<": | |
Game.messages.append("You can go up the stairs by typing 'up'") | |
if new_tile == ">": | |
Game.messages.append("You can go down the stairs by typing 'down'") | |
print("Game Over") | |
if __name__ == "__main__": | |
create_dungeon(d1,d2) | |
main() | |
while True: | |
command = input("type OK to end the game") | |
if command == "OK": | |
break | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment