-
Notifications
You must be signed in to change notification settings - Fork 0
/
tetris_human.py
200 lines (183 loc) · 7.92 KB
/
tetris_human.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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
from tetris_model import *
class Tetris:
def __init__(self, screen):
self.screen = screen
self.top_left_x = 900
self.top_left_y = 90
font = pygame.font.SysFont('Arial', 40)
self.font_small = pygame.font.SysFont('Arial', 20)
self.label = font.render('Human Player', 1, (255, 255, 255))
self.label_held_piece = self.font_small.render('Held Piece', 1, (255, 255, 255))
self.label_next_piece = self.font_small.render('Next Piece', 1, (255, 255, 255))
self.locked_positions = {}
self.incoming_lines = 0
self.bag = get_shapes()
self.current_piece = self.bag.pop()
self.next_piece = self.bag.pop()
self.held_piece = []
self.combo = 0
self.switch_piece = True
self.change_piece = False
self.run = False
draw_title(self.screen, self.label, self.top_left_x)
# Swaps current piece and held piece or next piece
def get_held_piece(self):
if self.switch_piece:
if not self.held_piece:
self.held_piece = self.current_piece
self.current_piece = self.next_piece
self.next_piece = self.bag.pop()
if not self.bag:
self.bag = get_shapes()
else:
holder = self.held_piece
self.held_piece = self.current_piece
self.current_piece = holder
self.current_piece.y = self.held_piece.y
self.current_piece.x = self.held_piece.x
# Resets the game
def reset(self):
self.locked_positions = {}
self.incoming_lines = 0
self.combo = 0
self.bag = get_shapes()
self.current_piece = self.bag.pop()
self.next_piece = self.bag.pop()
self.held_piece = []
self.switch_piece = True
self.change_piece = False
self.run = False
# User controls
def controls(self, movement):
# Moves piece left
accepted_positions = self.locked_positions
if movement == 1:
self.current_piece.x -= 1
if not valid_space(self.current_piece, accepted_positions):
self.current_piece.x += 1
# Moves piece right
elif movement == 2:
self.current_piece.x += 1
if not valid_space(self.current_piece, accepted_positions):
self.current_piece.x -= 1
# Rotates piece and deals with wall kicks
elif movement == 3:
self.current_piece.rotation = self.current_piece.rotation + 1 % len(self.current_piece.shape)
if not valid_space(self.current_piece, accepted_positions):
self.current_piece.x -= 1
if not valid_space(self.current_piece, accepted_positions):
self.current_piece.x += 2
if not valid_space(self.current_piece, accepted_positions):
self.current_piece.x += -1
self.current_piece.rotation = self.current_piece.rotation - 1 % len(
self.current_piece.shape)
# Moves piece down 1
elif movement == 4:
self.current_piece.y += 1
if not valid_space(self.current_piece, accepted_positions):
self.current_piece.y -= 1
return True
# Moves piece until down while in a valid spot
elif movement == 5:
if valid_space(self.current_piece, accepted_positions):
while valid_space(self.current_piece, accepted_positions):
self.current_piece.y += 1
self.current_piece.y -= 1
else:
return True
elif movement == 6:
self.get_held_piece()
self.switch_piece = False
if not valid_space(self.current_piece, accepted_positions):
self.current_piece.x -= 1
if not valid_space(self.current_piece, accepted_positions):
self.current_piece.x += 2
if not valid_space(self.current_piece, accepted_positions):
self.current_piece.x += -1
if not valid_space(self.current_piece, accepted_positions):
self.current_piece.y -= 1
if not valid_space(self.current_piece, accepted_positions):
self.current_piece.y += 1
self.switch_piece = True
self.get_held_piece()
return False
# Draws and refreshes the screen
def draw_screen(self, grid):
area = pygame.Rect(self.top_left_x - 150, 75, 700, 625)
self.screen.fill((0, 0, 0), area)
draw_window(self.screen, self.top_left_x, grid, self.top_left_y)
draw_lines_sent(self.screen, self.top_left_x, self.top_left_y, self.incoming_lines)
draw_next_shape(self.next_piece, self.screen, self.top_left_x, self.label_next_piece, self.top_left_y)
draw_held_shape(self.held_piece, self.screen, self.top_left_x, self.label_held_piece, self.top_left_y)
# moves the piece down for over a time step
def piece_falling(self):
accepted_positions = self.locked_positions
self.current_piece.y += 1
if not (valid_space(self.current_piece, accepted_positions)) and self.current_piece.y > 0:
self.current_piece.y -= 1
return True
return False
# swaps a piece when a piece lands
def piece_landed(self):
self.switch_piece = True
shape_pos = convert_shape_format(self.current_piece)
for pos in shape_pos:
p = (pos[0], pos[1])
self.locked_positions[p] = self.current_piece.color
self.current_piece = self.next_piece
self.next_piece = self.bag.pop()
if not self.bag:
self.bag = get_shapes()
# returns number of lines outgoing
def lines_out(self, grid):
outgoing_lines = 0
outgoing_lines += clear_rows(grid, self.locked_positions)
# scoring system
if outgoing_lines > 0:
self.combo = (self.combo + 1)
else:
self.combo = 0
if self.combo > 1:
outgoing_lines = outgoing_lines
elif outgoing_lines > 0:
outgoing_lines = outgoing_lines - 1
# Adds a row and moves rows down
if self.incoming_lines > outgoing_lines:
self.incoming_lines = self.incoming_lines - outgoing_lines
elif self.incoming_lines == outgoing_lines:
self.incoming_lines = 0
outgoing_lines = 0
elif self.incoming_lines < outgoing_lines:
outgoing_lines = outgoing_lines - self.incoming_lines
while self.incoming_lines > 0:
self.incoming_lines = self.incoming_lines - 1
for j in range(10):
for i in range(20):
if (j, i) in self.locked_positions:
self.locked_positions[j, i - 1] = self.locked_positions[j, i]
del self.locked_positions[j, i]
lines_sent = random.sample(range(10), 9)
for r in lines_sent:
self.locked_positions[r, 19] = (169, 169, 169)
return outgoing_lines
def main(self, movement=0, lines=0):
landed = False
self.incoming_lines += lines
grid = create_grid(self.locked_positions)
score = 0
if movement == 0:
landed = self.piece_falling()
elif movement > 0:
landed = self.controls(movement)
shape_pos = convert_shape_format(self.current_piece)
for i in range(len(shape_pos)):
x, y = shape_pos[i]
if y > -1:
grid[y][x] = self.current_piece.color
if landed:
self.piece_landed()
score = self.lines_out(grid)
self.draw_screen(grid)
if check_lost(self.locked_positions):
self.run = True
return self.run, score