The numpy version is now the only version.

master
Zed A. Shaw 3 days ago
parent 03c1126ef0
commit 44aa27f9d5
  1. 82
      npy_style/phase_01.py
  2. 88
      npy_style/phase_02.py
  3. 93
      npy_style/phase_03.py
  4. 95
      npy_style/phase_04.py
  5. 107
      npy_style/phase_05.py
  6. 208
      npy_style/phase_06.py
  7. 229
      npy_style/phase_07.py
  8. 241
      npy_style/phase_08.py
  9. 271
      npy_style/phase_09.py
  10. 270
      npy_style/phase_10.py
  11. 344
      npy_style/phase_11.py
  12. 353
      npy_style/phase_12.py
  13. 49
      phase_01.py
  14. 42
      phase_02.py
  15. 40
      phase_03.py
  16. 37
      phase_04.py
  17. 37
      phase_05.py
  18. 32
      phase_06.py
  19. 13
      phase_07.py
  20. 19
      phase_08.py
  21. 19
      phase_09.py
  22. 13
      phase_10.py
  23. 12
      phase_11.py
  24. 16
      phase_12.py

@ -1,82 +0,0 @@
import curses
import sys
import numpy as np
MAP = np.array([
list("####################"),
list("###....#############"),
list("###....#############"),
list("###...........######"),
list("#############.######"),
list("#############....###"),
list("#############....###"),
list("####################")], dtype=str)
def draw_map(win):
for y, row in enumerate(MAP):
win.addstr(y, 0, "".join(row))
def draw_status(status):
status.addstr(1, 1, "PLAYER STATS")
def draw_player(win, player_y, player_x):
win.addstr(player_y, player_x, '@', curses.A_BOLD)
def update(win, status, player_y, player_x):
win.clear()
status.box()
draw_map(win)
draw_status(status)
draw_player(win, player_y, player_x)
win.refresh()
def create_ui(stdscr, width, height, status_height):
curses.curs_set(0)
stdscr.clear()
begin_x = 0
begin_y = 0
win = curses.newwin(height, width, begin_y, begin_x)
status = win.subwin(status_height, width, height-status_height, begin_x)
win.keypad(True)
return win, status
def move_player(player_y, player_x, target_y, target_x):
if MAP[target_y][target_x] != '#':
return target_y, target_x
else:
return player_y, player_x
def handle_input(win, y, x, width, height):
ch = win.getch()
if ch == ord('q'):
sys.exit(0)
elif ch == curses.KEY_UP:
y = (y - 1) % height
elif ch == curses.KEY_DOWN:
y = (y + 1) % height
elif ch == curses.KEY_RIGHT:
x = (x + 1) % width
elif ch == curses.KEY_LEFT:
x = (x - 1) % width
return y, x
def main(stdscr):
width=27
height=17
win, status = create_ui(stdscr, width, height, 5)
player_x = 3
player_y = 3
while True:
update(win, status, player_y, player_x)
new_y, new_x = handle_input(
win, player_y, player_x, width, height)
player_y, player_x = move_player(
player_y, player_x, new_y, new_x)
curses.wrapper(main)

@ -1,88 +0,0 @@
import curses
import sys
import numpy as np
MAP = np.array([
list("####################"),
list("###....#############"),
list("###....#############"),
list("###...........######"),
list("#############.######"),
list("#############....###"),
list("#############....###"),
list("####################")], dtype=str)
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, height-status_height, begin_x)
# keep these for later by assigning to self
self.begin_x = 0
self.begin_y = 0
self.height = height
self.width = width
self.win = win
self.status = status
self.status_height = status_height
def update(self, player_y, player_x):
self.win.clear()
self.status.box()
self.draw_map()
self.draw_status()
self.draw_player(player_y, player_x)
self.win.refresh()
def draw_map(self):
for y, row in enumerate(MAP):
self.win.addstr(y, 0, "".join(row))
def draw_status(self):
self.status.addstr(1, 1, "PLAYER STATS")
def draw_player(self, player_y, player_x):
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
def move_player(player_y, player_x, target_y, target_x):
if MAP[target_y][target_x] != '#':
return target_y, target_x
else:
return player_y, player_x
def main(stdscr):
width=27
height=16
ui = UI(stdscr, height, width, 5)
player_x = 3
player_y = 3
while True:
ui.update(player_y, player_x)
new_y, new_x = ui.handle_input(player_y, player_x)
player_y, player_x = move_player(player_y, player_x, new_y, new_x)
curses.wrapper(main)

@ -1,93 +0,0 @@
import curses
import sys
import numpy as np
class Map:
def __init__(self):
self.map = [
list("####################"),
list("###....#############"),
list("###....#############"),
list("###...........######"),
list("#############.######"),
list("#############....###"),
list("#############....###"),
list("####################")]
def move_player(self, player_y, player_x, target_y, target_x):
if self.map[target_y][target_x] != '#':
return target_y, target_x
else:
return player_y, player_x
def draw(self, win):
for y, row in enumerate(self.map):
win.addstr(y, 0, "".join(row))
class UI:
def __init__(self, stdscr, the_map, 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, height-status_height, begin_x)
# keep these for later by assigning to self
self.begin_x = 0
self.begin_y = 0
self.map = the_map
self.height = height
self.width = width
self.win = win
self.status = status
self.status_height = status_height
def update(self, player_y, player_x):
self.win.clear()
self.status.box()
self.map.draw(self.win)
self.draw_status()
self.draw_player(player_y, player_x)
self.win.refresh()
def draw_status(self):
self.status.addstr(1, 1, "PLAYER STATS")
def draw_player(self, player_y, player_x):
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
def main(stdscr):
width=27
height=16
the_map = Map()
ui = UI(stdscr, the_map, height, width, 5)
player_x = 3
player_y = 3
while True:
ui.update(player_y, player_x)
new_y, new_x = ui.handle_input(player_y, player_x)
player_y, player_x = the_map.move_player(player_y, player_x, new_y, new_x)
curses.wrapper(main)

@ -1,95 +0,0 @@
import curses
import sys
import numpy as np
class Map:
def __init__(self):
self.map = [
list("####################"),
list("###....#############"),
list("###....#############"),
list("###...........######"),
list("#############.######"),
list("#############....###"),
list("#############....###"),
list("####################")]
def move_player(self, player, target_y, target_x):
if self.map[target_y][target_x] != '#':
player.y = target_y
player.x = target_x
def draw(self, win):
for y, row in enumerate(self.map):
win.addstr(y, 0, "".join(row))
class UI:
def __init__(self, stdscr, the_map, 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, height-status_height, begin_x)
# keep these for later by assigning to self
self.begin_x = 0
self.begin_y = 0
self.map = the_map
self.height = height
self.width = width
self.win = win
self.status = status
self.status_height = status_height
def update(self, player):
self.win.clear()
self.status.box()
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
def main(stdscr):
width=27
height=16
the_map = Map()
ui = UI(stdscr, the_map, height, width, 5)
player = Player(3, 3)
while True:
ui.update(player)
new_y, new_x = ui.handle_input(player.y, player.x)
the_map.move_player(player, new_y, new_x)
curses.wrapper(main)

