Created
June 25, 2015 13:32
-
-
Save sbrl/284b45dc566516a9c11b to your computer and use it in GitHub Desktop.
A maze game written in Python
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
class _Getch: | |
"""Gets a single character from standard input. Does not echo to the | |
screen.""" | |
def __init__(self): | |
try: | |
self.impl = _GetchWindows() | |
except ImportError: | |
self.impl = _GetchUnix() | |
def __call__(self): return self.impl() | |
class _GetchUnix: | |
def __init__(self): | |
import tty, sys | |
def __call__(self): | |
import sys, tty, termios | |
fd = sys.stdin.fileno() | |
old_settings = termios.tcgetattr(fd) | |
try: | |
tty.setraw(sys.stdin.fileno()) | |
ch = sys.stdin.read(1) | |
finally: | |
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) | |
return ch | |
class _GetchWindows: | |
def __init__(self): | |
import msvcrt | |
def __call__(self): | |
import msvcrt | |
return msvcrt.getch() | |
getch = _Getch() |
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
""" | |
Notes | |
===== | |
Possible Directions | |
------------------- | |
- up | |
- down | |
- left | |
- right | |
""" | |
#imports | |
#core | |
from random import random, randint, shuffle, choice, randrange; | |
from math import floor; | |
#temporary | |
#import time; | |
registry = { | |
"player": "@", #the player | |
"unknown": "?", #an unknown tile | |
"wall": "#", #walls we can't go through | |
"space": " ", #spaces we can go through | |
"entrance": ":", #the entrance to the maze | |
"exit": "0", #the exit of the exit | |
"treasure-small": "*", #small amounts of treasure | |
"treasure-large": "=" #large amounts of treasure | |
}; | |
difficulties = { | |
"easy": 0.75, | |
"normal": 1, | |
"hard": 1.25, | |
"insane": 2 | |
}; | |
def space(width = 16, height = 8, ch = registry["wall"]): | |
area = []; | |
for y in range(height): | |
area.append([]); | |
for x in range(width): | |
area[y].append(ch); | |
x | |
return area; | |
def chooseremove(items): | |
# pick an item index | |
if items: | |
index = randrange( len(items) ) | |
return items.pop(index) | |
# nothing left! | |
return None | |
class coord: | |
def __init__(self, x = 1, y = 1): | |
self.x = x; | |
self.y = y; | |
#def to check a space for neighbours | |
def checkneighbors(area, cur): | |
neighbours = {"left": True, "right": True, "up": True, "down": True}; | |
if(cur.x > 2): | |
#we are not near the left edge | |
if(area[cur.y][cur.x - 2] == registry["wall"]): | |
#we can move left | |
neighbours["left"] = False; | |
if(cur.x < len(area[0]) - 3): | |
if(area[cur.y][cur.x + 2] == registry["wall"]): | |
#we can move right | |
neighbours["right"] = False; | |
if(cur.y > 2): | |
if(area[cur.y - 2][cur.x] == registry["wall"]): | |
#we can move up | |
neighbours["up"] = False; | |
if(cur.y < len(area) - 3): | |
if(area[cur.y + 2][cur.x] == registry["wall"]): | |
#we can move down | |
neighbours["down"] = False; | |
return neighbours; | |
#def to determine which sides can be moved to based on neighbour data from the def above | |
def getpossibleneighbours(neighbours): | |
possiblesides = []; | |
if(not neighbours["left"]): | |
possiblesides.append("left"); | |
if(not neighbours["right"]): | |
possiblesides.append("right"); | |
if(not neighbours["up"]): | |
possiblesides.append("up"); | |
if(not neighbours["down"]): | |
possiblesides.append("down"); | |
return possiblesides; | |
def maze(width = 17, height = 9): | |
#this maze generator works on odd numbers | |
if(width % 2 == 0): | |
width += 1; | |
if(height % 2 == 0): | |
height += 1; | |
area = space(width, height); #create an area to build the maze | |
area[1][1] = " "; #fill in the initial space | |
nodes = [coord(1, 1)]; #node to continue from | |
while True: | |
#break out of the loop if there are no more nodes to choose from | |
if(len(nodes) == 0): | |
break; | |
shuffle(nodes); #shuffle the bag of nodes | |
cur = chooseremove(nodes); #grab a random node from the bag | |
neighbours = checkneighbors(area, cur); #check which neighbouring spots are free | |
possiblesides = getpossibleneighbours(neighbours); #determine the possible sides that we could move to | |
#there are no posible sides that we can go to here, let's move on | |
if(len(possiblesides) == 0): | |
continue; | |
newside = choice(possiblesides); #choose a random side from the list of possible sides | |
#todo implement loops here | |
#add a new section to the maze based on which sides | |
if(newside == "left"): | |
area[cur.y][cur.x - 1] = " "; | |
area[cur.y][cur.x - 2] = " "; | |
nodes.append(coord(cur.x - 2, cur.y)); | |
elif(newside == "right"): | |
area[cur.y][cur.x + 1] = " "; | |
area[cur.y][cur.x + 2] = " "; | |
nodes.append(coord(cur.x + 2, cur.y)); | |
elif(newside == "up"): | |
area[cur.y - 1][cur.x] = " "; | |
area[cur.y - 2][cur.x] = " "; | |
nodes.append(coord(cur.x, cur.y - 2)); | |
elif(newside == "down"): | |
area[cur.y + 1][cur.x] = " "; | |
area[cur.y + 2][cur.x] = " "; | |
nodes.append(coord(cur.x, cur.y + 2)); | |
neighbours[newside] = True; | |
possiblesides = getpossibleneighbours(neighbours); #update the list of possible sides | |
if(len(possiblesides) > 0): | |
nodes.append(cur); | |
shuffle(nodes); #shuffle the nodes | |
return area; | |
#def to print a space to stdout | |
def printspace(area): | |
for row in area: | |
print("".join(row)); | |
def difftomult(diff = "normal"): | |
if(diff == "easy"): | |
return 0.75; | |
elif(diff == "normal"): | |
return 1; | |
elif(diff == "hard"): | |
return 1.25; | |
elif(diff == "insane"): | |
return 2; | |
def placestuff(maze, difficulty = "normal"): | |
print("Placing treasure...."); | |
diffmult = difftomult(difficulty); #convert the difficulty to a multiplier | |
treasurecount = 0; | |
#loop over every space | |
y = 0; | |
for row in maze: | |
x = 0; | |
for ch in row: | |
if(ch == registry["space"]): | |
#we have a space | |
#place treasure | |
chance = int(floor((1 / diffmult) * random() * 10)); | |
#print("stuffchance:", chance); | |
if(chance == 0): | |
treasurecount += 1; | |
#1 in 4 chance to place large treasure | |
if(randint(0, 4) == 0): | |
maze[y][x] = registry["treasure-large"]; | |
else: | |
maze[y][x] = registry["treasure-small"]; | |
x += 1; | |
y += 1; | |
print("Placed " + str(treasurecount) + " treasures"); | |
#def to place the entrance and exit in a maze | |
def placedoors(maze, firstfloor = False, lastexit = [1, 1]): | |
placements = {}; | |
if(firstfloor): | |
#we are on the first floor, the entrance should be a gap on the edge of the maze | |
#the space at (1, 1) is guaranteed to be a space because of the generation algorithm, so we can place the entrance there | |
maze[0][1] = registry["space"]; | |
#record this in the object placements dictionary | |
placements["firstfloor"] = True; | |
placements["entrance"] = [1, 0]; | |
else: | |
#we are not on the first floor, place the entrance in the same location as the exit on the previous floor | |
#todo check to see if there is a wall in the location that we have been told to place the entrance, and if so we should place it in the nearest free spot | |
#make sure that the entrance is on the screen | |
if(lastexit[0] > len(maze[0]) - 1): | |
lastexit[0] = len(maze[0]) - 1; | |
if(lastexit[1] > len(maze) - 1): | |
lastexit[1] = len(maze) - 1; | |
maze[lastexit[1]][lastexit[0]] = registry["entrance"]; | |
#make sure that the player can actually move when they start playing | |
if(lastexit[0] == len(maze[1]) - 1 and lastexit[1] == len(maze) - 1): | |
#we are in the bottom corner, add a space so the player can get out | |
maze[lastexit[1]][lastexit[0] - 1] = registry["space"]; | |
#record the entrance location in the placements dictionary | |
placements["firstfloor"] = False; | |
placements["entrance"] = lastexit; | |
while True: | |
exitloc = [randint(0, len(maze[0]) - 1), randint(0, len(maze) - 1)]; | |
#make sure that there is a space at the generated position | |
#print("w", len(maze[0]), "h", len(maze)); | |
#print(exitloc); | |
if(maze[exitloc[1]][exitloc[0]] != registry["space"]): | |
continue; | |
else: | |
maze[exitloc[1]][exitloc[0]] = registry["exit"]; #place the exit | |
placements["exit"] = exitloc; #record the exit's location | |
break; | |
return placements; #return the coordinates of the locations at which we placed the doors | |
#def to convert a difficulty into a viewsize - currently unused | |
def difftoviewsize(diff): | |
if(diff == "easy"): | |
return [9, 9]; | |
elif(diff == "normal"): | |
return [7, 7]; | |
elif(diff == "hard"): | |
return [5, 5]; | |
elif(diff == "insane"): | |
return [3, 3]; | |
else: | |
raise ValueError("Invalid difficulty " + diff); | |
#def to extract the view that a player will see from a maze, translating a difficulty into a view size | |
def playerview(maze, playerloc = (1, 0), diff = "normal"): | |
if(diff == "easy"): | |
return extractview(maze, playerloc, 9, 9); | |
elif(diff == "normal"): | |
return extractview(maze, playerloc, 7, 7); | |
elif(diff == "hard"): | |
return extractview(maze, playerloc, 5, 5); | |
elif(diff == "insane"): | |
return extractview(maze, playerloc, 3, 3); | |
else: | |
raise ValueError("Invalid difficulty " + diff); | |
#raw view extraction from mazes | |
def extractview(maze, playerloc = (1, 0), width = 3, height = 3): | |
view = space(width, height, registry["unknown"]); | |
xbounds = [playerloc[0] - ((width - 1) / 2), playerloc[0] + ((width - 1) / 2)]; | |
ybounds = [playerloc[1] - ((height - 1) / 2), playerloc[1] + ((height - 1) / 2)]; | |
#make sure that the bounds are within the maze | |
if(xbounds[0] < 0): | |
xbounds[0] = 0; | |
if(ybounds[0] < 0): | |
ybounds[0] = 0; | |
if(xbounds[1] > len(maze[0]) - 1): | |
xbounds[1] = len(maze[0]) - 1; | |
if(ybounds[1] > len(maze) - 1): | |
ybounds[1] = len(maze) - 1; | |
#print("xbounds", xbounds); | |
#print("ybounds", ybounds); | |
playerviewloc = (playerloc[0] - xbounds[0], playerloc[1] - ybounds[0]); | |
#print("Player in view at", playerviewloc); | |
#copy out a section of the maze to serve as the view | |
y = 0; | |
for row in maze: | |
x = 0; | |
for ch in row: | |
if(x >= xbounds[0] and x <= xbounds[1] and y >= ybounds[0] and y <= ybounds[1]): | |
#we are inside the view bounds | |
#print("adding char " + ch + " at abs (" + str(x) + ", " + str(y) + ")"); | |
view[int(y - ybounds[0])][int(x - xbounds[0])] = ch; | |
x += 1; | |
y += 1; | |
#place the player in the view | |
view[int(playerviewloc[1])][int(playerviewloc[0])] = registry["player"]; | |
return view; | |
#def to test the maze generator | |
def test(): | |
printspace(maze(40, 30)); | |
if __name__ == "__main__": | |
test(); |
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
#!/usr/bin/env python | |
import os, shlex, struct, platform, subprocess | |
def get_terminal_size(): | |
""" getTerminalSize() | |
- get width and height of console | |
- works on linux,os x,windows,cygwin(windows) | |
originally retrieved from: | |
http://stackoverflow.com/questions/566746/how-to-get-console-window-width-in-python | |
""" | |
current_os = platform.system() | |
tuple_xy = None | |
if current_os == 'Windows': | |
tuple_xy = _get_terminal_size_windows() | |
if tuple_xy is None: | |
tuple_xy = _get_terminal_size_tput() | |
# needed for window's python in cygwin's xterm! | |
if current_os in ['Linux', 'Darwin'] or current_os.startswith('CYGWIN'): | |
tuple_xy = _get_terminal_size_linux() | |
if tuple_xy is None: | |
print("default"); | |
tuple_xy = (80, 25) # default value | |
return tuple_xy | |
def _get_terminal_size_windows(): | |
try: | |
from ctypes import windll, create_string_buffer | |
# stdin handle is -10 | |
# stdout handle is -11 | |
# stderr handle is -12 | |
h = windll.kernel32.GetStdHandle(-12) | |
csbi = create_string_buffer(22) | |
res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi) | |
if res: | |
(bufx, bufy, curx, cury, wattr, | |
left, top, right, bottom, | |
maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw) | |
sizex = right - left + 1 | |
sizey = bottom - top + 1 | |
return sizex, sizey | |
except: | |
pass | |
def _get_terminal_size_tput(): | |
# get terminal width | |
# src: http://stackoverflow.com/questions/263890/how-do-i-find-the-width-height-of-a-terminal-window | |
try: | |
cols = int(subprocess.check_call(shlex.split('tput cols'))) | |
rows = int(subprocess.check_call(shlex.split('tput lines'))) | |
return (cols, rows) | |
except: | |
pass | |
def _get_terminal_size_linux(): | |
def ioctl_GWINSZ(fd): | |
try: | |
import fcntl | |
import termios | |
cr = struct.unpack('hh', | |
fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234')) | |
return cr | |
except: | |
pass | |
cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2) | |
if not cr: | |
try: | |
fd = os.open(os.ctermid(), os.O_RDONLY) | |
cr = ioctl_GWINSZ(fd) | |
os.close(fd) | |
except: | |
pass | |
if not cr: | |
try: | |
cr = (os.environ['LINES'], os.environ['COLUMNS']) | |
except: | |
return None | |
return int(cr[1]), int(cr[0]) | |
if __name__ == "__main__": | |
sizex, sizey = get_terminal_size() | |
print('width =', sizex, 'height =', sizey) |
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
########################################################################################## | |
#### _____ ___ _ ___ #### | |
#### |_ _|____ __ _____ _ _ / __|___ __| |___ | _ \__ _ _ _ ___ ___ _ _ #### | |
#### | |/ _ \ V V / -_) '_| | (__/ _ \/ _` / -_) | _/ _` | '_(_-</ -_) '_| #### | |
#### |_|\___/\_/\_/\___|_| \___\___/\__,_\___| |_| \__,_|_| /__/\___|_| #### | |
#### #### | |
########################################################################################## | |
""" | |
Examples | |
======== | |
name:The tower of mazes,difficulty:normal,seed:2345953|1*4x4,3*11x15 | |
""" | |
#imports | |
#temporary | |
from pprint import pprint; | |
#def to decode tower codes | |
def decode(str): | |
parts = str.split("|"); | |
metadata = {}; | |
for param in parts[0].split(","): | |
pparam = param.split(":"); | |
metadata[pparam[0]] = pparam[1]; | |
towerdata = {}; | |
towerdata["metadata"] = metadata; | |
towerdata["floors"] = []; | |
for floorcode in parts[1].split(","): | |
multiply = int(floorcode[0:floorcode.index("*")]); | |
floordata = {}; | |
floordata["partofsetof"] = multiply; | |
dimensions = floorcode[floorcode.index("*") + 1:].split("x"); | |
floordata["width"] = int(dimensions[0]); | |
floordata["height"] = int(dimensions[1]); | |
for i in range(multiply): | |
towerdata["floors"].append(floordata); | |
return towerdata; | |
#def to encode tower codes | |
def encode(towerdata): | |
towercode = ""; #set up a string to hold the towercode | |
#encode the metadata | |
towercode += "name:" + towerdata["metadata"]["name"] + ","; | |
try: | |
towercode += "seed:" + towerdata["metadata"]["seed"] + ","; | |
except KeyError: | |
print("Warning: No seed was specified, so the mazes will be random!"); | |
towercode = towercode[0:-1]; #remove the trailing comma | |
towercode += "|"; | |
#encode the floors | |
skip = 0; | |
for floor in towerdata["floors"]: | |
if(skip > 0): | |
skip -= 1; | |
continue; | |
towercode += str(floor["partofsetof"]) + "*" + str(floor["width"]) + "x" + str(floor["height"]) + ","; | |
skip = floor["partofsetof"] - 1; | |
towercode = towercode[0:-1]; #remove the trailing comma | |
return towercode; | |
if __name__ == "__main__": | |
print("Encoding"); | |
print("=-=-=-=-"); | |
print(encode(decode("name:The tower of mazes,seed:2345953|1*4x4, 3*11x15"))); | |
print(); | |
print("Decoding"); | |
print("=-=-=-=-"); | |
pprint(decode("name:The tower of mazes,difficulty:normal,seed:2345953|1*4x4, 3*11x15")); |
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
################################################################################################ | |
################################################################################################ | |
#### _____ _ __ __ ___ #### | |
#### |_ _|____ __ _____ _ _(_)_ _ __ _ | \/ |__ _ ______ / __|__ _ _ __ ___ #### | |
#### | |/ _ \ V V / -_) '_| | ' \/ _` | | |\/| / _` |_ / -_) | (_ / _` | ' \/ -_) #### | |
#### |_|\___/\_/\_/\___|_| |_|_||_\__, | |_| |_\__,_/__\___| \___\__,_|_|_|_\___| #### | |
#### |___/ #### | |
################################################################################################ | |
################################################################################################ | |
#imports | |
#core | |
import random; | |
from sys import exit, stdout; | |
from time import sleep; | |
from math import floor, ceil; | |
#other files | |
import maze, utils, towercode; | |
from getch import getch; #to use: getch(); #gets one char of input | |
#temporary | |
#from pprint import pprint; | |
#def to play a game of the towering maze game | |
def play(towerdata): | |
towerdata["metadata"]["totalfloors"] = len(towerdata["floors"]); #add the total number of floors to the tower's metadata | |
floor = 0; | |
#loop over all the floors in the towerdata we have been supplied | |
lastexit = [1, 0]; #the last exit's location | |
rawscore = 0; #the player's raw score, not includeing the movement bonus | |
score = 0; #the player's total score | |
moves = 0; #the number of moves that have beeen made | |
floornum = 0; | |
for floor in towerdata["floors"]: | |
#play the floor | |
flooresult = playfloor(floor, floornum, towerdata["metadata"], lastexit, towerdata["metadata"]["difficulty"], score, moves); | |
lastexit = flooresult["exitloc"]; #update the last exit location | |
score += flooresult["score"]; | |
rawscore += flooresult["rawscore"]; | |
moves += flooresult["moves"]; | |
floornum += 1; | |
print("\n\n\n\n"); | |
print("***** You reached the top of the tower! *****"); | |
print("Moves: " + str(moves)); | |
print("Difficulty Multiplier: " + str(maze.difftomult(towerdata["metadata"]["difficulty"]))); | |
score *= maze.difftomult(towerdata["metadata"]["difficulty"]); | |
print("Score: " + str(score)); | |
print("\n**** Press any key to continue ****"); | |
getch(); | |
return score; | |
#def to play a floor | |
def playfloor(floordata, floornum, towermetadata, lastexit = [1, 0], difficulty = "normal", totalscore = 0, totalmoves = 0): | |
#variable setup | |
score = 0; #the score the player has gained on this floor | |
moves = 0; #the number of moves the player has made on this floor | |
playerloc = lastexit; #the current location of the player | |
floormaze = maze.maze(floordata["width"], floordata["height"]); | |
maze.placestuff(floormaze, difficulty); | |
#determine whether we are on the first floor | |
if(floornum == 0): | |
firstfloor = True; | |
else: | |
firstfloor = False; | |
entexlocs = maze.placedoors(floormaze, firstfloor, lastexit); #place the entrance and exits and remember their locations | |
while True: | |
utils.clearterminal(); #clear the terminal | |
playerview = maze.playerview(floormaze, playerloc, difficulty); #extract the view that the player will see | |
if(difficulty != "insane" and difficulty != "hard"): | |
playerlocdisp = "(" + str(int(playerloc[0])) + ", " + str(int(playerloc[1])) + ")"; | |
else: | |
playerlocdisp = "(?, ?)"; #mask the location on insane difficulty | |
#print the heading | |
print("+" + "="*44 + "+"); | |
print("|" + towermetadata["name"].center(44) + "|"); | |
print("+" + "="*23 + "+" + "="*20 + "+"); | |
#prepare the sidebar | |
sidebar = []; | |
sidebar.append((" On floor " + str(floornum) + " / " + str(towermetadata["totalfloors"])).ljust(20) + "|"); | |
sidebar.append((" at " + playerlocdisp).ljust(20) + "|"); | |
sidebar.append("-"*20 + "+"); | |
sidebar.append(" This Floor".ljust(20) + "|"); | |
sidebar.append("-"*7 + "+" + "-"*12 + "+"); | |
sidebar.append(" Score | " + str(int(score)).ljust(11) + "|"); | |
sidebar.append(" Moves | " + str(int(moves)).ljust(11) + "|"); | |
sidebar.append("-"*7 + "+" + "-"*12 + "+"); | |
sidebar.append(" Overall".ljust(20) + "|"); | |
sidebar.append("-"*7 + "+" + "-"*12 + "+"); | |
sidebar.append(" Score | " + str(int(totalscore + score)).ljust(11) + "|"); | |
sidebar.append(" Moves | " + str(int(totalmoves + moves)).ljust(11) + "|"); | |
#prepare the player's view | |
pviewdisp = []; | |
if(len(playerview) < 12): | |
lendiff = 12 - len(playerview); | |
toprowsneeded = floor(lendiff / 2); | |
for i in range(toprowsneeded): | |
pviewdisp.append("|" + " "*23 + "|"); | |
for row in playerview: | |
pviewdisp.append("|" + "".join(row).center(23) + "|"); | |
if(len(playerview) < 12): | |
lendiff = 12 - len(playerview); | |
toprowsneeded = ceil(lendiff / 2); | |
for i in range(toprowsneeded): | |
pviewdisp.append("|" + " "*23 + "|"); | |
#add plus signs at table intersections | |
pviewdisp[2] = pviewdisp[2][0:-1] + "+"; | |
pviewdisp[4] = pviewdisp[4][0:-1] + "+"; | |
pviewdisp[7] = pviewdisp[7][0:-1] + "+"; | |
pviewdisp[9] = pviewdisp[9][0:-1] + "+"; | |
#display the interface | |
for sides in zip(pviewdisp, sidebar): | |
print("".join(sides)); | |
print("+" + "-"*23 + "+" + "-"*20 + "+"); | |
#(new tui) | |
#+========================================+ | |
#| The Tower of Mazes | | |
#+=======================+================+ | |
#| | On floor 3 / 5 | | |
#| | at (3, 1) | | |
#| #####?? +----------------+ | |
#| # 0@#?? | This Floor | | |
#| ### #?? +-------+--------+ | |
#| # #?? | Score | 50 | | |
#| ### :?? | Moves | 29 | | |
#| ??????? +----------------+ | |
#| ??????? | Overall | | |
#| +----------------+ | |
#| | Score | 1050 | | |
#| | Moves | 329 | | |
#+-----------------------+----------------+ | |
#print("+-" + ("-" * 30) + "-+"); | |
#print("| " + floornumdisp.ljust(30) + " |"); | |
#print("+-" + ("-" * 30) + "-+"); | |
#print("| " + ("Score: ".ljust(15) + str(score).ljust(15)) + " |"); | |
#print("+-" + ("-" * 30) + "-+"); | |
#print("| " + ("Moves: ".ljust(15) + str(moves).ljust(15)) + " |"); | |
#print("+-" + ("-" * 30) + "-+"); | |
#print("| " + ("Location: ".ljust(15) + ("(" + str(playerloc[0]) + ", " + str(playerloc[1]) + ")").ljust(15)) + " |"); | |
#print("+-" + ("-" * 30) + "-+\n"); | |
#maze.printspace(playerview); #display the maze | |
ch1 = getch(); #get a character of input from the user | |
if(ch1 == b'\xe0' or ch1 == "\x1b"): | |
#if the first chracter is "\x1b", there will be an extra "[" character next - this needs picking up so it doesn't break the rest of the script | |
if(ch1 == "\x1b"): | |
ch1b = getch(); | |
#we have an escaped character, get more input | |
ch2 = getch(); | |
#todo make the arrow keys actually do something | |
#todo make sure that the player can't crash the game by moving out of the playing area on the first floor | |
#todo make sure that the player can't go through walls | |
if(ch2 == b'H' or ch2 == "A"): | |
#the up arrow key was pressed | |
if(playerloc[1] > 0): | |
if(floormaze[playerloc[1] - 1][playerloc[0]] != maze.registry["wall"]): | |
#the new space is not a wall :D Move the player. | |
playerloc[1] -= 1; | |
moves += 1; #increment the number of moves the player has made | |
elif(ch2 == b'P' or ch2 == "B"): | |
#the down arrow key was pressed | |
if(playerloc[1] < len(floormaze) - 1): | |
if(floormaze[playerloc[1] + 1][playerloc[0]] != maze.registry["wall"]): | |
#the new space is not a wall :D Move the player. | |
playerloc[1] += 1; | |
moves += 1; #increment the number of moves the player has made | |
elif(ch2 == b'K' or ch2 == "D"): | |
#the left arrow key was pressed | |
if(playerloc[0] > 0): | |
if(floormaze[playerloc[1]][playerloc[0] - 1] != maze.registry["wall"]): | |
#the new space is not a wall :D Move the player. | |
playerloc[0] -= 1; | |
moves += 1; #increment the number of moves the player has made | |
elif(ch2 == b'M' or ch2 == "C"): | |
#the right arrow key was pressed | |
if(playerloc[0] < len(floormaze[0]) - 1): | |
if(floormaze[playerloc[1]][playerloc[0] + 1] != maze.registry["wall"]): | |
#the new space is not a wall :D Move the player. | |
playerloc[0] += 1; | |
moves += 1; #increment the number of moves the player has made | |
elif(ch1 == b'\x03' or ch1 == "\x03"): | |
print("Press CTRL + C again to quit, or any other key to cancel."); | |
ch2 = getch(); | |
if(ch2 == b'\x03'): | |
print("Exiting"); | |
exit(); | |
if(floormaze[playerloc[1]][playerloc[0]] == maze.registry["exit"]): | |
#calculate the bonus score gained through completing the floor in a low number of moves | |
#we add one here since we exit the loop early | |
#todo tweak this algorithm based on playtesting | |
movementscore = (1 / (moves + 1)) * floordata["width"] * floordata["height"] * 50; | |
print("-----------------------------"); | |
print("---- Floor complete! ----"); | |
print("-----------------------------"); | |
print("**** Floor Results ****"); | |
print("Moves: " + str(moves + 1) + "\n"); #we add one to the number of moves since we exit the loop early | |
print("Score: " + str(score)); | |
print("Movement bonus: " + str(movementscore)); | |
print("----"); | |
print("Total floor score: " + str(score + movementscore)); | |
print("\n\nPress any key to continue..."); | |
ch = getch(); | |
break; | |
elif(floormaze[playerloc[1]][playerloc[0]] == maze.registry["treasure-small"]): | |
#we have found a little bit of treasure! Add to the score and remove the treasure. | |
floormaze[playerloc[1]][playerloc[0]] = maze.registry["space"]; | |
score += 50; | |
elif(floormaze[playerloc[1]][playerloc[0]] == maze.registry["treasure-large"]): | |
#we have found a little bit of treasure! Add to the score and remove the treasure. | |
floormaze[playerloc[1]][playerloc[0]] = maze.registry["space"]; | |
score += 250; | |
return { | |
"exitloc": entexlocs["exit"], | |
"rawscore": score, | |
"score": score + movementscore, | |
"moves": moves | |
}; | |
stdout.write(""" _____ _ __ __ ___ | |
|_ _|____ __ _____ _ _(_)_ _ __ _ | \/ |__ _ ______ / __|__ _ _ __ ___ | |
| |/ _ \ V V / -_) '_| | ' \/ _` | | |\/| / _` |_ / -_) | (_ / _` | ' \/ -_) | |
|_|\___/\_/\_/\___|_| |_|_||_\__, | |_| |_\__,_/__\___| \___\__,_|_|_|_\___| | |
|___/ v0.3dev b7, The name is temporary | |
******** Press any key ********\r"""); | |
getch(); | |
for i in range(10): | |
if(i % 2 == 1): | |
print("|---| |---| |---| |---| |---| |---| |---| |---|"); | |
else: | |
print("| | | | | | | | | | | | | | | |"); | |
sleep(random.random() * 0.1); | |
while True: | |
print(""" | |
+=============================+ | |
| Main Menu | | |
+=============================+ | |
| 0: Help | | |
| 1: Load tower | | |
| | | |
| 2: Play the example tower | | |
| | | |
| 3: Changelog | | |
| 4: Exit | | |
+-----------------------------+ | |
| (Press a number) | | |
+-----------------------------+ | |
"""); | |
ch = getch(); #get a charcter of input | |
if(ch == b'0' or ch == "0"): | |
#the player wants help | |
print("\n\n\n\n"); | |
print(utils.file_get_contents("help.txt")); | |
print("Press any key to continue...."); | |
ch2 = getch(); | |
elif(ch == b'1' or ch == "1"): | |
#the player wants to play | |
print("\n\n\n\n"); | |
towerdata = towercode.decode(utils.getinput("Enter tower code: ")); #get and decode a tower code | |
#set the seed if it is specified | |
if "seed" in towerdata["metadata"]: | |
random.seed(towerdata["metadata"]["seed"]); | |
play(towerdata); #play the game | |
elif(ch == b'2' or ch == "2"): | |
#the player wants to play the example tower | |
print("\n\n\n\n"); | |
towerdata = towercode.decode("name:The tower of mazes,difficulty:normal,seed:2345953|1*4x4,3*11x15,1*5x5"); | |
#set the seed if it is specified | |
if "seed" in towerdata["metadata"]: | |
random.seed(towerdata["metadata"]["seed"]); | |
play(towerdata); | |
elif(ch == b'3' or ch == "3"): | |
#the player wants the changelog | |
print(utils.file_get_contents("changelog.log")); | |
print("Press any key to continue...."); | |
ch2 = getch(); | |
if(ch == b'\x03' or ch == "\x03" or ch == "4" or ch == b'4'): | |
#CTRL + C | |
print("Exiting"); | |
exit(); |
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
#imports | |
#other files | |
from terminalsize import get_terminal_size; | |
#function to get input from the user - guarantees that the user will enter at least 1 character. | |
def getinput(prompt = ">", minchars = 1): | |
while True: | |
inputstr = input(prompt); | |
if(len(inputstr) >= minchars): | |
return inputstr; | |
#function to get a yes / no input | |
def confirm(prompt = "Are you sure?"): | |
while True: | |
response = getinput(prompt).lower(); #get the input and convert it to lower case | |
if(response == "" or response == "y" or response == "ye" or response == "yes"): | |
#the user answered yes | |
return True; | |
elif(response == "n" or response == "no"): | |
#the user answered no | |
return False; | |
#temporary def to output a bunch of blank lines to clear the terminal while we figure out how to move the cursor upwards | |
def clearterminal(): | |
tsize = get_terminal_size(); | |
print("\n" * tsize[1]); | |
#def to get the contents of a file | |
def file_get_contents(filename): | |
with open(filename) as f: | |
return f.read() |
How to play, please help.
Oh wow, this some old stuff I've written here.
@aniruddha-ingle: Sorry I didn't see your comment there!
@IronManRox228228: I would assume that you would download the contents of this gist, and then do python towermazegame.py
.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How do you play this game?