def __init__(self): self.grid = [] self.mixer = Mixer() self.stats = Statistics() self.curr_piece = random_piece() self.next_piece = random_piece() self.fall_speed = 30 self.time_to_drop = self.fall_speed self.running = False
class Tetris(object): def __init__(self): self.grid = [] self.mixer = Mixer() self.stats = Statistics() self.curr_piece = random_piece() self.next_piece = random_piece() self.fall_speed = 30 self.time_to_drop = self.fall_speed self.running = False def process_key_events(self, keys): if K_LEFT in keys: self.lateral_piece_move(-1) elif K_RIGHT in keys: self.lateral_piece_move(1) elif K_DOWN in keys: self.drop_piece() elif K_UP in keys: self.rotate_piece(1) def update(self): # Countdown to current piece drop self.time_to_drop -= 1 if self.time_to_drop < 0: self.time_to_drop = self.fall_speed self.drop_piece(1) def render(self, gfx, gallery): gfx.blit(gallery.background, (0, 0)) self.stats.render(gfx) # Render grid blocks for x in xrange(GridSize.width): for y in xrange(GridSize.height): if self.grid[x][y] > 0: gallery.render_block(gfx, self.stats.level, self.grid[x][y] - 1, Point(x, y)) elif self.grid[x][y] < 0: gallery.render_ghost(gfx, (self.grid[x][y] * -1) - 1, Point(x, y)) # Render next blocks for y in xrange(len(self.next_piece.grid)): for x in xrange(len(self.next_piece.grid[y])): if self.next_piece.grid[y][x]: pt = Point(x - self.next_piece.origin.x, y - self.next_piece.origin.y) gallery.render_next(gfx, self.stats.level, self.next_piece.grid[y][x] - 1, self.next_piece.size, pt) # Translate piece by delta def lateral_piece_move(self, dx): self.clear_grid_piece(self.curr_piece) self.curr_piece.pos.x += dx if not self.valid_move(self.curr_piece): self.curr_piece.pos.x -= dx else: self.mixer.lateral.play() self.set_grid_piece(self.curr_piece) # Rotate piece by delta def rotate_piece(self, dr): self.clear_grid_piece(self.curr_piece) if dr < 0: self.curr_piece.rotate_left() if not self.valid_move(self.curr_piece): self.curr_piece.rotate_right() else: self.mixer.rotate.play() elif dr > 0: self.curr_piece.rotate_right() if not self.valid_move(self.curr_piece): self.curr_piece.rotate_left() else: self.mixer.rotate.play() self.set_grid_piece(self.curr_piece) # Drop piece to the bottom def drop_piece(self, incr=GridSize.height): self.clear_grid_piece(self.curr_piece) # Find grid bottom place = False for i in range(incr): self.curr_piece.pos.y += 1 if not self.valid_move(self.curr_piece): self.curr_piece.pos.y -= 1 place = True break self.set_grid_piece(self.curr_piece) if place: if self.curr_piece.pos.y + self.curr_piece.origin.x <= 0: self.end_game() else: self.place_piece(self.curr_piece) # Place piece at grid bottom def place_piece(self, piece): # Find cleared rows cleared = [] for y in xrange(GridSize.height): if (len([x for x in xrange(GridSize.width) if self.grid[x][y]]) == GridSize.width): cleared.append(y) # Clear rows & shift down remains. if cleared: for row in cleared: for x in xrange(GridSize.width): self.grid[x][row] = 0 for row in cleared: self.shift_row_down(row) # Update statistics. self.mixer.play_dropped(len(cleared)) if self.stats.update(len(cleared)): self.mixer.level_up.play() self.update_speed() self.new_piece() def update_speed(self): if self.fall_speed >= 2: if self.fall_speed < 5: self.fall_speed -= 1 elif self.fall_speed < 10: self.fall_speed -= 2 else: self.fall_speed -= 3 # Shift above rows down from cleared row. def shift_row_down(self, row): for x in xrange(GridSize.width): for y in reversed(xrange(row)): self.grid[x][y + 1] = self.grid[x][y] self.grid[x][y] = 0 # Set piece values into grid. def set_grid_piece(self, piece): # Find and set piece ghost grid points yorig = piece.pos.y for y in xrange(GridSize.height - piece.pos.y): piece.pos.y += 1 if not self.valid_move(piece): piece.pos.y -= 1 break for y in xrange(len(piece.grid)): for x in xrange(len(piece.grid[y])): if piece.grid[y][x]: self.grid[piece.pos.x + x][piece.pos.y + y] = (piece.grid[y][x] * -1) # Set grid values for piece. piece.pos.y = yorig for y in xrange(len(piece.grid)): for x in xrange(len(piece.grid[y])): if piece.grid[y][x] and piece.pos.y + y >= 0: self.grid[piece.pos.x + x][piece.pos.y + y] = piece.grid[y][x] # Remove piece values from grid. def clear_grid_piece(self, piece): # Clear ghost grid points. for x in xrange(GridSize.width): for y in xrange(GridSize.height): if self.grid[x][y] < 0: self.grid[x][y] = 0 # Clear piece grid points. for y in xrange(len(piece.grid)): for x in xrange(len(piece.grid[y])): if piece.grid[y][x] and piece.pos.y + y >= 0: self.grid[piece.pos.x + x][piece.pos.y + y] = 0 # Check if piece can be moved to new location def valid_move(self, piece): for y in xrange(len(piece.grid)): for x in xrange(len(piece.grid[y])): pt = Point(piece.pos.x + x, piece.pos.y + y) if piece.grid[y][x] and pt.y >= 0: if pt.x < 0 or pt.x >= GridSize.width or pt.y >= GridSize.height: return False if self.grid[pt.x][pt.y]: return False return True def new_piece(self): self.curr_piece = self.next_piece self.next_piece = random_piece() if not self.valid_move(self.curr_piece): self.end_game() self.set_grid_piece(self.curr_piece) def new_game(self): self.grid = [[0 for y in xrange(GridSize.height)] for x in xrange(GridSize.width)] self.stats = Statistics() self.new_piece() self.mixer.start.play() self.mixer.loop_music() self.fall_speed = 30 self.time_to_drop = self.fall_speed self.running = True def end_game(self): self.mixer.game_over.play() self.running = False def game_over(self): return not self.running
class Tetris(object): def __init__(self): self.grid = [] self.mixer = Mixer() self.stats = Statistics() self.next_piece = random_piece() self.fall_speed = 30 self.time_to_drop = self.fall_speed self.running = False self.place = place def process_key_events(self, keys): if K_LEFT in keys: self.lateral_piece_move(-1) elif K_RIGHT in keys: self.lateral_piece_move(1) elif K_DOWN in keys: self.drop_piece() elif K_UP in keys: self.rotate_piece(1) def update(self): # Countdown to current piece drop self.time_to_drop -= 1 if self.time_to_drop < 0: self.drop_piece() #self.place(self) self.time_to_drop = self.fall_speed self.drop_piece(1) def render(self, gfx, gallery): gfx.blit(gallery.background, (0, 0)) self.stats.render(gfx) # Render grid blocks for x in xrange(GridSize.width): for y in xrange(GridSize.height): if self.grid[x][y] > 0: gallery.render_block(gfx, self.stats.level, self.grid[x][y] - 1, Point(x, y)) elif self.grid[x][y] < 0: gallery.render_ghost(gfx, (self.grid[x][y] * -1) - 1, Point(x, y)) # Render next blocks for y in xrange(len(self.next_piece.grid)): for x in xrange(len(self.next_piece.grid[y])): if self.next_piece.grid[y][x]: pt = Point(x - self.next_piece.origin.x, y - self.next_piece.origin.y) gallery.render_next(gfx, self.stats.level, self.next_piece.grid[y][x] - 1, self.next_piece.size, pt) # Translate piece by delta def lateral_piece_move(self, dx): self.clear_grid_piece(self.curr_piece) self.curr_piece.pos.x += dx self.curr_piece.tranState.move(dx) if not self.valid_move(self.curr_piece): self.curr_piece.pos.x -= dx else: self.mixer.lateral.play() self.set_grid_piece(self.curr_piece) # Rotate piece by delta def rotate_piece(self, dr): self.clear_grid_piece(self.curr_piece) if dr < 0: self.curr_piece.rotate_left() if not self.valid_move(self.curr_piece): self.curr_piece.rotate_right() else: self.mixer.rotate.play() elif dr > 0: self.curr_piece.rotate_right() if not self.valid_move(self.curr_piece): self.curr_piece.rotate_left() else: self.mixer.rotate.play() self.set_grid_piece(self.curr_piece) # Drop piece to the bottom def drop_piece(self, incr=GridSize.height): self.clear_grid_piece(self.curr_piece) # Find grid bottom place = False for i in range(incr): self.curr_piece.pos.y += 1 if not self.valid_move(self.curr_piece): self.curr_piece.pos.y -= 1 place = True break self.set_grid_piece(self.curr_piece) if place: if self.curr_piece.pos.y + self.curr_piece.origin.x <= 0: self.end_game() else: self.place_piece(self.curr_piece) # Place piece at grid bottom def place_piece(self, piece): # Find cleared rows cleared = [] for y in xrange(GridSize.height): if (len([x for x in xrange(GridSize.width) if self.grid[x][y]]) == GridSize.width): cleared.append(y) # Clear rows & shift down remains. if cleared: for row in cleared: for x in xrange(GridSize.width): self.grid[x][row] = 0 for row in cleared: self.shift_row_down(row) # Update statistics. self.mixer.play_dropped(len(cleared)) if self.stats.update(len(cleared)): self.mixer.level_up.play() self.update_speed() self.new_piece() def update_speed(self): if self.fall_speed >= 2: if self.fall_speed < 5: self.fall_speed -= 1 elif self.fall_speed < 10: self.fall_speed -= 2 else: self.fall_speed -= 3 # Shift above rows down from cleared row. def shift_row_down(self, row): for x in xrange(GridSize.width): for y in reversed(xrange(row)): self.grid[x][y + 1] = self.grid[x][y] self.grid[x][y] = 0 # Set piece values into grid. def set_grid_piece(self, piece): # Find and set piece ghost grid points yorig = piece.pos.y for y in xrange(GridSize.height - piece.pos.y): piece.pos.y += 1 if not self.valid_move(piece): piece.pos.y -= 1 break for y in xrange(len(piece.grid)): for x in xrange(len(piece.grid[y])): if piece.grid[y][x]: self.grid[piece.pos.x + x][piece.pos.y + y] = (piece.grid[y][x] * -1) # Set grid values for piece. piece.pos.y = yorig for y in xrange(len(piece.grid)): for x in xrange(len(piece.grid[y])): if piece.grid[y][x] and piece.pos.y + y >= 0: self.grid[piece.pos.x + x][piece.pos.y + y] = piece.grid[y][x] # Remove piece values from grid. def clear_grid_piece(self, piece): # Clear ghost grid points. for x in xrange(GridSize.width): for y in xrange(GridSize.height): if self.grid[x][y] < 0: self.grid[x][y] = 0 # Clear piece grid points. for y in xrange(len(piece.grid)): for x in xrange(len(piece.grid[y])): if piece.grid[y][x] and piece.pos.y + y >= 0: self.grid[piece.pos.x + x][piece.pos.y + y] = 0 # Check if piece can be moved to new location def valid_move(self, piece): for y in xrange(len(piece.grid)): for x in xrange(len(piece.grid[y])): pt = Point(piece.pos.x + x, piece.pos.y + y) if piece.grid[y][x] and pt.y >= 0: if pt.x < 0 or pt.x >= GridSize.width or pt.y >= GridSize.height: return False if self.grid[pt.x][pt.y]: return False return True def new_piece(self): self.curr_piece = self.next_piece self.next_piece = random_piece() if not self.valid_move(self.curr_piece): self.end_game() self.set_grid_piece(self.curr_piece) self.play() # Our playing method def play(self): rotation = -1 translation = -1 state = GameState.TetrisGame(self.grid, self.curr_piece, self.next_piece, rotation, translation, self.stats.level, self.stats.lines, self.stats.score) root = GameNode(state, None, (rotation,translation)) # create a copy of this state and generates every possible chil ################## ALGORITHMS ##################### # MCTS #mcts = MonteCarloTreeSearch(root) #best_child = mcts.run() # ONE DEPTH MAX SEARCH #best_child = shallowMaxSearch(root) # TWO LAYER MAX SEARCH best_child = DEEPMaxSearch(root) ##################################################### self.best_action = best_child.action # perform the actions self.iterative_rotate_piece(self.best_action[0]) self.iterative_lateral_piece_move(self.best_action[1]) def new_game(self): self.grid = [[0 for y in xrange(GridSize.height)] for x in xrange(GridSize.width)] self.stats = Statistics() self.new_piece() self.mixer.start.play() self.mixer.loop_music() self.fall_speed = 30 self.time_to_drop = self.fall_speed self.running = True def end_game(self): self.mixer.game_over.play() self.running = False def game_over(self): return not self.running # Translate piece by delta def iterative_lateral_piece_move(self, dx): for _ in range(abs(dx)): self.clear_grid_piece(self.curr_piece) self.curr_piece.pos.x += dx/abs(dx) if not self.valid_move(self.curr_piece): self.curr_piece.pos.x -= dx/abs(dx) self.set_grid_piece(self.curr_piece) # Rotate piece by delta def iterative_rotate_piece(self, dr): self.clear_grid_piece(self.curr_piece) if dr < 0: self.curr_piece.rotate_left() if not self.valid_move(self.curr_piece): self.curr_piece.rotate_right() elif dr > 0: # EXTENT ROTATION FUNCTION for _ in range(dr): self.curr_piece.rotate_right() if not self.valid_move(self.curr_piece): self.curr_piece.rotate_left() self.set_grid_piece(self.curr_piece)