@ -1,107 +0,0 @@
import curses
import sys
import numpy as np
class Map:
def __init__(self):
self.map = [
list("####################"),
list("###....#############"),
list("###....#############"),
list("###...........######"),
list("#############.######"),
list("#############....###"),
list("#############....###"),
list("####################")]
def move_player(self, player, target_y, target_x):
if self.map[target_y][target_x] != '#':
player.y = target_y
player.x = target_x
def draw(self, win):
for y, row in enumerate(self.map):
win.addstr(y, 0, "".join(row))
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, height-status_height, begin_x)
# 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.status.box()
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(3, 3)
self.map = Map()
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=27
height=16
ui = UI(stdscr, height, width, 5)
game = GameEngine(ui)
game.run()
curses.wrapper(main)

@ -1,208 +0,0 @@
import curses
import sys
import random
import numpy as np
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_x, target_y):
if self.map[target_y][target_x] != '#':
player.y = target_y
player.x = target_x
def draw(self, win):
for y, row in enumerate(self.map):
win.addstr(y, 0, "".join(row))
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, height-status_height, begin_x)
# 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.status.box()
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, x, y):
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 x, y
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(3, 3)
self.map = Map(self.ui.width, self.ui.height - self.ui.status_height)
self.ui = ui
ui.set_map(self.map)
def run(self):
while True:
self.ui.update(self.player)
new_x, new_y = self.ui.handle_input(self.player.x, self.player.y)
self.map.move_player(self.player, new_x, new_y)
def main(stdscr):
width=27
height=16
ui = UI(stdscr, height, width, 5)
game = GameEngine(ui)
game.run()
curses.wrapper(main)

@ -1,229 +0,0 @@
import curses
import sys
import random
import numpy as np
WALL = '#'
SPACE = '.'
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 spawn(self):
while True:
y = random.randrange(0, self.height)
x = random.randrange(0, self.width)
if self.map[y][x] == SPACE:
return x, y
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):
return np.full((self.height, self.width), WALL, dtype=str)
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.neighbors(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 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):
result.append([x,y])
return result
def neighbor_walls(self, grid, x, y):
neighbors = self.neighbors(grid, x, y)
result = []
for x,y in neighbors:
if 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.neighbor_walls(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):
cur_row += char
self.map.append(cur_row)
def move_player(self, player, target_x, target_y):
if self.map[target_y][target_x] != '#':
player.y = target_y
player.x = target_x
def draw(self, win):
for y, row in enumerate(self.map):
win.addstr(y, 0, "".join(row))
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, height-status_height, begin_x)
# 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, actors):
assert self.map, "You forgot to call set_map()"
self.win.clear()
self.status.box()
self.map.draw(self.win)
# this assumes actors[0] is the player
self.draw_status(actors[0])
for actor in actors:
self.draw_actor(actor)
self.win.refresh()
def draw_status(self, player):
self.status.addstr(1, 1, f"PLAYER AT {player.x},{player.y}")
def draw_actor(self, actor):
assert self.map.map[actor.y][actor.x] != '#', f"WHAT? actor at {actor.x},{actor.y} but that's a wall!"
# actor has to be moved in by 1 for the border
self.win.addstr(actor.y, actor.x, actor.symbol, curses.A_BOLD)
def handle_input(self, x, y):
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 x, y
class Player:
def __init__(self, x, y):
self.x = x
self.y = y
self.symbol = '@'
class Enemy:
def __init__(self, x, y, symbol):
self.x = x
self.y = y
self.symbol = symbol
class GameEngine:
def __init__(self, ui):
self.ui = ui
self.map = Map(ui.width, ui.height - ui.status_height)
self.ui = ui
ui.set_map(self.map)
def spawn_actors(self):
x, y = self.map.spawn()
self.player = Player(x, y)
x, y = self.map.spawn()
self.enemy = Enemy(x, y, '{')
self.actors = [self.player, self.enemy]
def run(self):
self.spawn_actors()
self.map.move_player(self.player, self.player.x, self.player.y)
while True:
# remember, first one has to be the player
self.ui.update(self.actors)
new_x, new_y = self.ui.handle_input(self.player.x, self.player.y)
self.map.move_player(self.player, new_x, new_y)
def main(stdscr):
width=27
height=16
ui = UI(stdscr, height, width, 5)
game = GameEngine(ui)
game.run()
curses.wrapper(main)

@ -1,241 +0,0 @@
import curses
import sys
import random
import numpy as np
WALL = '#'
SPACE = '.'
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 spawn(self):
while True:
y = random.randrange(0, self.height)
x = random.randrange(0, self.width)
if self.map[y][x] == SPACE:
return x, y
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):
return np.full((self.height, self.width), WALL, dtype=str)
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.neighbors(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 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):
result.append([x,y])
return result
def neighbor_walls(self, grid, x, y):
neighbors = self.neighbors(grid, x, y)
result = []
for x,y in neighbors:
if 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.neighbor_walls(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):
cur_row += char
self.map.append(cur_row)
def collision(self, target_x, target_y):
# remember this is True==COLLIDE WITH WALL, False=CAN MOVE THERE
return self.map[target_y][target_x] == '#'
def draw(self, win):
for y, row in enumerate(self.map):
win.addstr(y, 0, "".join(row))
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, height-status_height, begin_x)
# 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, actors):
assert self.map, "You forgot to call set_map()"
self.win.clear()
self.status.box()
self.map.draw(self.win)
# this assumes actors[0] is the player
self.draw_status(actors)
for actor in actors:
self.draw_actor(actor)
self.win.refresh()
def draw_status(self, actors):
for line, actor in enumerate(actors):
self.status.addstr(line+1, 1, f"PLAYER AT {actor.x},{actor.y}")
def draw_actor(self, actor):
assert self.map.map[actor.y][actor.x] != '#', f"WHAT? actor at {actor.x},{actor.y} but that's a wall!"
# actor has to be moved in by 1 for the border
self.win.addstr(actor.y, actor.x, actor.symbol, curses.A_BOLD)
def handle_input(self, x, y):
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 x, y
class Player:
def __init__(self, x, y):
self.x = x
self.y = y
self.symbol = '@'
class Enemy:
def __init__(self, x, y, symbol):
self.x = x
self.y = y
self.symbol = symbol
class GameEngine:
def __init__(self, ui):
self.ui = ui
self.map = Map(ui.width, ui.height - ui.status_height)
self.ui = ui
ui.set_map(self.map)
def collision(self, actor, x, y):
if self.map.collision(x, y): return True
for target in self.actors:
if target != actor and target.x == x and target.y == y:
return True
return False
def move_actor(self, actor, x, y):
if not self.collision(actor, x, y):
actor.x = x
actor.y = y
def spawn_actors(self):
x, y = self.map.spawn()
self.player = Player(x, y)
x, y = self.map.spawn()
self.enemy = Enemy(x, y, '{')
self.actors = [self.player, self.enemy]
def run(self):
self.spawn_actors()
while True:
# remember, first one has to be the player
self.ui.update(self.actors)
new_x, new_y = self.ui.handle_input(self.player.x, self.player.y)
self.move_actor(self.player, new_x, new_y)
def main(stdscr):
width=27
height=16
ui = UI(stdscr, height, width, 5)
game = GameEngine(ui)
game.run()
curses.wrapper(main)

