Skip to content

Commit

Permalink
Procedurally-generated map and a smidge of color
Browse files Browse the repository at this point in the history
  • Loading branch information
seansawyer committed Oct 10, 2019
1 parent 12bf119 commit b8ba772
Showing 1 changed file with 74 additions and 38 deletions.
112 changes: 74 additions & 38 deletions pmrl.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,59 +9,80 @@ class Coordinates(NamedTuple):
x: int
y: int

map_s = [
'##########',
'#........#',
'#........#',
'#........#',
'#........#',
'#........#',
'#........#',
'#........#',
'#........#',
'##########',
]
map = [list(r) for r in map_s]
map_width = len(map[0])
map_height = len(map)
screen_width = 80
screen_height = 50
map_width = screen_width
map_height = screen_height - 2

def generate_map():
# start with all walls
map_tiles = [['#'] * map_width for y in range(map_height)]
# choose a random starting point
x = random.randint(1, map_width - 2)
y = random.randint(1, map_height - 2)
# walk in a random direction
possible_moves = [
(0, -1), # up
(0, 1), # down
(-1, 0), # left
(1, 0), # right
]
map_tiles[y][x] = '.'
for i in range(10000):
choice = random.randint(0, len(possible_moves) - 1)
dx, dy = possible_moves[choice]
if 0 < x + dx < map_width - 2 and 0 < y + dy < map_height - 2:
x = x + dx
y = y + dy
map_tiles[y][x] = '.'
return map_tiles


def is_mob(coords: Coordinates, mobs_coords: List[Coordinates]):
return coords in mobs_coords

def is_wall(coords: Coordinates, map_coords: Coordinates):
def is_wall(coords: Coordinates, map_tiles: List[List[str]]):
# Is it even in the map?
if not map_coords.x <= coords.x < map_coords.x + map_width:
if not 0 <= coords.x < map_width:
return True
if not map_coords.y <= coords.y < map_coords.y + map_height:
if not 0 <= coords.y < map_height:
return True
# Is it a wall tile?
tile = map[coords.y][coords.x]
tile = map_tiles[coords.y][coords.x]
return tile == '#'

def draw_status(
map_coords: Coordinates,
status_y: Coordinates,
player_hp: int
):
msg = f'HP: {player_hp:2}'
libtcod.console_print(0, 0, map_coords.y + map_height, msg)
libtcod.console_set_default_foreground(0, libtcod.blue)
libtcod.console_print(0, 0, status_y, msg)
libtcod.console_set_default_foreground(0, libtcod.white)

def draw_map(
map_coords: Coordinates,
map_tiles: List[List[str]],
exit_coords: Coordinates,
player_coords: Coordinates,
mobs_coords: List[Coordinates]
):
y = map_coords.y
for row in map:
x = map_coords.x
y = 0
for row in map_tiles:
x = 0
for tile in row:
color = libtcod.white
if x == player_coords.x and y == player_coords.y:
tile = '@'
color = libtcod.yellow
elif Coordinates(x, y) in mobs_coords:
tile = 'o'
color = libtcod.red
elif x == exit_coords.x and y == exit_coords.y:
tile = '<'
color = libtcod.green
libtcod.console_set_default_foreground(0, color)
libtcod.console_put_char(0, x, y, tile, libtcod.BKGND_NONE)
libtcod.console_set_default_foreground(0, libtcod.white)
x += 1
y += 1

Expand All @@ -84,22 +105,35 @@ def keypress_to_command(key: libtcod.Key):
return key_char_command_map.get(chr(key.c), {})
return key_vk_command_map.get(key.vk, {})

def choose_random_open_tile(map_tiles: List[List[str]], occupied_coords: List[Coordinates]):
coords = None
tile = '#'
while tile != '.' and coords not in occupied_coords:
x = random.randint(1, map_width - 2)
y = random.randint(1, map_height - 2)
tile = map_tiles[y][x]
coords = Coordinates(x, y)
occupied_coords.append(coords)
return coords

def main():
screen_width = map_width
screen_height = map_height + 2
map_coords = Coordinates(0, 0)
exit_coords = Coordinates(8, 8)
map_tiles = generate_map()
# pick a random tile to place the exit
occupied_coords = []
exit_coords = choose_random_open_tile(map_tiles, occupied_coords)
mobs_coords = [
Coordinates(3, 4),
Coordinates(6, 5),
Coordinates(2, 7),
choose_random_open_tile(map_tiles, occupied_coords),
choose_random_open_tile(map_tiles, occupied_coords),
choose_random_open_tile(map_tiles, occupied_coords),
]
mobs_hp = [
5,
4,
3,
]
player_coords = Coordinates(1, 1)
# pick a random tile to place the player
tile = '#'
player_coords = choose_random_open_tile(map_tiles, occupied_coords)
player_hp = 10
libtcod.console_set_custom_font('arial10x10.png', libtcod.FONT_TYPE_GRAYSCALE | libtcod.FONT_LAYOUT_TCOD)
libtcod.console_init_root(screen_width, screen_height, 'pmrl', False)
Expand All @@ -115,13 +149,15 @@ def main():
libtcod.sys_check_for_event(libtcod.EVENT_KEY_PRESS, key, mouse)
libtcod.console_set_default_foreground(0, libtcod.white)
# update the screen
draw_map(map_coords, exit_coords, player_coords, mobs_coords)
draw_status(map_coords, player_hp)
draw_map(map_tiles, exit_coords, player_coords, mobs_coords)
draw_status(map_height, player_hp)
libtcod.console_flush()
# endgame sequence
if dying or winning:
msg_y = map_coords.y + map_height + 1
msg_y = map_height + 1
msg = 'You win!' if winning else 'You die.'
color = libtcod.green if winning else libtcod.red
libtcod.console_set_default_foreground(0, color)
libtcod.console_print(0, 0, msg_y, msg)
libtcod.console_flush()
running = False
Expand Down Expand Up @@ -154,7 +190,7 @@ def main():
mobs_hp[mob_i] -= 1
if mobs_hp[mob_i] == 0:
dead_mobs.add(mob_i)
elif not is_wall(new_mob_coords, map_coords):
elif not is_wall(new_mob_coords, map_tiles):
# check if it's another mob
try:
is_other_mob = mob_i == mobs_coords.index(new_mob_coords)
Expand All @@ -173,7 +209,7 @@ def main():
try:
mob_i = mobs_coords.index(new_player_coords)
except ValueError:
if not is_wall(new_player_coords, map_coords):
if not is_wall(new_player_coords, map_tiles):
player_coords = new_player_coords
else:
player_hp -= 1
Expand Down

0 comments on commit b8ba772

Please sign in to comment.