def heuristic(node: Grid): score = 0 num_empty_cells = len(node.getAvailableCells()) for i in range(node.size): for j in range(node.size): val = node.getCellValue((i, j)) score += val * 10 if val else ( 1000 / num_empty_cells ) # reward empty spaces more if they are scarce val_up = node.getCellValue((i - 1, j)) val_dn = node.getCellValue((i + 1, j)) val_lt = node.getCellValue((i, j - 1)) val_rt = node.getCellValue((i, j + 1)) if val_up is not None and \ val_dn is not None and \ val != 0: if not (val_up <= val <= val_dn or val_up >= val >= val_dn): score -= 75 * (abs(val_up - val) + abs(val_dn - val)) if val_lt is not None and \ val_rt is not None and \ val != 0: if not (val_lt <= val <= val_rt or val_lt >= val >= val_rt): score -= 75 * (abs(val_lt - val) + abs(val_rt - val)) if j == 0: row = node.map[i] monotonic_row = all(x <= y for x, y in zip(row, row[1:])) monotonic_row = monotonic_row or all( x >= y for x, y in zip(row, row[1:])) if monotonic_row: score += 200 * sum(row) # big bonus if i == 0: col = [node.map[pos][j] for pos in range(node.size)] monotonic_col = all(x <= y for x, y in zip(col, col[1:])) monotonic_col = monotonic_col or all( x >= y for x, y in zip(col, col[1:])) if monotonic_col: score += 200 * sum(col) # big bonus val_order = PlayerAI.get_value_order(val) if val_order > 0: val_up_order = PlayerAI.get_value_order(val_up) val_dn_order = PlayerAI.get_value_order(val_dn) val_lt_order = PlayerAI.get_value_order(val_lt) val_rt_order = PlayerAI.get_value_order(val_rt) if val_up_order > 0: score -= abs(val_up_order - val_order) * 25 if val_dn_order > 0: score -= abs(val_dn_order - val_order) * 25 if val_lt_order > 0: score -= abs(val_lt_order - val_order) * 25 if val_rt_order > 0: score -= abs(val_rt_order - val_order) * 25 return score
def is_state_terminal(self, grid_to_check: Grid, min_max: str): if self.is_grid_depth_out_of_bound(grid_to_check.current_depth): return True if min_max == 'min': return len(grid_to_check.getAvailableCells() ) == 0 # or grid.getMaxTile() > 100 else: return not grid_to_check.canMove() # or grid.getMaxTile() > 100
def set_grid_cell_numbers(self, grid: Grid): self.number_grid_cells = grid.size**2 self.number_grid_cells_zero = len(grid.getAvailableCells()) if self.number_grid_cells_zero == 0: self.number_grid_cells_zero = 1 # to avoid problems self.level_number_branches.update({ '0': 1 }) # default value for 0 - which is only used for this calculation for k in range(1, 100): if k % 2 == 1: # on that level the computer's values are added to each branch self.level_number_branches.update({ str(k): self.level_number_branches.get(str(k - 1)) * self.number_grid_cells_zero * 2 }) else: # on that level the movements are added to each branch self.level_number_branches.update( {str(k): self.level_number_branches.get(str(k - 1)) * 4})
def get_grid_value(grid: Grid): number_cells = grid.size**2 sum_tiles = 0 neigbors_equal = 0 for x in range(grid.size): for y in range(grid.size): sum_tiles += grid.map[x][y] if (x < grid.size - 1) and grid.map[x][y] == grid.map[x + 1][y]: neigbors_equal += 1 if (y < grid.size - 1) and grid.map[x][y] == grid.map[x][y + 1]: neigbors_equal += 1 average = sum_tiles / number_cells number_zero_cells = len(grid.getAvailableCells()) return 2 * number_zero_cells / number_cells + average / 2048 + neigbors_equal / number_cells
def get_children(self, grid: Grid, min_or_max: str): grid_children = [] if min_or_max == 'max': moves = grid.getAvailableMoves() for move in moves: child_grid = self.get_grid_for_move(grid, move) child_grid.current_depth = grid.current_depth + 1 grid_children.append(child_grid) else: cells = grid.getAvailableCells() values = [2, 4] for cell in cells: for value in values: grid_copy = grid.clone() grid_copy.setCellValue(cell, value) grid_copy.current_depth = grid.current_depth + 1 grid_children.append(grid_copy) return grid_children
def minimizing(self, alpha, beta, node: Grid, depth): if depth == 0: return self.heuristic(node) cells = node.getAvailableCells() if not cells: return self.get_terminal_node_value(node) value = math.inf for cell in cells: for i in range(2, 5, 2): child = node.clone() child.insertTile(cell, i) value = min(value, self.maximizing(alpha, beta, child, depth - 1)[0]) beta = min(beta, value) if alpha >= beta: break return value
class GameManager: def __init__(self, size = 4): self.grid = Grid(size) self.possibleNewTiles = [2, 4] self.probability = defaultProbability self.initTiles = defaultInitialTiles self.computerAI = None self.playerAI = None self.displayer = None self.over = False def setComputerAI(self, computerAI): self.computerAI = computerAI def setPlayerAI(self, playerAI): self.playerAI = playerAI def setDisplayer(self, displayer): self.displayer = displayer def updateAlarm(self, currTime): if currTime - self.prevTime > timeLimit + allowance: self.over = True else: while time.clock() - self.prevTime < timeLimit + allowance: pass self.prevTime = time.clock() def gridAverage(self, grid): cells = [] for x in range(4): for y in range(4): if grid.map[x][y] > 0: cells.append((x,y)) sum = 0 for c in cells: sum += grid.map[c[0]][c[1]] return sum / len(cells) def play_one(self, model, tmodel, eps, gamma, copy_period): for i in range(self.initTiles): self.insertRandonTile() grid_array = np.array(self.grid.map).ravel() #observation = grid_array / np.linalg.norm(grid_array) observation = grid_array / 2048 done = False totalreward = 0 iters = 0 ##self.displayer.display(self.grid) # Player AI Goes First turn = PLAYER_TURN maxTile = 2 self.prevTime = time.clock() #while not self.isGameOver() and not self.over: while not self.isGameOver(): # Copy to Ensure AI Cannot Change the Real Grid to Cheat gridCopy = self.grid.clone() move = None if turn == PLAYER_TURN: ##print("Player's Turn:", end="") #move = self.playerAI.getMove(gridCopy) move = model.sample_action(observation, eps, gridCopy) gridAvg = self.gridAverage(gridCopy) #lastMax = gridCopy.getMaxTile() prev_observation = observation last_maxTile = maxTile ##print(actionDic[move]) # Validate Move if move != None and move >= 0 and move < 4: if self.grid.canMove([move]): self.grid.move(move) maxTile = self.grid.getMaxTile() #observation, reward, done, info = env.step(action) grid_array = np.array(self.grid.map).ravel() #observation = grid_array / np.linalg.norm(grid_array) observation = grid_array / maxTile gridNewAvg = self.gridAverage(self.grid) #newMax = self.grid.getMaxTile() reward = gridNewAvg - gridAvg # Update maxTile #reward = maxTile - last_maxTile #reward = 1 done = self.isGameOver() if done: reward = -100 # update the model model.add_experience(prev_observation, move, reward, observation, done) model.train(tmodel) if iters % copy_period == 0: tmodel.copy_from(model) if reward == 1: totalreward += reward iters += 1 else: print("Invalid PlayerAI Move") self.over = True else: print("Invalid PlayerAI Move - 1") self.over = True else: ##print("Computer's turn:") move = self.computerAI.getMove(gridCopy) # Validate Move if move and self.grid.canInsert(move): self.grid.setCellValue(move, self.getNewTileValue()) else: print("Invalid Computer AI Move") self.over = True #if not self.over: #self.displayer.display(self.grid) # Exceeding the Time Allotted for Any Turn Terminates the Game # self.updateAlarm(time.clock()) turn = 1 - turn self.maxTile = self.grid.getMaxTile() print(maxTile) return maxTile def isGameOver(self): return not self.grid.canMove() def getNewTileValue(self): if randint(0,99) < 100 * self.probability: return self.possibleNewTiles[0] else: return self.possibleNewTiles[1]; def insertRandonTile(self): tileValue = self.getNewTileValue() cells = self.grid.getAvailableCells() cell = cells[randint(0, len(cells) - 1)] self.grid.setCellValue(cell, tileValue)
class GameManager: def __init__(self, size=4): self.grid = Grid(size) self.possibleNewTiles = [2, 4] self.probability = defaultProbability self.initTiles = defaultInitialTiles self.computerAI = None self.playerAI = None self.displayer = None self.over = False def setComputerAI(self, computerAI): self.computerAI = computerAI def setPlayerAI(self, playerAI): self.playerAI = playerAI def setDisplayer(self, displayer): self.displayer = displayer def updateAlarm(self, currTime): if currTime - self.prevTime > timeLimit + allowance: #self.over = True print("Time over!!") print(currTime - self.prevTime) else: while time.clock() - self.prevTime < timeLimit + allowance: pass self.prevTime = time.clock() def start(self): for i in range(self.initTiles): self.insertRandonTile() self.displayer.display(self.grid) # Player AI Goes First turn = PLAYER_TURN maxTile = 0 self.prevTime = time.clock() while not self.isGameOver() and not self.over: # Copy to Ensure AI Cannot Change the Real Grid to Cheat gridCopy = self.grid.clone() move = None if turn == PLAYER_TURN: print("Player's Turn:", end="") move = self.playerAI.getMove(gridCopy) print(actionDic[move]) # Validate Move if move != None and move >= 0 and move < 4: if self.grid.canMove([move]): self.grid.move(move) # Update maxTile maxTile = self.grid.getMaxTile() else: print("Invalid PlayerAI Move") self.over = True else: print("Invalid PlayerAI Move - 1") self.over = True else: print("Computer's turn:") move = self.computerAI.getMove(gridCopy) # Validate Move if move and self.grid.canInsert(move): self.grid.setCellValue(move, self.getNewTileValue()) else: print("Invalid Computer AI Move") self.over = True if not self.over: self.displayer.display(self.grid) # Exceeding the Time Allotted for Any Turn Terminates the Game self.updateAlarm(time.clock()) turn = 1 - turn print(maxTile) def isGameOver(self): return not self.grid.canMove() def getNewTileValue(self): if randint(0, 99) < 100 * self.probability: return self.possibleNewTiles[0] else: return self.possibleNewTiles[1] def insertRandonTile(self): tileValue = self.getNewTileValue() cells = self.grid.getAvailableCells() cell = cells[randint(0, len(cells) - 1)] self.grid.setCellValue(cell, tileValue)
class GameManager: def __init__(self, size=4, playerAI=None, computerAI=None, displayer=None): self.grid = Grid(size) self.possibleNewTiles = [2, 4] self.probability = defaultProbability self.initTiles = defaultInitialTiles self.over = False # Initialize the AI players self.computerAI = computerAI or ComputerAI() self.playerAI = playerAI or PlayerAI() self.displayer = displayer or Displayer() self.timedOut = False def updateAlarm(self) -> None: """ Checks if move exceeded the time limit and updates the alarm """ if time.process_time() - self.prevTime > maxTime: print("timed out") self.over = True self.timedOut = True self.prevTime = time.process_time() def getNewTileValue(self) -> int: """ Returns 2 with probability 0.95 and 4 with 0.05 """ return self.possibleNewTiles[random.random() > self.probability] def insertRandomTiles(self, numTiles: int): """ Insert numTiles number of random tiles. For initialization """ for i in range(numTiles): tileValue = self.getNewTileValue() cells = self.grid.getAvailableCells() cell = random.choice(cells) if cells else None self.grid.setCellValue(cell, tileValue) def start(self) -> int: """ Main method that handles running the game of 2048 """ # Initialize the game self.insertRandomTiles(self.initTiles) self.displayer.display(self.grid) turn = PLAYER_TURN # Player AI Goes First self.prevTime = time.process_time() while self.grid.canMove() and not self.over: # Copy to Ensure AI Cannot Change the Real Grid to Cheat gridCopy = self.grid.clone() #time.sleep(.1) move = None if turn == PLAYER_TURN: print("Player's Turn: ", end="") move = self.playerAI.getMove(gridCopy) print(actionDic[move]) # If move is valid, attempt to move the grid if move != None and 0 <= move < 4: if self.grid.canMove([move]): self.grid.move(move) else: print("Invalid PlayerAI Move - Cannot move") self.over = True else: print("Invalid PlayerAI Move - Invalid input") self.over = True else: print("Computer's turn: ") move = self.computerAI.getMove(gridCopy) # Validate Move if move and self.grid.canInsert(move): self.grid.setCellValue(move, self.getNewTileValue()) else: print("Invalid Computer AI Move") self.over = True # Comment out during heuristing optimizations to increase runtimes. # Printing slows down computation time. self.displayer.display(self.grid) # Exceeding the Time Allotted for Any Turn Terminates the Game self.updateAlarm() turn = 1 - turn return self.grid.getMaxTile() def start_no_disp(self) -> int: """ Main method that handles running the game of 2048 """ # Initialize the game self.insertRandomTiles(self.initTiles) #self.displayer.display(self.grid) turn = PLAYER_TURN # Player AI Goes First self.prevTime = time.process_time() while self.grid.canMove() and not self.over: # Copy to Ensure AI Cannot Change the Real Grid to Cheat gridCopy = self.grid.clone() #time.sleep(.1) move = None if turn == PLAYER_TURN: #print("Player's Turn: ", end="") move = self.playerAI.getMove(gridCopy) #print(actionDic[move]) # If move is valid, attempt to move the grid if move != None and 0 <= move < 4: if self.grid.canMove([move]): self.grid.move(move) else: #print("Invalid PlayerAI Move - Cannot move") self.over = True else: #print("Invalid PlayerAI Move - Invalid input") self.over = True else: #print("Computer's turn: ") move = self.computerAI.getMove(gridCopy) # Validate Move if move and self.grid.canInsert(move): self.grid.setCellValue(move, self.getNewTileValue()) else: #print("Invalid Computer AI Move") self.over = True # Comment out during heuristing optimizations to increase runtimes. # Printing slows down computation time. #self.displayer.display(self.grid) # Exceeding the Time Allotted for Any Turn Terminates the Game self.updateAlarm() turn = 1 - turn return self.grid.getMaxTile() def start_training(self) -> int: """ Main method that handles running the game of 2048 """ # Initialize the game self.insertRandomTiles(self.initTiles) #self.displayer.display(self.grid) turn = PLAYER_TURN # Player AI Goes First self.prevTime = time.process_time() while self.grid.canMove() and not self.over: # Copy to Ensure AI Cannot Change the Real Grid to Cheat gridCopy = self.grid.clone() #time.sleep(.1) move = None if turn == PLAYER_TURN: #print("Player's Turn: ", end="") move = self.playerAI.getMoveLearning(gridCopy) #print(actionDic[move]) # If move is valid, attempt to move the grid if move != None and 0 <= move < 4: if self.grid.canMove([move]): self.grid.move(move) else: #print("Invalid PlayerAI Move - Cannot move") self.over = True else: #print("Invalid PlayerAI Move - Invalid input") self.over = True else: #print("Computer's turn: ") move = self.computerAI.getMove(gridCopy) # Validate Move if move and self.grid.canInsert(move): self.grid.setCellValue(move, self.getNewTileValue()) else: #print("Invalid Computer AI Move") self.over = True # Comment out during heuristing optimizations to increase runtimes. # Printing slows down computation time. #self.displayer.display(self.grid) # Exceeding the Time Allotted for Any Turn Terminates the Game self.updateAlarm() turn = 1 - turn return self.grid.getMaxTile() def start_reinforce(self) -> int: """ Main method that handles running the game of 2048 """ # Initialize the game self.insertRandomTiles(self.initTiles) #self.displayer.display(self.grid) turn = PLAYER_TURN # Player AI Goes First self.prevTime = time.process_time() while self.grid.canMove() and not self.over: # Copy to Ensure AI Cannot Change the Real Grid to Cheat gridCopy = self.grid.clone() #time.sleep(.1) move = None if turn == PLAYER_TURN: #print("Player's Turn: ", end="") move = self.playerAI.getMove(gridCopy) #print(actionDic[move]) # If move is valid, attempt to move the grid if move != None and 0 <= move < 4: if self.grid.canMove([move]): self.grid.move(move) else: #print("Invalid PlayerAI Move - Cannot move") self.over = True else: #print("Invalid PlayerAI Move - Invalid input") self.over = True else: #print("Computer's turn: ") move = self.computerAI.getMove(gridCopy) # Validate Move if move and self.grid.canInsert(move): self.grid.setCellValue(move, self.getNewTileValue()) else: #print("Invalid Computer AI Move") self.over = True # Comment out during heuristing optimizations to increase runtimes. # Printing slows down computation time. #self.displayer.display(self.grid) # Exceeding the Time Allotted for Any Turn Terminates the Game self.updateAlarm() turn = 1 - turn return self.grid.getMaxTile()
class GameManager: def __init__(self, size=4): self.grid = Grid(size) self.possibleNewTiles = [2, 4] self.probability = defaultProbability self.initTiles = defaultInitialTiles self.computerAI = None self.playerAI = None self.displayer = None self.over = False self.max_time_for_get_move = 0 self.next_move_counter = 0 self.MAX_NEXT_MOVE_COUNTER = 10000 def setComputerAI(self, computerAI): self.computerAI = computerAI def setPlayerAI(self, playerAI): self.playerAI = playerAI def setDisplayer(self, displayer): self.displayer = displayer def updateAlarm(self, currTime): if currTime - self.prevTime > timeLimit + allowance: self.over = False else: while time.clock() - self.prevTime < timeLimit + allowance: pass self.prevTime = time.clock() def start(self): for i in range(self.initTiles): self.insertRandonTile() # self.grid.map = [[4, 128, 4, 2], [64, 4, 32, 4], [8, 64, 8, 16], [16, 4, 2, 2]] # self.grid.map = [[2, 32, 2, 4], [4, 256, 32, 8], [16, 64, 16, 0], [4, 16, 8, 4]] # self.grid.map = [[2, 32, 2, 4], [4, 256, 32, 8], [2, 32, 64, 16], [4, 0, 8, 4]] # with utility_value (min) = -inf for move 0 # self.grid.map = [[2, 32, 2, 4], [4, 256, 32, 8], [2, 32, 64, 16], [2, 4, 8, 4]] # for move 0 => -inf - WHY self.displayer.display(self.grid) # Player AI Goes First turn = PLAYER_TURN maxTile = 0 self.prevTime = time.clock() while not self.isGameOver() and not self.over: # Copy to Ensure AI Cannot Change the Real Grid to Cheat gridCopy = self.grid.clone() move = None if turn == PLAYER_TURN: print("Player's Turn:", end="") move = self.playerAI.getMove(gridCopy) if self.playerAI.run_time > self.max_time_for_get_move: self.max_time_for_get_move = self.playerAI.run_time print(actionDic[move]) # Validate Move if move != None and move >= 0 and move < 4: if self.grid.canMove([move]): self.grid.move(move) # Update maxTile maxTile = self.grid.getMaxTile() else: print("Invalid PlayerAI Move") self.over = True else: print("Invalid PlayerAI Move - 1") self.over = True self.next_move_counter += 1 if self.next_move_counter > self.MAX_NEXT_MOVE_COUNTER: self.over = True break else: print("Computer's turn:") move = self.computerAI.getMove(gridCopy) # Validate Move if move and self.grid.canInsert(move): self.grid.setCellValue(move, self.getNewTileValue()) else: print("Invalid Computer AI Move") self.over = True if not self.over: self.displayer.display(self.grid) # Exceeding the Time Allotted for Any Turn Terminates the Game self.updateAlarm(time.clock()) turn = 1 - turn print( 'maxTile = {0} - max_time_for_get_move = {1:5.4f} - number_players_moves = {2}' .format(maxTile, self.max_time_for_get_move, self.next_move_counter)) self.plot_move_times() def plot_move_times(self): x = np.array([i for i in range(len(self.playerAI.run_time_list))]) y = np.array(self.playerAI.run_time_list) plt.plot(x, y) plt.show() # plot with various axes scales plt.figure(1) # linear plt.subplot(221) plt.plot(x, y) plt.yscale('linear') plt.title('linear') plt.grid(True) def isGameOver(self): return not self.grid.canMove() def getNewTileValue(self): if randint(0, 99) < 100 * self.probability: return self.possibleNewTiles[0] else: return self.possibleNewTiles[1] def insertRandonTile(self): tileValue = self.getNewTileValue() cells = self.grid.getAvailableCells() cell = cells[randint(0, len(cells) - 1)] self.grid.setCellValue(cell, tileValue)
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Created on Mon Jun 11 16:36:48 2018 @author: jinzhao """ from Grid_3 import Grid g = Grid() g.map[0][0] = 2 g.map[1][0] = 2 g.map[3][0] = 4 empty = g.getAvailableCells() print(empty) def test_fun(): return 1, 2 b = test_fun()[1] print(b) class test_class(): def __init__(self): self.val = 100
neighbours = self.get_neighbours(pos) for n in neighbours: if pos_value == grid.getCellValue(n): merges += 1 return merges def grid_eval(self, grid): gradients = [[[3, 2, 1, 0], [2, 1, 0, -1], [1, 0, -1, -2], [0, -1, -2, -3]], [[0, 1, 2, 3], [-1, 0, 1, 2], [-2, -1, 0, 1], [-3, -2, -1, -0]], [[0, -1, -2, -3], [1, 0, -1, -2], [2, 1, 0, -1], [3, 2, 1, 0]], [[-3, -2, -1, 0], [-2, -1, 0, 1], [-1, 0, 1, 2], [0, 1, 2, 3]]] values = [0, 0, 0, 0] for i in range(4): for x in range(4): for y in range(4): values[i] += gradients[i][x][y] * grid.map[x][y] return max(values) if __name__ == "__main__": grid = Grid() a = grid.getAvailableCells() print(len(a))
from random import randint from BaseAI_3 import BaseAI from Grid_3 import Grid from PlayerAI_3 import PlayerAI grid = Grid() grid.map = [[4, 64, 8, 4], [32, 8, 64, 8], [256, 512, 32, 4], [4, 8, 4, 2]] moves = [1, 2, 3, 4] print(moves) moves[2] = 7 print(moves) print(len(grid.getAvailableCells())) print(grid.map) print(PlayerAI.is_state_terminal(grid, 'min'))
class gym_2048(): def __init__(self, size=4): self.size = size self.grid = None self.possible_new_tiles = [2, 4] self.probability = default_probability self.init_tiles = default_initial_tiles self.over = False self.action_space = 4 self.reward = 0 self.max_tile = 0 self.score = 0 pass def make(self): self.grid = Grid(self.size) for i in range(self.init_tiles): self.insert_random_tile() def get_state(self): return self.grid.map def reset(self): self.make() self.score = 0 self.max_tile = 0 self.reward = 0 def get_new_tile_value(self): if randint(0, 99) < 100 * self.probability: return self.possible_new_tiles[0] else: return self.possible_new_tiles[1] def insert_random_tile(self): tile_value = self.get_new_tile_value() cells = self.grid.getAvailableCells() if len(cells) > 0: cell = cells[randint(0, len(cells) - 1)] self.grid.setCellValue(cell, tile_value) def close(self): self.grid = None def is_done(self): return not self.grid.canMove() def render(self, mode='human'): grid = self.grid if mode == "human": for i in range(grid.size): for j in range(grid.size): print("%6d " % grid.map[i][j], end="") print("") print("") # return self.get_state() def step(self, action): move = action # print(action_dict[move]) # Validate Move if move is not None and 0 <= move < 4: moved, merge_points = self.grid.move(move) self.score = merge_points # Update maxTile self.max_tile = self.grid.getMaxTile() if moved: self.insert_random_tile() self.calculate_reward() else: print("Invalid PlayerAI Move - 1") exit(0) return self.get_state(), self.reward, self.is_done(), [] def calculate_reward(self): # weighted_sum = self.calculate_weighted_sum() # penalty = self.calculate_penalty() # self.reward = weighted_sum - penalty self.reward = self.score def calculate_weighted_sum(self): score = 0 for x in range(4): for y in range(4): score += (priority[x][y] * self.grid.map[x][y] * self.grid.map[x][y]) return score def calculate_penalty(self): # Calculate clustering penalty. # We want two same valued tiles to be present next to each other # so that it is easier to merge. # This penalty becomes large when high valued tiles are scattered across # the grid, indicating that the grid is bad. def within_bounds(position): return 0 <= position['x'] < 4 and 0 <= position['y'] < 4 penalty = 0 # Direction vectors for up, down, left and right directions = ([-1, 0], [1, 0], [0, -1], [0, 1]) for x in range(4): for y in range(4): # if grid.map[x][y] != 0: for i in range(4): pos = { "x": x + directions[i][0], "y": y + directions[i][1] } if within_bounds(pos): neighbour = self.grid.map[pos['x']][pos['y']] # if neighbour!=0: penalty += math.fabs(neighbour - self.grid.map[x][y]) return penalty
class GameManager: def __init__(self, size=4): self.grid = Grid(size) self.possibleNewTiles = [2, 4] self.probability = defaultProbability self.initTiles = defaultInitialTiles self.computerAI = None self.playerAI = None self.displayer = None self.over = False # Load the DNN model self.model_NN = load_model("all_2048_8000games.h5") # self.result_file = open("resultRandom.txt", "a") def setComputerAI(self, computerAI): self.computerAI = computerAI def setPlayerAI(self, playerAI): self.playerAI = playerAI def setDisplayer(self, displayer): self.displayer = displayer def updateAlarm(self, currTime): if currTime - self.prevTime > timeLimit + allowance: self.over = True else: while time.clock() - self.prevTime < timeLimit + allowance: pass self.prevTime = time.clock() def start(self): for i in range(self.initTiles): self.insertRandonTile() self.displayer.display(self.grid) # Player AI Goes First turn = PLAYER_TURN maxTile = 0 self.prevTime = time.clock() while not self.isGameOver() and not self.over: # Copy to Ensure AI Cannot Change the Real Grid to Cheat gridCopy = self.grid.clone() move = None if turn == PLAYER_TURN: print("Player's Turn:", end="") # move = self.playerAI.getMove(gridCopy) # Using NN to make move instead list_proba = self.model_NN.predict( self.generateCurrentBoard1D(self.grid.map))[0].tolist() move = list_proba.index(max(list_proba)) # availableMoves = self.grid.getAvailableMoves() # move = availableMoves[randint(0, len(availableMoves)-1)] while not self.grid.canMove([move]): # print(list_proba) list_proba[move] = -1 move = list_proba.index(max(list_proba)) # randint(0,3) print(actionDic[move]) # Validate Move if move != None and move >= 0 and move < 4: if self.grid.canMove([move]): """TODO: This line to print out the current grid and how to move for the current state""" current_board_and_move = self.generateCurrentBoardAndMoveToText( self.grid.map, move) print(current_board_and_move) self.grid.move(move) # Update maxTile maxTile = self.grid.getMaxTile() else: print("Invalid PlayerAI Move") self.over = True else: print("Invalid PlayerAI Move - 1") self.over = True else: print("Computer's turn:") move = self.computerAI.getMove(gridCopy) # Validate Move if move and self.grid.canInsert(move): self.grid.setCellValue(move, self.getNewTileValue()) else: print("Invalid Computer AI Move") self.over = True """ Comment this out if do not want to have the display """ if not self.over: self.displayer.display(self.grid) # Exceeding the Time Allotted for Any Turn Terminates the Game self.updateAlarm(time.clock()) turn = 1 - turn print(maxTile) # self.result_file.write(str(maxTile)+"\n") # self.result_file.close() def isGameOver(self): return not self.grid.canMove() def getNewTileValue(self): if randint(0, 99) < 100 * self.probability: return self.possibleNewTiles[0] else: return self.possibleNewTiles[1] def insertRandonTile(self): tileValue = self.getNewTileValue() cells = self.grid.getAvailableCells() cell = cells[randint(0, len(cells) - 1)] self.grid.setCellValue(cell, tileValue) def generateCurrentBoardAndMoveToText(self, map, move): """ Generate the current board situation and the AI's move decision for that situation into text to export to .csv :param map: current board situation :param move: :return: """ current_board_and_move = "" for row in map: for cell in row: current_board_and_move += str(cell) + "," current_board_and_move += str(move) + "\n" return current_board_and_move def generateCurrentBoard1D(self, map): currentBoard = [] for row in map: for cell in row: currentBoard.append(cell) return np.array([currentBoard])
class GameManager: def __init__(self, size = 4): self.grid = Grid(size) self.possibleNewTiles = [2, 4] self.probability = defaultProbability self.initTiles = defaultInitialTiles self.computerAI = None self.playerAI = None self.displayer = None self.over = False def setComputerAI(self, computerAI): self.computerAI = computerAI def setPlayerAI(self, playerAI): self.playerAI = playerAI def setDisplayer(self, displayer): self.displayer = displayer def updateAlarm(self, currTime): if currTime - self.prevTime > timeLimit + allowance: self.over = True else: while time.clock() - self.prevTime < timeLimit + allowance: pass self.prevTime = time.clock() def start(self): for i in range(self.initTiles): self.insertRandonTile() #self.displayer.display(self.grid) # Player AI Goes First turn = PLAYER_TURN maxTile = 0 #self.prevTime = time.clock() while not self.isGameOver() and not self.over: # Copy to Ensure AI Cannot Change the Real Grid to Cheat gridCopy = self.grid.clone() move = None if turn == PLAYER_TURN: #print("Player's Turn:", end="") move = self.playerAI.getMove(gridCopy) #print(actionDic[move]) # Validate Move if move != None and move >= 0 and move < 4: if self.grid.canMove([move]): self.grid.move(move) # Update maxTile maxTile = self.grid.getMaxTile() else: #print("Invalid PlayerAI Move") self.over = True else: #print("Invalid PlayerAI Move - 1") self.over = True else: #print("Computer's turn:") move = self.computerAI.getMove(gridCopy) # Validate Move if move and self.grid.canInsert(move): self.grid.setCellValue(move, self.getNewTileValue()) else: #print("Invalid Computer AI Move") self.over = True #if not self.over: # self.displayer.display(self.grid) # Exceeding the Time Allotted for Any Turn Terminates the Game #self.updateAlarm(time.clock()) turn = 1 - turn print(maxTile) def isGameOver(self): return not self.grid.canMove() def getNewTileValue(self): if randint(0,99) < 100 * self.probability: return self.possibleNewTiles[0] else: return self.possibleNewTiles[1]; def insertRandonTile(self): tileValue = self.getNewTileValue() cells = self.grid.getAvailableCells() cell = cells[randint(0, len(cells) - 1)] self.grid.setCellValue(cell, tileValue)