@ -1,271 +0,0 @@
import curses
import sys
import random
import numpy as np
WALL = '#'
SPACE = '.'
class Player:
def __init__(self, x, y):
self.x = x
self.y = y
self.symbol = '@'
self.name = 'You'
self.hp = 10
self.damage = 2
class Enemy:
def __init__(self, x, y, symbol):
self.x = x
self.y = y
self.symbol = symbol
self.name = 'Bat'
self.hp = 5
self.damage = 1
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 spawn(self):
while True:
y = random.randrange(0, self.height)
x = random.randrange(0, self.width)
if self.map[y][x] == SPACE:
return x, y
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):
return np.full((self.height, self.width), WALL, dtype=str)
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.neighbors(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 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):
result.append([x,y])
return result
def neighbor_walls(self, grid, x, y):
neighbors = self.neighbors(grid, x, y)
result = []
for x,y in neighbors:
if 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.neighbor_walls(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):
cur_row += char
self.map.append(cur_row)
def collision(self, target_x, target_y):
# remember this is True==COLLIDE WITH WALL, False=CAN MOVE THERE
return self.map[target_y][target_x] == '#'
def draw(self, win):
for y, row in enumerate(self.map):
win.addstr(y, 0, "".join(row))
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, height-status_height, begin_x)
# 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_msg = "HAVE FUN!"
self.status_height = status_height
def set_map(self, the_map):
self.map = the_map
def update(self, actors):
assert self.map, "You forgot to call set_map()"
self.win.clear()
self.status.box()
self.map.draw(self.win)
# this assumes actors[0] is the player
self.draw_status(actors)
for actor in actors:
self.draw_actor(actor)
self.win.refresh()
def post_status(self, msg):
self.status_msg = msg
def draw_status(self, actors):
for line, actor in enumerate(actors):
self.status.addstr(line+1, 1, f"PLAYER AT {actor.x},{actor.y}")
self.status.addstr(1, self.width // 2, self.status_msg)
def draw_actor(self, actor):
assert self.map.map[actor.y][actor.x] != '#', f"WHAT? actor at {actor.x},{actor.y} but that's a wall!"
# actor has to be moved in by 1 for the border
self.win.addstr(actor.y, actor.x, actor.symbol, curses.A_BOLD)
def handle_input(self, x, y):
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 x, y
class GameEngine:
def __init__(self, ui):
self.ui = ui
self.map = Map(ui.width, ui.height - ui.status_height)
self.ui = ui
ui.set_map(self.map)
def death(self, target):
self.actors.remove(target)
self.ui.post_status(f"Killed {target.name}")
def combat(self, actor, target):
target.hp -= actor.damage
if target.hp > 0:
self.ui.post_status(f"HIT {target.name} for {actor.damage}")
else:
self.death(target)
def actor_collision(self, actor, x, y):
for target in self.actors:
if target != actor and target.x == x and target.y == y:
return target
return None
def collision(self, actor, x, y):
if self.map.collision(x, y): return True
target = self.actor_collision(actor, x, y)
if target:
self.combat(actor, target)
return True
return False
def move_actor(self, actor, x, y):
if not self.collision(actor, x, y):
actor.x = x
actor.y = y
def spawn_actors(self):
x, y = self.map.spawn()
self.player = Player(x, y)
x, y = self.map.spawn()
self.enemy = Enemy(x, y, '{')
self.actors = [self.player, self.enemy]
def run(self):
self.spawn_actors()
while True:
# remember, first one has to be the player
self.ui.update(self.actors)
new_x, new_y = self.ui.handle_input(self.player.x, self.player.y)
self.move_actor(self.player, new_x, new_y)
def main(stdscr):
width=27
height=16
ui = UI(stdscr, height, width, 5)
game = GameEngine(ui)
game.run()
curses.wrapper(main)

@ -1,270 +0,0 @@
import curses
import sys
import random
import numpy as np
WALL = '#'
SPACE = '.'
class Player:
def __init__(self, x, y):
self.x = x
self.y = y
self.symbol = '@'
self.name = 'You'
self.hp = 10
self.damage = 2
class Enemy:
def __init__(self, x, y, symbol):
self.x = x
self.y = y
self.symbol = symbol
self.name = 'Bat'
self.hp = 5
self.damage = 1
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 spawn(self):
while True:
y = random.randrange(0, self.height)
x = random.randrange(0, self.width)
if self.map[y][x] == SPACE:
return x, y
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):
return np.full((self.height, self.width), WALL, dtype=str)
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.neighbors(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 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):
result.append([x,y])
return result
def neighbor_walls(self, grid, x, y):
neighbors = self.neighbors(grid, x, y)
result = []
for x,y in neighbors:
if 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.neighbor_walls(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):
cur_row += char
self.map.append(cur_row)
def collision(self, target_x, target_y):
# remember this is True==COLLIDE WITH WALL, False=CAN MOVE THERE
return self.map[target_y][target_x] == '#'
def draw(self, win):
for y, row in enumerate(self.map):
win.addstr(y, 0, "".join(row))
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, height-status_height, begin_x)
# 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_msg = "HAVE FUN!"
self.status_height = status_height
def set_map(self, the_map):
self.map = the_map
def update(self, actors):
assert self.map, "You forgot to call set_map()"
self.win.clear()
self.status.box()
self.map.draw(self.win)
# this assumes actors[0] is the player
self.draw_status(actors)
for actor in actors:
self.draw_actor(actor)
self.win.refresh()
def post_status(self, msg):
self.status_msg = msg
def draw_status(self, actors):
self.status.addstr(1, 1, self.status_msg)
def draw_actor(self, actor):
assert self.map.map[actor.y][actor.x] != '#', f"WHAT? actor at {actor.x},{actor.y} but that's a wall!"
# actor has to be moved in by 1 for the border
self.win.addstr(actor.y, actor.x, actor.symbol, curses.A_BOLD)
def handle_input(self, x, y):
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 x, y
class GameEngine:
def __init__(self, ui):
self.ui = ui
self.map = Map(ui.width, ui.height - ui.status_height)
self.ui = ui
ui.set_map(self.map)
def death(self, target):
self.actors.remove(target)
self.ui.post_status(f"Killed {target.name}")
def combat(self, actor, target):
target.hp -= actor.damage
if target.hp > 0:
self.ui.post_status(f"HIT {target.name} for {actor.damage}")
else:
self.death(target)
def actor_collision(self, actor, x, y):
for target in self.actors:
if target != actor and target.x == x and target.y == y:
return target
return None
def collision(self, actor, x, y):
if self.map.collision(x, y): return True
target = self.actor_collision(actor, x, y)
if target:
self.combat(actor, target)
return True
return False
def move_actor(self, actor, x, y):
if not self.collision(actor, x, y):
actor.x = x
actor.y = y
def spawn_actors(self, enemy_count):
x, y = self.map.spawn()
self.player = Player(x, y)
self.actors = [self.player]
for i in range(0, enemy_count):
x, y = self.map.spawn()
enemy = Enemy(x, y, '{')
self.actors.append(enemy)
def run(self):
self.spawn_actors(5)
while True:
# remember, first one has to be the player
self.ui.update(self.actors)
new_x, new_y = self.ui.handle_input(self.player.x, self.player.y)
self.move_actor(self.player, new_x, new_y)
def main(stdscr):
width=27
height=16
ui = UI(stdscr, height, width, 5)
game = GameEngine(ui)
game.run()
curses.wrapper(main)

