-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsnek_curse.py
171 lines (153 loc) · 4.96 KB
/
snek_curse.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
import curses as cs
import time
import threading
import copy
import random
# Direction const
D_RIGHT = 1
D_LEFT = 2
D_TOP = 3
D_DOWN = 4
# Draw const
DRAW_BG = 1
DRAW_WALLS = 2
DRAW_SNAKE = 3
DRAW_CHERRY = 4
BORDER_WIDTH = 70
BORDER_HEIGHT = 30
# Globals
direction = D_LEFT
game_over = False
class Cell:
def __init__(self, x, y, c):
self.x = x
self.y = y
self.repr = c
def __eq__(self, other):
if isinstance(other, Cell):
return self.x == other.x and self.y == other.y
else:
return NotImplemented
def __ne__(self, other):
res = self.__eq__(other)
if res == NotImplemented:
return res
else:
return not res
class Player:
def __init__(self):
self.dir = D_LEFT
self.cells = [Cell(40, 13, '@'), Cell(41, 13, '*'), Cell(42, 13, '*')]
self.head = self.cells[0]
self.score = 0
class Cherry:
def __init__(self):
self.pos = Cell(random.randint(1, BORDER_WIDTH),
random.randint(1, BORDER_HEIGHT), '$')
def game_loop(player, cherry, scr):
global game_over
# Player movement
player.dir = direction
dst_cell = copy.deepcopy(player.head)
dst_cell.repr = '*' # Restore non-head repr
if player.dir == D_RIGHT:
player.head.x = player.head.x + 1
elif player.dir == D_LEFT:
player.head.x = player.head.x - 1
elif player.dir == D_TOP:
player.head.y = player.head.y - 1
elif player.dir == D_DOWN:
player.head.y = player.head.y + 1
for n in range(1, len(player.cells)):
src_cell = copy.deepcopy(player.cells[n])
player.cells[n] = dst_cell
dst_cell = copy.deepcopy(src_cell)
# Player eats cherry, gets new cherry, adds new block to player's tail
if player.head.x == cherry.pos.x and player.head.y == cherry.pos.y:
cherry.pos.x = random.randint(1, BORDER_WIDTH - 4)
cherry.pos.y = random.randint(1, BORDER_HEIGHT - 5)
player.cells.append(dst_cell)
player.score = player.score + 10
# Game over checks
for n in range(1, len(player.cells)):
if player.head == player.cells[n]:
game_over = True
if player.head.x < 1 or player.head.x > BORDER_WIDTH - 2:
game_over = True
elif player.head.y < 1 or player.head.y > BORDER_HEIGHT - 1:
game_over = True
# Draw everything
draw(scr, player, cherry)
return
def get_input(scr):
global direction
global game_over
new_dir = direction
while True:
c = chr(scr.getch())
if c == 'w' and direction != D_DOWN:
new_dir = D_TOP
elif c == 's' and direction != D_TOP:
new_dir = D_DOWN
elif c == 'd' and direction != D_LEFT:
new_dir = D_RIGHT
elif c == 'a' and direction != D_RIGHT:
new_dir = D_LEFT
elif c == 'q':
game_over = True
direction = new_dir
return
def draw(scr, player, cherry):
scr.clear()
# Upper border
scr.addstr('#'*BORDER_WIDTH+'\n', cs.color_pair(DRAW_WALLS))
# Side borders
for i in range(1, BORDER_HEIGHT):
scr.addstr('#', cs.color_pair(DRAW_WALLS))
scr.addstr(' '*(BORDER_WIDTH-2), cs.color_pair(DRAW_BG))
scr.addstr('#\n', cs.color_pair(DRAW_WALLS))
# Lower border
scr.addstr('#'*BORDER_WIDTH+'\n', cs.color_pair(DRAW_WALLS))
# Player draw
for i in range(0, len(player.cells)):
c = player.cells[i]
if 0 < c.x < BORDER_WIDTH - 1\
and 0 < c.y < BORDER_HEIGHT:
scr.addch(c.y, c.x, c.repr, cs.color_pair(DRAW_SNAKE))
# Cherry draw
scr.addch(cherry.pos.y, cherry.pos.x,
cherry.pos.repr, cs.color_pair(DRAW_CHERRY))
# Score string
scr.addstr(BORDER_HEIGHT + 1, 0,
'Your score: {}\n'.format(player.score), cs.color_pair(0))
scr.refresh()
return
def main():
# Screen initializing
scr = cs.initscr()
cs.cbreak()
cs.noecho()
cs.start_color()
cs.init_pair(DRAW_BG, cs.COLOR_WHITE, cs.COLOR_WHITE)
cs.init_pair(DRAW_WALLS, cs.COLOR_RED, cs.COLOR_RED)
cs.init_pair(DRAW_SNAKE, cs.COLOR_CYAN, cs.COLOR_WHITE)
cs.init_pair(DRAW_CHERRY, cs.COLOR_GREEN, cs.COLOR_WHITE)
# Game initializing
player = Player()
cherry = Cherry()
input_thread = threading.Thread(target=get_input, daemon=True, args=(scr, ))
input_thread.start()
# Game loop starts here
while not game_over:
game_thread = threading.Thread(target=game_loop,
args=(player, cherry, scr, ))
game_thread.start()
time.sleep(0.2)
game_thread.join()
# Console to default state
scr.addstr('GAME OVER\n')
scr.refresh()
cs.endwin()
return
if __name__ == '__main__':
main()