-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprototype_gridrunner.py
171 lines (140 loc) · 5.08 KB
/
prototype_gridrunner.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# BEGIN OUTLINE
"""
Interactively navigating grids in console.
NOTICE Unfinished.
"""
# END OUTLINE
# BEGIN IMPORTS
import curses
# END IMPORTS
# BEGIN CONSTANTS
# No constants
# END CONSTANTS
# BEGIN DECORATORS
# No decorators
# END DECORATORS
# BEGIN CLASSES
class Gridrunner:
"""Grid representation to store and navigate a grid."""
def __init__(self, grid):
self._grid = grid
self._player_coordinates = (1, 1)
#self._goal_coordinates = (-2, -2)
#self._entities = []
self._won = False
@property
def won(self):
"""Whether round is 'won'."""
return self._won
def run(self):
"""Run the `curses` in-console grid navigator."""
#try:
#stdscr = curses.initscr()
#curses.cbreak()
#curses.noecho()
#stdscr.keypad(True)
#curses.curs_set(False)
#self._run(stdscr)
#finally:
#curses.nocbreak()
#curses.echo()
#stdscr.keypad(False)
#curses.curs_set(True)
#curses.endwin()
curses.wrapper(self._run) # Wraps the actual main runner so cleanup is done nicely
return
def _run(self, stdscr):
"""Navigate the maze given a curses window `stdscr`.
Navigate with wasd or arrow keys.
Use WASD (wasd + shift) to long jump within grid.
"""
# Curses initialization
curses.curs_set(False) # Invisible cursor
stdscr.timeout(100) # How long to wait for input before continuing
#curses.init_pair(1,curses.COLOR_BLACK,curses.COLOR_WHITE) # Make palette
#stdscr.bkgd(' ',curses.color_pair(1)) # Use palette
# State initialization
(CH, CW) = stdscr.getmaxyx() # Console Height, Width
CH -= 1 # (I don't wanna deal with bottom right corner curses 'bug')
grid = self._grid
(gridH, gridW) = len(grid), len(grid[0]) # Grid dimensions
(screenH, screenW) = CH, CW//2 # Grid cells allowed on screen
(marginH, marginW) = screenH//3, screenW//3 # View padding for player cam
# Helper functions
def wall_at(y, x):
return not(0<=y<gridH and 0<=x<gridW) or grid[y][x] == 1
# Store Initial
(camx, camy) = (0, 0) # Top left camera position
(x, y) = self._player_coordinates # Player position
# Main loop
while True:
# Get inputs
try: key = stdscr.getkey()
except curses.error: key = ''
if key == '\x1b': # Escape
break
# Do player movement calculations
longjmp = (key in "DWAS") # Jump to wall?
while True:
if (key in ['d','D','KEY_RIGHT'] and not wall_at(y,x+1)):
(y,x) = (y, x+1)
elif (key in ['w','W','KEY_UP'] and not wall_at(y-1,x)):
(y,x) = (y-1, x)
elif (key in ['a','A','KEY_LEFT'] and not wall_at(y,x-1)):
(y,x) = (y, x-1)
elif (key in ['s','S','KEY_DOWN'] and not wall_at(y+1,x)):
(y,x) = (y+1, x)
else:
break
if not longjmp:
break
# Test for win condition
if x >= gridW-1 or y >= gridH-1: # Hack: win if outside grid
self._won = True
break
# Update camera position
if x < camx+marginW and 0 < camx: camx -= 1
elif camx+screenW-marginW < x and camx+screenW < gridW: camx += 1
if y < camy+marginH and 0 < camy: camy -= 1
elif camy+screenH-marginH < y and camy+screenH < gridH: camy += 1
# Update screen
# Draw grid
to_str = lambda i: '▒▒' if i==1 else ' ' # ░▒▓█
for i in range(min(screenH,gridH)):
stdscr.addstr(i,0, ''.join(to_str(b) for b in grid[i+camy][camx:camx+screenW]))
# Draw player
if 0<=y-camy<screenH and 0<=x-camx<screenW:
stdscr.addstr((y-camy),(x-camx)*2, '██')
# Draw debug
#stdscr.addstr(0,0,f"{x,y =} {camx,camy =}")
return
# END CLASSES
# BEGIN FUNCTIONS
# No functions
# END FUNCTIONS
# BEGIN MAIN
def main():
# Make maze grid
from mazing import Maze, ALGORITHMS
maze = Maze(32,32)
maze.division(
roomlength=float('inf'),
nest_algorithms=[
ALGORITHMS['clear'],
ALGORITHMS['backtracker'],
ALGORITHMS['division'],
],
)
#maze.clear() # Debug
maze.make_braided(probability=0.1) # Make easier for player
maze.node_at( 0, 0)._edges |= 0b0010 # Hack top entrance
maze.node_at(-1,-1)._edges |= 0b1000 # Hack bottom exit
grid = maze.generate_raster(decolumnated=True)
# Make and run main grid navigator
gridrunner = Gridrunner(grid)
gridrunner.run()
# End of game
print("G.G. W.P." if gridrunner.won else "F")
return
if __name__=="__main__": main()
# END MAIN