@ -1,344 +0,0 @@
import curses
import sys
import random
import numpy as np
WALL = '#'
SPACE = '.'
PATH_LIMIT = 1000
def compass(x, y, offset=1):
return [[x, y - offset], # North
[x, y + offset], # South
[x + offset, y], # East
[x - offset, y]] # West
class Player:
def __init__(self, x, y):
self.x = x
self.y = y
self.symbol = '@'
self.name = 'You'
self.hp = 10
self.damage = 2
class Enemy:
def __init__(self, x, y, symbol):
self.x = x
self.y = y
self.symbol = symbol
self.name = 'Bat'
self.hp = 5
self.damage = 1
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 spawn(self):
while True:
y = random.randrange(0, self.height)
x = random.randrange(0, self.width)
if self.map[y][x] == SPACE:
return x, y
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):
return np.full((self.height, self.width), WALL, dtype=str)
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.neighbors(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 neighbors(self, grid, x, y):
points = compass(x, y, 2)
result = []
for x,y in points:
if self.inbounds(x, y):
result.append([x,y])
return result
def neighbor_walls(self, grid, x, y):
neighbors = self.neighbors(grid, x, y)
result = []
for x,y in neighbors:
if 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.neighbor_walls(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):
cur_row += char
self.map.append(cur_row)
def collision(self, target_x, target_y):
# remember this is True==COLLIDE WITH WALL, False=CAN MOVE THERE
return self.map[target_y][target_x] == WALL
def draw(self, win):
for y, row in enumerate(self.map):
win.addstr(y, 0, "".join(row))
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, height-status_height, begin_x)
# 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_msg = "HAVE FUN!"
self.status_height = status_height
def set_map(self, the_map):
self.map = the_map
def update(self, actors):
assert self.map, "You forgot to call set_map()"
self.win.clear()
self.status.box()
self.map.draw(self.win)
# this assumes actors[0] is the player
self.draw_status(actors)
for actor in actors:
self.draw_actor(actor)
self.win.refresh()
def post_status(self, msg):
self.status_msg = msg
def draw_status(self, actors):
self.status.addstr(1, 1, self.status_msg)
def draw_actor(self, actor):
assert self.map.map[actor.y][actor.x] != WALL, f"WHAT? actor at {actor.x},{actor.y} but that's a wall!"
# actor has to be moved in by 1 for the border
self.win.addstr(actor.y, actor.x, actor.symbol, curses.A_BOLD)
def handle_input(self, x, y):
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 x, y
class GameEngine:
def __init__(self, ui):
self.ui = ui
self.map = Map(ui.width, ui.height - ui.status_height)
self.ui = ui
ui.set_map(self.map)
def add_neighbors(self, neighbors, closed, near_y, near_x):
points = compass(near_x, near_y)
for x,y in points:
if self.map.inbounds(x,y) and closed[y][x] == SPACE:
closed[y][x] = WALL
neighbors.append([x,y])
def path_enemies(self, in_grid):
height = self.map.height
width = self.map.width
self.paths = [[PATH_LIMIT] * width for x in range(0, height)]
closed = [list(row) for row in self.map.map]
starting_pixels = []
open_pixels = []
counter = 0
while counter < height * width:
x = counter % width
y = counter // width
if in_grid[y][x] == 0:
self.paths[y][x] = 0
closed[y][x] = WALL
starting_pixels.append([x,y])
counter += 1
for x, y in starting_pixels:
self.add_neighbors(open_pixels, closed, y, x)
counter = 1
while counter < PATH_LIMIT and open_pixels:
next_open = []
for x,y in open_pixels:
self.paths[y][x] = counter
self.add_neighbors(next_open, closed, y, x)
open_pixels = next_open
counter += 1
for x, y in open_pixels:
self.paths[y][x] = counter
def debug_paths(self):
debug_map = []
for y in range(0, self.map.height):
row = list(self.map.map[y])
for x in range(0, self.map.width):
level = self.paths[y][x]
if row[x] != WALL:
if level < 10:
row[x] = str(level)
else:
row[x] = '*'
debug_map.append("".join(row))
return debug_map
def move_enemies(self):
in_grid = [[1] * self.map.width for x in range(0, self.map.height)]
in_grid[self.player.y][self.player.x] = 0
self.path_enemies(in_grid)
def death(self, target):
self.actors.remove(target)
self.ui.post_status(f"Killed {target.name}")
def combat(self, actor, target):
target.hp -= actor.damage
if target.hp > 0:
self.ui.post_status(f"HIT {target.name} for {actor.damage}")
else:
self.death(target)
def actor_collision(self, actor, x, y):
for target in self.actors:
if target != actor and target.x == x and target.y == y:
return target
return None
def collision(self, actor, x, y):
if self.map.collision(x, y): return True
target = self.actor_collision(actor, x, y)
if target:
self.combat(actor, target)
return True
return False
def move_player(self, actor, x, y):
if not self.collision(actor, x, y):
actor.x = x
actor.y = y
def spawn_actors(self, enemy_count):
x, y = self.map.spawn()
self.player = Player(x, y)
self.actors = [self.player]
for i in range(0, enemy_count):
x, y = self.map.spawn()
enemy = Enemy(x, y, '{')
self.actors.append(enemy)
def run(self):
self.spawn_actors(5)
self.move_enemies()
while True:
# remember, first one has to be the player
the_map = self.map.map
self.map.map = self.debug_paths()
self.ui.update(self.actors)
self.map.map = the_map
new_x, new_y = self.ui.handle_input(self.player.x, self.player.y)
self.move_player(self.player, new_x, new_y)
self.move_enemies()
def main(stdscr):
width=27
height=16
ui = UI(stdscr, height, width, 5)
game = GameEngine(ui)
game.run()
curses.wrapper(main)

