Curseyou is a Python Rogue style game that's intended to be small and simple. You can take this and turn it into your own game, but keep in mind it's built in stages based on the content of Learn Python the Hard Way 6th Edition.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
curseyou-python-rogue/phase_six.py

210 lines
5.7 KiB

import curses
import sys
import random
WALL = 1
SPACE = 0
class Map:
def __init__(self, width, height):
self.width = width
self.height = height
grid = self.make_grid()
dead_ends = self.hunt_and_kill(grid)
grid = self.sample_rooms(grid, dead_ends, 4, int(len(dead_ends) * 0.6))
self.hunt_and_kill(grid)
self.render_map(grid)
def sample_rooms(self, grid, dead_ends, size, count):
grid = self.make_grid()
for x, y in random.sample(dead_ends, count):
if x < self.width - size and y < self.height - size:
self.make_room(grid, x, y, size)
return grid
def make_grid(self):
grid = []
for y in range(0, self.height):
grid.append([WALL] * self.width)
return grid
def make_room(self, grid, x, y, size):
for row in range(y, y+size):
for col in range(x, x+size):
grid[row][col] = SPACE
def find_coord(self, grid):
for y in range(1, self.height, 2):
for x in range(1, self.width, 2):
if grid[y][x] != WALL: continue
found = self.neighborsAB(grid, x, y)
for found_x, found_y in found:
if grid[found_y][found_x] == SPACE:
return [[x,y],[found_x, found_y]]
return None
def inbounds(self, x, y):
return x >= 0 and x < self.width and y >= 0 and y < self.height
def neighborsAB(self, grid, x, y):
points = [[x, y - 2],
[x, y + 2],
[x - 2, y],
[x + 2, y]]
result = []
for x,y in points:
if self.inbounds(x, y):
result.append([x,y])
return result
def neighbors(self, grid, x, y):
points = [[x, y - 2],
[x, y + 2],
[x - 2, y],
[x + 2, y]]
result = []
for x,y in points:
if self.inbounds(x, y) and grid[y][x] == WALL:
result.append([x,y])
return result
def hunt_and_kill(self, grid):
on_x = 1
on_y = 1
dead_ends = []
while True:
n = self.neighbors(grid, on_x, on_y)
if len(n) == 0:
dead_ends.append([on_x, on_y])
t = self.find_coord(grid)
if t == None: break
on_x, on_y = t[0]
found_x, found_y = t[1]
grid[on_y][on_x] = SPACE
row = (on_y + found_y) // 2
col = (on_x + found_x) // 2
grid[row][col] = SPACE
else:
nb_x, nb_y = random.choice(n)
grid[nb_y][nb_x] = SPACE
row = (nb_y + on_y) // 2
col = (nb_x + on_x) // 2
grid[row][col] = SPACE
on_x, on_y = nb_x, nb_y
return dead_ends
def render_map(self, grid):
self.map = []
for y, y_line in enumerate(grid):
cur_row = ""
for x, char in enumerate(y_line):
if char == 0:
cur_row += '.'
else:
cur_row += '#'
self.map.append(cur_row)
def move_player(self, player, target_y, target_x):
if self.map[target_y - 1][target_x - 1] != '#':
player.y = target_y
player.x = target_x
def draw(self, win):
map_line = 1
for line in self.map:
win.addstr(map_line, 1, line)
map_line += 1
class UI:
def __init__(self, stdscr, height, width, status_height):
curses.curs_set(0)
stdscr.clear()
begin_x = 0
begin_y = 0
win = curses.newwin(height, width, begin_y, begin_x)
win.keypad(True)
status = win.subwin(status_height, width-2, height-status_height, begin_x+1)
# keep these for later by assigning to self
self.begin_x = 0
self.begin_y = 0
self.map = None
self.height = height
self.width = width
self.win = win
self.status = status
self.status_height = status_height
def set_map(self, the_map):
self.map = the_map
def update(self, player):
assert self.map, "You forgot to call set_map()"
self.win.clear()
self.win.box()
self.status.hline(0,0, curses.ACS_HLINE, self.width - 2)
self.map.draw(self.win)
self.draw_status()
self.draw_player(player)
self.win.refresh()
def draw_status(self):
self.status.addstr(1, 1, "PLAYER STATS")
def draw_player(self, player):
self.win.addstr(player.y, player.x, '@', curses.A_BOLD)
def handle_input(self, y, x):
ch = self.win.getch()
if ch == ord('q'):
sys.exit(0)
elif ch == curses.KEY_UP:
y = (y - 1) % self.height
elif ch == curses.KEY_DOWN:
y = (y + 1) % self.height
elif ch == curses.KEY_RIGHT:
x = (x + 1) % self.width
elif ch == curses.KEY_LEFT:
x = (x - 1) % self.width
return y, x
class Player:
def __init__(self, x, y):
self.x = x
self.y = y
class GameEngine:
def __init__(self, ui):
self.ui = ui
self.player = Player(4, 4)
self.map = Map(77,19)
self.ui = ui
ui.set_map(self.map)
def run(self):
while True:
self.ui.update(self.player)
new_y, new_x = self.ui.handle_input(self.player.y, self.player.x)
self.map.move_player(self.player, new_y, new_x)
def main(stdscr):
width=80
height=26
ui = UI(stdscr, height, width, 5)
game = GameEngine(ui)
game.run()
curses.wrapper(main)