def __init__(self): self.game_state = GameState(TetrisBoard()) #from blocks import BlockLine, BlockRightL, BlockCube #l = BlockLine() #l.rotate() #r = BlockRightL() #r.rotate(-1) #c = BlockCube() #self.game_state.board.place_block(l, (-1,0)) #self.game_state.board.place_block(r, (1,0)) #self.game_state.board.place_block(c, (8,0)) self.engine = TetrisEngine(self.game_state) self.ai = TetrisAI(self.engine)
def generate_random_games(self, num=1): """Generates a completely new set of Tetris instanes and AIs with randomized weights.""" self.tetris_instances.clear() self.tetris_ais.clear() for i in range(num): self.tetris_instances.append( Tetris(self.grid_width, self.grid_height, self.cell_width)) self.tetris_ais.append( TetrisAI(self.grid_width, self.grid_height, [], [], []))
class TetrisGame: def __init__(self): self.game_state = GameState(TetrisBoard()) #from blocks import BlockLine, BlockRightL, BlockCube #l = BlockLine() #l.rotate() #r = BlockRightL() #r.rotate(-1) #c = BlockCube() #self.game_state.board.place_block(l, (-1,0)) #self.game_state.board.place_block(r, (1,0)) #self.game_state.board.place_block(c, (8,0)) self.engine = TetrisEngine(self.game_state) self.ai = TetrisAI(self.engine) def run_main(self): self.engine.start() while not self.engine.running(): pass self.ai.play() while self.engine.running(): try: c = getch() if c == LEFT_KEY: self.engine.move_left() if c == RIGHT_KEY: self.engine.move_right() if c == DOWN_KEY: self.engine.move_down() if c == DROP_KEY: self.engine.drop_block() if c == UP_KEY: self.engine.rotate() except KeyboardInterrupt: self.engine.stop()
def next_generation(self): """Ends the current generation and produces the next generation of AIs.""" self.generation += 1 # get fitness scores and sort fitness_scores = [(inst.lines_cleared, i) for i, inst in enumerate(self.tetris_instances)] list.sort(fitness_scores, key=lambda elem: elem[0]) fitness_scores.reverse() avg_all = sum([elem[0] for elem in fitness_scores]) / len(fitness_scores) print( 'Lines cleared: ', self.format_float_list([elem[0] for elem in fitness_scores], num_decimals=0, delimiter=' ')) print('Lines cleared average: ', self.format_float_list([avg_all])) highest_scores = fitness_scores[:self.selection_size] avg_most = sum([elem[0] for elem in highest_scores]) / len(highest_scores) print( 'Most lines cleared: ', self.format_float_list([elem[0] for elem in highest_scores], num_decimals=0, delimiter=' ')) print('Most lines cleared average: ', self.format_float_list([avg_most])) print( 'Most cleared row filled weights: ', self.format_float_list( self.tetris_ais[highest_scores[0][1]].row_filled_weights, brackets=True)) print( 'Most cleared hole height weights: ', self.format_float_list( self.tetris_ais[highest_scores[0][1]].hole_height_weights, brackets=True)) print( 'Most cleared column diff weights: ', self.format_float_list( self.tetris_ais[highest_scores[0][1]].column_diff_weights, brackets=True)) # save the weights of the highest scoring AI with open('data/weights.txt', 'a') as f: f.write('\n') f.write(str(datetime.now()) + '\n') f.write( f'Generation: {self.generation - 1} | Instance: {self.current_spectating_idx + 1}/{self.population_size}\n' ) f.write(f'Lines cleared: {fitness_scores[0][0]}\n') f.write( self.format_float_list(self.tetris_ais[highest_scores[0] [1]].row_filled_weights, brackets=True) + '\n') f.write( self.format_float_list(self.tetris_ais[ highest_scores[0][1]].hole_height_weights, brackets=True) + '\n') f.write( self.format_float_list(self.tetris_ais[ highest_scores[0][1]].column_diff_weights, brackets=True) + '\n') # prepare next generation new_ais = [] # create completely new AIs if the average was too low if avg_most <= 0.1: [ new_ais.append( TetrisAI(self.grid_width, self.grid_height, [], [], [])) for i in range(self.population_size) ] else: # produce new generation # let the upper third of the most fit of this generation continue on as is for i in range(self.population_size // 2): new_ais.append(self.tetris_ais[fitness_scores[i][1]].clone()) # then crossover until the population size is reached while len(new_ais) != self.population_size: # randomly select two different parents idx1 = randint(0, len(highest_scores) - 1) idx2 = idx1 while idx2 == idx1: idx2 = randint(0, len(highest_scores) - 1) new_ais.append( self.tetris_ais[highest_scores[idx1][1]].crossover( self.tetris_ais[highest_scores[idx2][1]])) new_ais[-1].mutate(self.mutate_rate) self.tetris_instances.clear() [ self.tetris_instances.append( Tetris(self.grid_width, self.grid_height, self.cell_width)) for i in range(self.population_size) ] self.tetris_ais.clear() self.tetris_ais = new_ais self.print_starting_generation()