@ -1,353 +0,0 @@
import curses
import sys
import random
import numpy as np
WALL = '#'
SPACE = '.'
PATH_LIMIT = 1000
def compass(x, y, offset=1):
return [[x, y - offset], # North
[x, y + offset], # South
[x + offset, y], # East
[x - offset, y]] # West
class Player:
def __init__(self, x, y):
self.x = x
self.y = y
self.symbol = '@'
self.name = 'You'
self.hp = 10
self.damage = 2
class Enemy:
def __init__(self, x, y, symbol):
self.x = x
self.y = y
self.symbol = symbol
self.name = 'Python'
self.hp = 5
self.damage = 1
self.hearing_distance = 5
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 spawn(self):
while True:
y = random.randrange(0, self.height)
x = random.randrange(0, self.width)
if self.map[y][x] == SPACE:
return x, y
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):
return np.full((self.height, self.width), WALL, dtype=str)
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.neighbors(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 neighbors(self, grid, x, y):
points = compass(x, y, 2)
result = []
for x,y in points:
if self.inbounds(x, y):
result.append([x,y])
return result
def neighbor_walls(self, grid, x, y):
neighbors = self.neighbors(grid, x, y)
result = []
for x,y in neighbors:
if 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.neighbor_walls(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):
cur_row += char
self.map.append(cur_row)
def collision(self, target_x, target_y):
# remember this is True==COLLIDE WITH WALL, False=CAN MOVE THERE
return self.map[target_y][target_x] == WALL
def draw(self, win):
for y, row in enumerate(self.map):
win.addstr(y, 0, "".join(row))
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, height-status_height, begin_x)
# 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_msg = "HAVE FUN!"
self.status_height = status_height
def set_map(self, the_map):
self.map = the_map
def update(self, actors):
assert self.map, "You forgot to call set_map()"
self.win.clear()
self.status.box()
self.map.draw(self.win)
# this assumes actors[0] is the player
self.draw_status(actors)
for actor in actors:
self.draw_actor(actor)
self.win.refresh()
def post_status(self, msg):
self.status_msg = msg
def draw_status(self, actors):
self.status.addstr(1, 1, self.status_msg)
def draw_actor(self, actor):
assert self.map.map[actor.y][actor.x] != WALL, f"WHAT? actor at {actor.x},{actor.y} but that's a wall!"
# actor has to be moved in by 1 for the border
self.win.addstr(actor.y, actor.x, actor.symbol, curses.A_BOLD)
def handle_input(self, x, y):
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 x, y
class GameEngine:
def __init__(self, ui):
self.ui = ui
self.map = Map(ui.width, ui.height - ui.status_height)
self.ui = ui
ui.set_map(self.map)
def add_neighbors(self, neighbors, closed, near_y, near_x):
points = compass(near_x, near_y)
for x,y in points:
if self.map.inbounds(x,y) and closed[y][x] == SPACE:
closed[y][x] = WALL
neighbors.append([x,y])
def path_enemies(self, in_grid):
height = self.map.height
width = self.map.width
self.paths = [[PATH_LIMIT] * width for x in range(0, height)]
closed = [list(row) for row in self.map.map]
starting_pixels = []
open_pixels = []
counter = 0
while counter < height * width:
x = counter % width
y = counter // width
if in_grid[y][x] == 0:
self.paths[y][x] = 0
closed[y][x] = WALL
starting_pixels.append([x,y])
counter += 1
for x, y in starting_pixels:
self.add_neighbors(open_pixels, closed, y, x)
counter = 1
while counter < PATH_LIMIT and open_pixels:
next_open = []
for x,y in open_pixels:
self.paths[y][x] = counter
self.add_neighbors(next_open, closed, y, x)
open_pixels = next_open
counter += 1
for x, y in open_pixels:
self.paths[y][x] = counter
def debug_paths(self):
debug_map = []
for y in range(0, self.map.height):
row = list(self.map.map[y])
for x in range(0, self.map.width):
level = self.paths[y][x]
if row[x] != WALL:
if level < 10:
row[x] = str(level)
else:
row[x] = '*'
debug_map.append("".join(row))
return debug_map
def move_enemies(self):
in_grid = [[1] * self.map.width for x in range(0, self.map.height)]
in_grid[self.player.y][self.player.x] = 0
self.path_enemies(in_grid)
# for every enemy (actors[0] is player)
for enemy in self.actors[1:]:
nearby = compass(enemy.x, enemy.y)
our_path = self.paths[enemy.y][enemy.x]
if our_path > enemy.hearing_distance: continue
for x, y in nearby:
if self.paths[y][x] <= our_path and not self.actor_collision(enemy, x, y):
enemy.x = x
enemy.y = y
break
def death(self, target):
self.actors.remove(target)
self.ui.post_status(f"Killed {target.name}")
def combat(self, actor, target):
target.hp -= actor.damage
if target.hp > 0:
self.ui.post_status(f"HIT {target.name} for {actor.damage}")
else:
self.death(target)
def actor_collision(self, actor, x, y):
for target in self.actors:
if target != actor and target.x == x and target.y == y:
return target
return None
def collision(self, actor, x, y):
if self.map.collision(x, y): return True
target = self.actor_collision(actor, x, y)
if target:
self.combat(actor, target)
return True
return False
def move_player(self, actor, x, y):
if not self.collision(actor, x, y):
actor.x = x
actor.y = y
def spawn_actors(self, enemy_count):
x, y = self.map.spawn()
self.player = Player(x, y)
self.actors = [self.player]
for i in range(0, enemy_count):
x, y = self.map.spawn()
enemy = Enemy(x, y, '{')
self.actors.append(enemy)
def run(self):
self.spawn_actors(5)
self.move_enemies()
while True:
# remember, first one has to be the player
self.ui.update(self.actors)
new_x, new_y = self.ui.handle_input(self.player.x, self.player.y)
self.move_player(self.player, new_x, new_y)
self.move_enemies()
def main(stdscr):
width=27
height=16
ui = UI(stdscr, height, width, 5)
game = GameEngine(ui)
game.run()
curses.wrapper(main)

@ -1,21 +1,21 @@
import curses import curses
import sys import sys
import numpy as np
MAP = np.array([
list("####################"),
list("###....#############"),
list("###....#############"),
list("###...........######"),
list("#############.######"),
list("#############....###"),
list("#############....###"),
list("####################")], dtype=str)
MAP = [
"####################",
"###....#############",
"###....#############",
"###...........######",
"#############.######",
"#############....###",
"#############....###",
"####################"]
def draw_map(win): def draw_map(win):
map_line = 1 for y, row in enumerate(MAP):
for line in MAP: win.addstr(y, 0, "".join(row))
win.addstr(map_line, 1, line)
map_line += 1
def draw_status(status): def draw_status(status):
status.addstr(1, 1, "PLAYER STATS") status.addstr(1, 1, "PLAYER STATS")
@ -25,30 +25,29 @@ def draw_player(win, player_y, player_x):
def update(win, status, player_y, player_x): def update(win, status, player_y, player_x):
win.clear() win.clear()
win.box() status.box()
status.hline(0,0, curses.ACS_HLINE, 78)
draw_map(win) draw_map(win)
draw_status(status) draw_status(status)
draw_player(win, player_y, player_x) draw_player(win, player_y, player_x)
win.refresh() win.refresh()
def create_ui(stdscr, height, width, status_height): def create_ui(stdscr, width, height, status_height):
curses.curs_set(0) curses.curs_set(0)
stdscr.clear() stdscr.clear()
begin_x = 0 begin_x = 0
begin_y = 0 begin_y = 0
win = curses.newwin(height, width, begin_y, begin_x) win = curses.newwin(height, width, begin_y, begin_x)
status = win.subwin(status_height, width-2, height-status_height, begin_x+1) status = win.subwin(status_height, width, height-status_height, begin_x)
win.keypad(True) win.keypad(True)
return win, status return win, status
def move_player(player_y, player_x, target_y, target_x): def move_player(player_y, player_x, target_y, target_x):
if MAP[target_y - 1][target_x - 1] != '#': if MAP[target_y][target_x] != '#':
return target_y, target_x return target_y, target_x
else: else:
return player_y, player_x return player_y, player_x
def handle_input(win, y, x, height, width): def handle_input(win, y, x, width, height):
ch = win.getch() ch = win.getch()
if ch == ord('q'): if ch == ord('q'):
@ -65,17 +64,17 @@ def handle_input(win, y, x, height, width):
return y, x return y, x
def main(stdscr): def main(stdscr):
width=80 width=27
height=26 height=17
win, status = create_ui(stdscr, 26, 80, 5) win, status = create_ui(stdscr, width, height, 5)
player_x = 4 player_x = 3
player_y = 4 player_y = 3
while True: while True:
update(win, status, player_y, player_x) update(win, status, player_y, player_x)
new_y, new_x = handle_input( new_y, new_x = handle_input(
win, player_y, player_x, height, width) win, player_y, player_x, width, height)
player_y, player_x = move_player( player_y, player_x = move_player(
player_y, player_x, new_y, new_x) player_y, player_x, new_y, new_x)

