def predetermined_random(board_state: BoardState, params: dict = None): # get the pre-determined set of random moves if it hasn't already been loaded if len(AutoPlayMethods.directions) == 0: rnd_filename = "random.dat" rnd_file = open(rnd_filename, "r") AutoPlayMethods.directions = [ Direction[str.rstrip(line)] for idx, line in enumerate(rnd_file.readlines()) ] #run the random simulation i = 0 while not board_state.Lost: board_state.move(AutoPlayMethods.directions[i]) i += 1
def branch(board_state: BoardState, params: dict = None): layers: int = params.get("LAYERS") if not layers: layers = 2 if layers < 1: return move_num = 1 root: Move = Move.as_root_node(board_state) while not board_state.Lost: print(f"Move: {move_num}") print(str(board_state.field)) move_num += 1 current_layer = [] next_layer = [root] for _ in range(layers): current_layer = next_layer next_layer = [] for move in current_layer: next_layer.extend(move.generate_children()) if not any(next_layer): next_layer = current_layer break # when we're done, the last layer is the final set of children weights = {d: 0 for d in Direction} for d in Direction: scores = [ move.get_reward() for move in filter( lambda mv: mv.reward_direction() == d, next_layer) ] if len(scores) > 0: weights[d] = mean(scores) top_score = max(weights.values()) # get options with weights equivalent to top scorer; # if there are more than one, pick a random one top_scorers = [ key for key, value in weights.items() if value == top_score ] rec_dir = top_scorers[0] if len( top_scorers) == 1 else random.choice(top_scorers) board_state.move(rec_dir, weights) # find the move that represents what actually happened and make it the new root root = next(move for move in root.children if move.end_state == board_state.field) root.parent = None
def pseudo_ML(board_state: BoardState, params: dict = None): pml = Pseudo_ML() if params == None else Pseudo_ML(params) while not board_state.Lost: weights = pml.get_direction_weights(board_state) direction_rec = pml.get_direction_recommendation(weights) this_dir = direction_rec[0] # get options with weights equivalent to top scorer; # if there are more than one, pick a random one top_scorers = [ key for key, value in weights.items() if value == direction_rec[1] ] if (len(top_scorers) > 1): this_dir = random.choice(top_scorers) board_state.move(this_dir, weights.copy())
def get_direction_weights(self, board_state: BoardState): statesAfterMove = [] direction_scores = {d: 0 for d in Direction} squares_array = flatten(board_state.field) # get a list of the board state after making all legal moves for direction in Direction: dir_move = board_state.move(direction, {}, False, False) if dir_move.changed_board( ): # ignore moves that do not change the board possible_states = self.enumerate_possible_outcomes( squares_array, board_state.FOUR_CHANCE, board_state.BOARD_SIZE) for state, prob in possible_states: score = self.score_board_state2(board_state) direction_scores[direction] += prob * score statesAfterMove.append([direction, state, prob, score]) return {key: val for key, val in direction_scores.items() if val != 0}
def run_method(x, method_to_call, log_path: str = '', params: dict = {}): new_board = BoardState() start_time = time.time() method_to_call(new_board, params) end_time = time.time() print(f'End: {x}') # save the detailed log, if appropriate if log_path: #create a log file log_file = open(log_path, 'w') log_file.writelines( [entry.as_log_entry() + '\n' for entry in new_board.move_history]) log_file.close() # return the results return [ x, len(new_board.move_history), new_board.field.get_score(), end_time - start_time, *params.values() ]
def score_board_state2(self, board: BoardState): scores = [] base_score = board.get_score() * (self.BASE_SCORE_MULTIPLIER / 10) scores.append(base_score) #add scores that don't change based on direction items = flatten(board.field) bonus = sum([ item * self.POINTS_PER_FREE_SQUARE for item in items if item == 0 ]) bonus += max(items) * self.HIGHEST_TILE_MULTIPLER scores.append(bonus) # get the corner into the 0,0 spot corner = self.get_corner_by_tiles(board) working_board = array_2d_copy(board.field) if corner[0] > 0: working_board = invert(working_board) if corner[1] > 0: working_board = flip(working_board) # get the order score order_score = self.get_board_order_score(working_board) scores.append(order_score) # get the high value on the board (closest to the corner) (h_x, h_y, high_val) = self.get_high_val(working_board) high_score = high_val * self.HIGHEST_TILE_MULTIPLER scores.append(high_score) # get the count of tiles between the high_val and the corner bad_tile_count = len([(x,y) for x in range(h_x + 1) \ for y in range(h_y + 1) \ if (x > 0 or y > 0) and working_board[x][y] > 0]) bad_tile_score = bad_tile_count * self.TILE_BETWEEN_HIGH_AND_CORNER_MULT * -1 scores.append(bad_tile_score) return sum(scores)
from game.BoardDisplay import BoardDisplay from game.BoardState import BoardState board = BoardDisplay(BoardState())
def reset(self): self.board.reset_board() self.board = BoardState() self.title(TITLE)
from autoplay.BoardReplay import BoardReplay from game.BoardState import BoardState from game.Move import Move import numpy as np # put in a filename from the log folder file_to_import = 'logs/branch_20181005_140715.392990.log' # 'logs/random_20180906_095102.239753.log' log_file = open(file_to_import, "r") moves = list(map(Move.from_log_entry, log_file.readlines())) log_file.close() board = BoardState() board.import_from_log(moves) replay = BoardReplay(board)