@ -1,15 +1,16 @@
import curses import curses
import sys import sys
import numpy as np
MAP = [
"####################", MAP = np.array([
"###....#############", list("####################"),
"###....#############", list("###....#############"),
"###...........######", list("###....#############"),
"#############.######", list("###...........######"),
"#############....###", list("#############.######"),
"#############....###", list("#############....###"),
"####################"] list("#############....###"),
list("####################")], dtype=str)
class UI: class UI:
def __init__(self, stdscr, height, width, status_height): def __init__(self, stdscr, height, width, status_height):
@ -20,7 +21,7 @@ class UI:
win = curses.newwin(height, width, begin_y, begin_x) win = curses.newwin(height, width, begin_y, begin_x)
win.keypad(True) win.keypad(True)
status = win.subwin(status_height, width-2, height-status_height, begin_x+1) status = win.subwin(status_height, width, height-status_height, begin_x)
# keep these for later by assigning to self # keep these for later by assigning to self
self.begin_x = 0 self.begin_x = 0
@ -33,18 +34,15 @@ class UI:
def update(self, player_y, player_x): def update(self, player_y, player_x):
self.win.clear() self.win.clear()
self.win.box() self.status.box()
self.status.hline(0,0, curses.ACS_HLINE, self.width - 2)
self.draw_map() self.draw_map()
self.draw_status() self.draw_status()
self.draw_player(player_y, player_x) self.draw_player(player_y, player_x)
self.win.refresh() self.win.refresh()
def draw_map(self): def draw_map(self):
map_line = 1 for y, row in enumerate(MAP):
for line in MAP: self.win.addstr(y, 0, "".join(row))
self.win.addstr(map_line, 1, line)
map_line += 1
def draw_status(self): def draw_status(self):
self.status.addstr(1, 1, "PLAYER STATS") self.status.addstr(1, 1, "PLAYER STATS")
@ -69,18 +67,18 @@ class UI:
return y, x return y, x
def move_player(player_y, player_x, target_y, target_x): def move_player(player_y, player_x, target_y, target_x):
if MAP[target_y - 1][target_x - 1] != '#': if MAP[target_y][target_x] != '#':
return target_y, target_x return target_y, target_x
else: else:
return player_y, player_x return player_y, player_x
def main(stdscr): def main(stdscr):
width=80 width=27
height=26 height=16
ui = UI(stdscr, height, width, 5) ui = UI(stdscr, height, width, 5)
player_x = 4 player_x = 3
player_y = 4 player_y = 3
while True: while True:
ui.update(player_y, player_x) ui.update(player_y, player_x)

@ -1,31 +1,28 @@
import curses import curses
import sys import sys
import numpy as np
class Map: class Map:
def __init__(self): def __init__(self):
self.map = [ self.map = [
"####################", list("####################"),
"###....#############", list("###....#############"),
"###....#############", list("###....#############"),
"###...........######", list("###...........######"),
"#############.######", list("#############.######"),
"#############....###", list("#############....###"),
"#############....###", list("#############....###"),
"####################"] list("####################")]
def move_player(self, player_y, player_x, target_y, target_x): def move_player(self, player_y, player_x, target_y, target_x):
if self.map[target_y - 1][target_x - 1] != '#': if self.map[target_y][target_x] != '#':
return target_y, target_x return target_y, target_x
else: else:
return player_y, player_x return player_y, player_x
def draw(self, win): def draw(self, win):
map_line = 1 for y, row in enumerate(self.map):
for line in self.map: win.addstr(y, 0, "".join(row))
win.addstr(map_line, 1, line)
map_line += 1
class UI: class UI:
def __init__(self, stdscr, the_map, height, width, status_height): def __init__(self, stdscr, the_map, height, width, status_height):
@ -36,7 +33,7 @@ class UI:
win = curses.newwin(height, width, begin_y, begin_x) win = curses.newwin(height, width, begin_y, begin_x)
win.keypad(True) win.keypad(True)
status = win.subwin(status_height, width-2, height-status_height, begin_x+1) status = win.subwin(status_height, width, height-status_height, begin_x)
# keep these for later by assigning to self # keep these for later by assigning to self
self.begin_x = 0 self.begin_x = 0
@ -50,8 +47,7 @@ class UI:
def update(self, player_y, player_x): def update(self, player_y, player_x):
self.win.clear() self.win.clear()
self.win.box() self.status.box()
self.status.hline(0,0, curses.ACS_HLINE, self.width - 2)
self.map.draw(self.win) self.map.draw(self.win)
self.draw_status() self.draw_status()
self.draw_player(player_y, player_x) self.draw_player(player_y, player_x)
@ -81,13 +77,13 @@ class UI:
return y, x return y, x
def main(stdscr): def main(stdscr):
width=80 width=27
height=26 height=16
the_map = Map() the_map = Map()
ui = UI(stdscr, the_map, height, width, 5) ui = UI(stdscr, the_map, height, width, 5)
player_x = 4 player_x = 3
player_y = 4 player_y = 3
while True: while True:
ui.update(player_y, player_x) ui.update(player_y, player_x)

@ -1,29 +1,27 @@
import curses import curses
import sys import sys
import numpy as np
class Map: class Map:
def __init__(self): def __init__(self):
self.map = [ self.map = [
"####################", list("####################"),
"###....#############", list("###....#############"),
"###....#############", list("###....#############"),
"###...........######", list("###...........######"),
"#############.######", list("#############.######"),
"#############....###", list("#############....###"),
"#############....###", list("#############....###"),
"####################"] list("####################")]
def move_player(self, player, target_y, target_x): def move_player(self, player, target_y, target_x):
if self.map[target_y - 1][target_x - 1] != '#': if self.map[target_y][target_x] != '#':
player.y = target_y player.y = target_y
player.x = target_x player.x = target_x
def draw(self, win): def draw(self, win):
map_line = 1 for y, row in enumerate(self.map):
for line in self.map: win.addstr(y, 0, "".join(row))
win.addstr(map_line, 1, line)
map_line += 1
class UI: class UI:
def __init__(self, stdscr, the_map, height, width, status_height): def __init__(self, stdscr, the_map, height, width, status_height):
@ -34,7 +32,7 @@ class UI:
win = curses.newwin(height, width, begin_y, begin_x) win = curses.newwin(height, width, begin_y, begin_x)
win.keypad(True) win.keypad(True)
status = win.subwin(status_height, width-2, height-status_height, begin_x+1) status = win.subwin(status_height, width, height-status_height, begin_x)
# keep these for later by assigning to self # keep these for later by assigning to self
self.begin_x = 0 self.begin_x = 0
@ -48,8 +46,7 @@ class UI:
def update(self, player): def update(self, player):
self.win.clear() self.win.clear()
self.win.box() self.status.box()
self.status.hline(0,0, curses.ACS_HLINE, self.width - 2)
self.map.draw(self.win) self.map.draw(self.win)
self.draw_status() self.draw_status()
self.draw_player(player) self.draw_player(player)
@ -84,11 +81,11 @@ class Player:
def main(stdscr): def main(stdscr):
width=80 width=27
height=26 height=16
the_map = Map() the_map = Map()
ui = UI(stdscr, the_map, height, width, 5) ui = UI(stdscr, the_map, height, width, 5)
player = Player(4, 4) player = Player(3, 3)
while True: while True:
ui.update(player) ui.update(player)

@ -1,29 +1,27 @@
import curses import curses
import sys import sys
import numpy as np
class Map: class Map:
def __init__(self): def __init__(self):
self.map = [ self.map = [
"####################", list("####################"),
"###....#############", list("###....#############"),
"###....#############", list("###....#############"),
"###...........######", list("###...........######"),
"#############.######", list("#############.######"),
"#############....###", list("#############....###"),
"#############....###", list("#############....###"),
"####################"] list("####################")]
def move_player(self, player, target_y, target_x): def move_player(self, player, target_y, target_x):
if self.map[target_y - 1][target_x - 1] != '#': if self.map[target_y][target_x] != '#':
player.y = target_y player.y = target_y
player.x = target_x player.x = target_x
def draw(self, win): def draw(self, win):
map_line = 1 for y, row in enumerate(self.map):
for line in self.map: win.addstr(y, 0, "".join(row))
win.addstr(map_line, 1, line)
map_line += 1
class UI: class UI:
def __init__(self, stdscr, height, width, status_height): def __init__(self, stdscr, height, width, status_height):
@ -34,7 +32,7 @@ class UI:
win = curses.newwin(height, width, begin_y, begin_x) win = curses.newwin(height, width, begin_y, begin_x)
win.keypad(True) win.keypad(True)
status = win.subwin(status_height, width-2, height-status_height, begin_x+1) status = win.subwin(status_height, width, height-status_height, begin_x)
# keep these for later by assigning to self # keep these for later by assigning to self
self.begin_x = 0 self.begin_x = 0
@ -52,8 +50,7 @@ class UI:
def update(self, player): def update(self, player):
assert self.map, "You forgot to call set_map()" assert self.map, "You forgot to call set_map()"
self.win.clear() self.win.clear()
self.win.box() self.status.box()
self.status.hline(0,0, curses.ACS_HLINE, self.width - 2)
self.map.draw(self.win) self.map.draw(self.win)
self.draw_status() self.draw_status()
self.draw_player(player) self.draw_player(player)
@ -89,7 +86,7 @@ class Player:
class GameEngine: class GameEngine:
def __init__(self, ui): def __init__(self, ui):
self.ui = ui self.ui = ui
self.player = Player(4, 4) self.player = Player(3, 3)
self.map = Map() self.map = Map()
self.ui = ui self.ui = ui
ui.set_map(self.map) ui.set_map(self.map)
@ -101,8 +98,8 @@ class GameEngine:
self.map.move_player(self.player, new_y, new_x) self.map.move_player(self.player, new_y, new_x)
def main(stdscr): def main(stdscr):
width=80 width=27
height=26 height=16
ui = UI(stdscr, height, width, 5) ui = UI(stdscr, height, width, 5)
game = GameEngine(ui) game = GameEngine(ui)
game.run() game.run()

@ -1,6 +1,7 @@
import curses import curses
import sys import sys
import random import random
import numpy as np
WALL = 1 WALL = 1
SPACE = 0 SPACE = 0
@ -114,16 +115,14 @@ class Map:
self.map.append(cur_row) self.map.append(cur_row)
def move_player(self, player, target_y, target_x): def move_player(self, player, target_x, target_y):
if self.map[target_y - 1][target_x - 1] != '#': if self.map[target_y][target_x] != '#':
player.y = target_y player.y = target_y
player.x = target_x player.x = target_x
def draw(self, win): def draw(self, win):
map_line = 1 for y, row in enumerate(self.map):
for line in self.map: win.addstr(y, 0, "".join(row))
win.addstr(map_line, 1, line)
map_line += 1
class UI: class UI:
def __init__(self, stdscr, height, width, status_height): def __init__(self, stdscr, height, width, status_height):
@ -134,7 +133,7 @@ class UI:
win = curses.newwin(height, width, begin_y, begin_x) win = curses.newwin(height, width, begin_y, begin_x)
win.keypad(True) win.keypad(True)
status = win.subwin(status_height, width-2, height-status_height, begin_x+1) status = win.subwin(status_height, width, height-status_height, begin_x)
# keep these for later by assigning to self # keep these for later by assigning to self
self.begin_x = 0 self.begin_x = 0
@ -152,8 +151,7 @@ class UI:
def update(self, player): def update(self, player):
assert self.map, "You forgot to call set_map()" assert self.map, "You forgot to call set_map()"
self.win.clear() self.win.clear()
self.win.box() self.status.box()
self.status.hline(0,0, curses.ACS_HLINE, self.width - 2)
self.map.draw(self.win) self.map.draw(self.win)
self.draw_status() self.draw_status()
self.draw_player(player) self.draw_player(player)
@ -165,7 +163,7 @@ class UI:
def draw_player(self, player): def draw_player(self, player):
self.win.addstr(player.y, player.x, '@', curses.A_BOLD) self.win.addstr(player.y, player.x, '@', curses.A_BOLD)
def handle_input(self, y, x): def handle_input(self, x, y):
ch = self.win.getch() ch = self.win.getch()
if ch == ord('q'): if ch == ord('q'):
@ -179,7 +177,7 @@ class UI:
elif ch == curses.KEY_LEFT: elif ch == curses.KEY_LEFT:
x = (x - 1) % self.width x = (x - 1) % self.width
return y, x return x, y
class Player: class Player:
def __init__(self, x, y): def __init__(self, x, y):
@ -189,20 +187,20 @@ class Player:
class GameEngine: class GameEngine:
def __init__(self, ui): def __init__(self, ui):
self.ui = ui self.ui = ui
self.player = Player(4, 4) self.player = Player(3, 3)
self.map = Map(77,19) self.map = Map(self.ui.width, self.ui.height - self.ui.status_height)
self.ui = ui self.ui = ui
ui.set_map(self.map) ui.set_map(self.map)
def run(self): def run(self):
while True: while True:
self.ui.update(self.player) self.ui.update(self.player)
new_y, new_x = self.ui.handle_input(self.player.y, self.player.x) new_x, new_y = self.ui.handle_input(self.player.x, self.player.y)
self.map.move_player(self.player, new_y, new_x) self.map.move_player(self.player, new_x, new_y)
def main(stdscr): def main(stdscr):
width=80 width=27
height=26 height=16
ui = UI(stdscr, height, width, 5) ui = UI(stdscr, height, width, 5)
game = GameEngine(ui) game = GameEngine(ui)
game.run() game.run()

@ -1,6 +1,7 @@
import curses import curses
import sys import sys
import random import random
import numpy as np
WALL = '#' WALL = '#'
SPACE = '.' SPACE = '.'
@ -30,11 +31,7 @@ class Map:
return grid return grid
def make_grid(self): def make_grid(self):
grid = [] return np.full((self.height, self.width), WALL, dtype=str)
for y in range(0, self.height):
grid.append([WALL] * self.width)
return grid
def make_room(self, grid, x, y, size): def make_room(self, grid, x, y, size):
for row in range(y, y+size): for row in range(y, y+size):
@ -120,10 +117,8 @@ class Map:
player.x = target_x player.x = target_x
def draw(self, win): def draw(self, win):
map_line = 0 for y, row in enumerate(self.map):
for line in self.map: win.addstr(y, 0, "".join(row))
win.addstr(map_line, 0, line)
map_line += 1
class UI: class UI:
def __init__(self, stdscr, height, width, status_height): def __init__(self, stdscr, height, width, status_height):

@ -1,6 +1,7 @@
import curses import curses
import sys import sys
import random import random
import numpy as np
WALL = '#' WALL = '#'
SPACE = '.' SPACE = '.'
@ -30,11 +31,7 @@ class Map:
return grid return grid
def make_grid(self): def make_grid(self):
grid = [] return np.full((self.height, self.width), WALL, dtype=str)
for y in range(0, self.height):
grid.append([WALL] * self.width)
return grid
def make_room(self, grid, x, y, size): def make_room(self, grid, x, y, size):
for row in range(y, y+size): for row in range(y, y+size):
@ -118,10 +115,8 @@ class Map:
return self.map[target_y][target_x] == '#' return self.map[target_y][target_x] == '#'
def draw(self, win): def draw(self, win):
map_line = 0 for y, row in enumerate(self.map):
for line in self.map: win.addstr(y, 0, "".join(row))
win.addstr(map_line, 0, line)
map_line += 1
class UI: class UI:
def __init__(self, stdscr, height, width, status_height): def __init__(self, stdscr, height, width, status_height):
@ -160,10 +155,8 @@ class UI:
self.win.refresh() self.win.refresh()
def draw_status(self, actors): def draw_status(self, actors):
line = 1 for line, actor in enumerate(actors):
for actor in actors: self.status.addstr(line+1, 1, f"PLAYER AT {actor.x},{actor.y}")
self.status.addstr(line, 1, f"{actor.symbol} AT {actor.x},{actor.y}")
line += 1
def draw_actor(self, actor): def draw_actor(self, actor):
assert self.map.map[actor.y][actor.x] != '#', f"WHAT? actor at {actor.x},{actor.y} but that's a wall!" assert self.map.map[actor.y][actor.x] != '#', f"WHAT? actor at {actor.x},{actor.y} but that's a wall!"

@ -1,6 +1,7 @@
import curses import curses
import sys import sys
import random import random
import numpy as np
WALL = '#' WALL = '#'
SPACE = '.' SPACE = '.'
@ -48,11 +49,7 @@ class Map:
return grid return grid
def make_grid(self): def make_grid(self):
grid = [] return np.full((self.height, self.width), WALL, dtype=str)
for y in range(0, self.height):
grid.append([WALL] * self.width)
return grid
def make_room(self, grid, x, y, size): def make_room(self, grid, x, y, size):
for row in range(y, y+size): for row in range(y, y+size):
@ -136,10 +133,8 @@ class Map:
return self.map[target_y][target_x] == '#' return self.map[target_y][target_x] == '#'
def draw(self, win): def draw(self, win):
map_line = 0 for y, row in enumerate(self.map):
for line in self.map: win.addstr(y, 0, "".join(row))
win.addstr(map_line, 0, line)
map_line += 1
class UI: class UI:
def __init__(self, stdscr, height, width, status_height): def __init__(self, stdscr, height, width, status_height):
@ -182,10 +177,8 @@ class UI:
self.status_msg = msg self.status_msg = msg
def draw_status(self, actors): def draw_status(self, actors):
line = 1 for line, actor in enumerate(actors):
for actor in actors: self.status.addstr(line+1, 1, f"PLAYER AT {actor.x},{actor.y}")
self.status.addstr(line, 1, f"{actor.symbol} AT {actor.x},{actor.y}")
line += 1
self.status.addstr(1, self.width // 2, self.status_msg) self.status.addstr(1, self.width // 2, self.status_msg)
def draw_actor(self, actor): def draw_actor(self, actor):

@ -1,6 +1,7 @@
import curses import curses
import sys import sys
import random import random
import numpy as np
WALL = '#' WALL = '#'
SPACE = '.' SPACE = '.'
@ -48,11 +49,7 @@ class Map:
return grid return grid
def make_grid(self): def make_grid(self):
grid = [] return np.full((self.height, self.width), WALL, dtype=str)
for y in range(0, self.height):
grid.append([WALL] * self.width)
return grid
def make_room(self, grid, x, y, size): def make_room(self, grid, x, y, size):
for row in range(y, y+size): for row in range(y, y+size):
@ -136,10 +133,8 @@ class Map:
return self.map[target_y][target_x] == '#' return self.map[target_y][target_x] == '#'
def draw(self, win): def draw(self, win):
map_line = 0 for y, row in enumerate(self.map):
for line in self.map: win.addstr(y, 0, "".join(row))
win.addstr(map_line, 0, line)
map_line += 1
class UI: class UI:
def __init__(self, stdscr, height, width, status_height): def __init__(self, stdscr, height, width, status_height):

@ -56,11 +56,7 @@ class Map:
return grid return grid
def make_grid(self): def make_grid(self):
grid = [] return np.full((self.height, self.width), WALL, dtype=str)
for y in range(0, self.height):
grid.append([WALL] * self.width)
return grid
def make_room(self, grid, x, y, size): def make_room(self, grid, x, y, size):
for row in range(y, y+size): for row in range(y, y+size):
@ -141,10 +137,8 @@ class Map:
return self.map[target_y][target_x] == WALL return self.map[target_y][target_x] == WALL
def draw(self, win): def draw(self, win):
map_line = 0 for y, row in enumerate(self.map):
for line in self.map: win.addstr(y, 0, "".join(row))
win.addstr(map_line, 0, line)
map_line += 1
class UI: class UI:
def __init__(self, stdscr, height, width, status_height): def __init__(self, stdscr, height, width, status_height):

@ -1,6 +1,7 @@
import curses import curses
import sys import sys
import random import random
import numpy as np
WALL = '#' WALL = '#'
SPACE = '.' SPACE = '.'
@ -56,11 +57,7 @@ class Map:
return grid return grid
def make_grid(self): def make_grid(self):
grid = [] return np.full((self.height, self.width), WALL, dtype=str)
for y in range(0, self.height):
grid.append([WALL] * self.width)
return grid
def make_room(self, grid, x, y, size): def make_room(self, grid, x, y, size):
for row in range(y, y+size): for row in range(y, y+size):
@ -141,10 +138,8 @@ class Map:
return self.map[target_y][target_x] == WALL return self.map[target_y][target_x] == WALL
def draw(self, win): def draw(self, win):
map_line = 0 for y, row in enumerate(self.map):
for line in self.map: win.addstr(y, 0, "".join(row))
win.addstr(map_line, 0, line)
map_line += 1
class UI: class UI:
def __init__(self, stdscr, height, width, status_height): def __init__(self, stdscr, height, width, status_height):
@ -342,10 +337,7 @@ class GameEngine:
while True: while True:
# remember, first one has to be the player # remember, first one has to be the player
# the_map = self.map.map
# self.map.map = self.debug_paths()
self.ui.update(self.actors) self.ui.update(self.actors)
# self.map.map = the_map
new_x, new_y = self.ui.handle_input(self.player.x, self.player.y) new_x, new_y = self.ui.handle_input(self.player.x, self.player.y)
self.move_player(self.player, new_x, new_y) self.move_player(self.player, new_x, new_y)

Loading…
Cancel
Save