def _precompute_distances(self, state): """ Precomputes the distance of each cell to that of the closest ghost """ theGhosts = api.ghosts(state) distances = [[float("inf") for col in range(len(self.map[0]))] for row in range(len(self.map))] theGhosts = api.ghosts(state) for ghost in theGhosts: self._flood_fill(distances, int(ghost[1]), int(ghost[0]), 0) return distances
def updateGhostsInMap(self, state): ghosts = api.ghosts(state) for i in range(len(ghosts)): self.map.setValue(int(ghosts[i][0]), int(ghosts[i][1]), self.GHOST) gSurround = self.getSurroundingLocations(int(ghosts[i][0]), int(ghosts[i][1])) for j in range(len(gSurround)): self.map.setValue(gSurround[j][0], gSurround[j][1], self.GHOST/2)
def getAction(self, state): #if the internal map of the environment has yet to be initialized, initialize it if not self.init: self.initialize(state) #update the legal moves for this move self.setLegal(state) #if pacman can detect a ghost nearby pacman needs to run away if api.ghosts(state): return self.runAway(state) #if a route has been found, pacman will follow it instead of searching again if len(self.path) != 0: #pop off the first move in the path nextMove = self.path.pop(0) #check that the move is legal if nextMove[1] in self.legal: #mark that position as visited with "P" self.map[nextMove[0][0]][nextMove[0][1]] = "P" self.lastDir = nextMove[1] #return the move return api.makeMove(self.lastDir, self.legal) #if the move is not legal, find a new path else: return self.findPath(state) #otherwise find a path else: return self.findPath(state)
def getAction(self, state): # Get legal actions legal = api.legalActions(state) # Get location of Pacman pacman = api.whereAmI(state) # Get location of Ghosts locGhosts = api.ghosts(state) #print "locGhosts: ", locGhosts # Get distance between pacman and the ghosts for i in locGhosts: p_g_dist = util.manhattanDistance(pacman, i) # Get distance between ghosts g_g_dist = util.manhattanDistance(locGhosts[0], locGhosts[1]) #print "g_g_dist:", g_g_dist # Get distance between pacman and first Ghost dist = [] dist.append(locGhosts[0][0] - pacman[0]) dist.append(locGhosts[0][1] - pacman[1]) return api.makeMove(Directions.STOP, legal)
def getAction(self,state): walls = api.walls(state) width,height = api.corners(state)[-1] legal = api.legalActions(state) me = api.whereAmI(state) food = api.food(state) ghosts = api.ghosts(state) capsules = api.capsules(state) direction = Directions.STOP x, y = me if not hasattr(self, 'map'): self.createMap(walls, width + 1, height + 1) self.checkForCapsules(capsules, legal, ghosts) legal = self.solveLoop(ghosts, legal) if len(ghosts): self.memorizeGhosts(ghosts) if self.counter < 0: for ghost in ghosts: legal = self.checkForGhosts(ghost, me, legal) direction = self.pickMove(me, legal, width + 1, height + 1, food) self.updatePosition(me, 1, self.map) self.printMap(self.map) self.last = direction return direction
def generateRewardGrid(self, state): # a negative incentive for non-terminal states # this is an incentive for taking the shortest route initialValue = -5 # initialize 2d array with correct dimensions (w, h) = api.corners(state)[3] rewardGrid = [[initialValue for x in range(w + 1)] for y in range(h + 1)] ghosts = api.ghosts(state) foods = api.food(state) walls = api.walls(state) for (x, y) in foods: rewardGrid[y][x] = 100 # fill a radius around each ghost with negative reward # size of radius dependent on number of foods remaining # pacman feels no fear when almost winning radius = 5 if len(foods) > 3 else 2 for (x, y) in ghosts: self.floodFill(rewardGrid, int(x), int(y), radius) for (x, y) in walls: rewardGrid[y][x] = 0 return rewardGrid
def getAction(self, state): print "-" * 30 #divider ghosts = api.ghosts(state) #get state of ghosts legal = state.getLegalPacmanActions() #Again, get a list of pacman's legal actions last = state.getPacmanState().configuration.direction #store last move pacman = api.whereAmI(state) #retrieve location of pacman food = api.food(state) #retrieve location of food walls = api.walls(state) #how to call getfoodvalmap method. #In reality, the reward should be the final value-iteration of the grid. foodVal = self.getValueMap(state, 10) print foodVal #example on how to use getPacMEU function currentUtil = self.getPacMEU(pacman[0], pacman[1], foodVal, legal) print "Utility values: " print currentUtil print max(currentUtil.values()) #example on how to use getMEU function foodUtil = self.getMEU((18, 3), foodVal, walls) print "max utility for (18, 3) is: " print foodUtil if Directions.STOP in legal: legal.remove(Directions.STOP) # Random choice between the legal options. return api.makeMove(random.choice(legal), legal) """
def getAction(self, state): self.makeMap(state) self.addWallsToMap(state) self.addConsumablesToMap(state) self.updateGhosts(state) # Get the actions we can try, and remove "STOP" if that is one of them. pacman = api.whereAmI(state) legal = api.legalActions(state) ghosts = api.ghosts(state) corners = api.corners(state) layoutHeight = self.getLayoutHeight(corners) layoutWidth = self.getLayoutWidth(corners) if (layoutHeight-1)<8 and (layoutWidth-1)<8: for i in range (100): self.valIterS(state,0.68,-0.1) else: for i in range (50): self.valIterM(state,0.8,-0.1) plannedMove = self.plannedMove(pacman[0],pacman[1]) #self.dankMap.prettyDisplay() #Feel free to uncomment this if you like to see the values generated if Directions.STOP in legal: legal.remove(Directions.STOP) #Input the calculated move for our next move return api.makeMove(plannedMove, legal)
def getAction(self, state): self.pacman = api.whereAmI(state) self.legal = api.legalActions(state) self.ghosts = api.ghosts(state) if not self.init: self.initialize(state) else: # if self.reward[self.pacman[0]][self.pacman[1]] < 10: # self.reward[self.pacman[0]][self.pacman[1]] = self.reward[self.pacman[0]][self.pacman[1]] - 1 # else: self.reward[self.pacman[0]][self.pacman[1]] = self.baseReward reward = self.updateMap(state) self.bellman(state, reward) print '' for row in reward: print row print '' for row in self.utility: print row #return self.getMove(state) return api.makeMove(Directions.STOP, self.legal)
def valueIterationSmall(self, state, reward, gamma, V1): # Similar to valueIteration function # does not calculate buffers around ghosts (cause it would be too small) # meant for maps smaller than 10 x 10 corners = api.corners(state) walls = api.walls(state) food = api.food(state) ghosts = api.ghosts(state) capsules = api.capsules(state) maxWidth = self.getLayoutWidth(corners) - 1 maxHeight = self.getLayoutHeight(corners) - 1 if not (0 < gamma <= 1): raise ValueError("MDP must have a gamma between 0 and 1.") # Implement Bellman equation with 10-loop iteration # Since smaller maps do not require as big of a value iteration loop loops = 100 while loops > 0: V = V1.copy() # This will store the old values for i in range(maxWidth): for j in range(maxHeight): # Exclude any food because in this case it is the terminal state if (i, j) not in walls and (i, j) not in food and ( i, j) not in ghosts and (i, j) not in capsules: V1[(i, j)] = reward + gamma * self.getTransition(i, j, V) loops -= 1
def getAction(self, state): """ The function to work out next intended action carried out. Parameters: None Returns: Directions: Intended action that Pacman will carry out. """ current_pos = api.whereAmI(state) corners = api.corners(state) food = api.food(state) ghosts = api.ghosts(state) ghost_scared_time = api.ghostStatesWithTimes(state)[0][1] walls = api.walls(state) legal = api.legalActions(state) capsules = api.capsules(state) protected_coords = walls + ghosts + [current_pos] width = max(corners)[0] + 1 height = max(corners, key=itemgetter(1))[1] + 1 board = self.create_board(width, height, -0.04) board.set_position_values(food, 1) board.set_position_values(walls, 'x') board.set_position_values(capsules, 2) if ghost_scared_time < 5: board.set_position_values(ghosts, -3) # for i in range(height): # for j in range(width): # print board[i, j], # print # print print "GHOST LIST: ", ghosts for x, y in ghosts: # set the surrounding area around the ghost to half the reward of the ghost # avoids changing the reward of the ghost itself, the pacman and the walls # print "GHOST Coordinates: " + str(x) + " " + str(y) x_coordinates = [x - 1, x, x + 1] y_coordinates = [y - 1, y, y + 1] # print "X/Y Coordinates: " + str(x_coordinates) + " " + str(y_coordinates) for x_coord in x_coordinates: for y_coord in y_coordinates: if (x_coord, y_coord) not in protected_coords: # print("index: " + str((board.convert_y(y_coord), x_coord))) converted_y = board.convert_y(y_coord) # print "VALUE: " + str(board[board.convert_y(y), x]) board[converted_y, x_coord] = board[board.convert_y(y), x] / 2 # print "VALUE PART 2: " + str(board[converted_y, x_coord]) board = self.value_iteration(state, board) expected_utility = self.calculate_expected_utility( state, board, abs(current_pos[1] - (height - 1)), current_pos[0]) return max([(utility, action) for utility, action in expected_utility if action in legal])[1]
def registerInitialState(self, state): print "Running registerInitialState!" # Make a map of the right size self.makeMap(state) self.addWallsToMap(state) self.updateFoodInMap(state) self.map.display() self.updateUtilities(api.walls(state), api.food(state), api.ghosts(state), 1000) self.counter = 0
def getAction(self, state): """ The function to work out next intended action carried out. Parameters: None Returns: Directions: Intended action that Pacman will carry out. """ current_pos = api.whereAmI(state) food = api.food(state) # make sure all ghost coordinates are ints rather than floats ghosts = [(int(x), int(y)) for x, y in api.ghosts(state)] legal = api.legalActions(state) capsules = api.capsules(state) food_multiplier = ( (0.8 * len(food) / float(self.initial_num_food))**2) + 6 ghost_multiplier = ( (0.2 * len(food) / float(self.initial_num_food))**2) + 3 board = Board(self.width, self.height, -0.04) board.set_position_values(self.walls, 'x') board.set_position_values(capsules, 2 * food_multiplier) board.set_position_values(food, 1 * food_multiplier) board.set_position_values(ghosts, -7 * ghost_multiplier) # rewards of ghosts, walls and current position cannot be overridden protected_pos = set(ghosts + self.walls + [current_pos]) # setting a much more negative reward for potential positions ghosts can occupy # in two moves. for ghost in ghosts: # loop through potential positions that the ghost can occupy if it were # to move now for pos in self.get_next_pos(ghost): if pos not in protected_pos: # set the reward value of surrounding positions of ghosts to -6 * # ghost multiplier. board[int(board.convert_y(pos[1])), int(pos[0])] = -6 * ghost_multiplier for position in self.get_next_pos(pos): # loop through potential positions that the ghost can occupy if # it were to move two times. if position not in protected_pos: board[int(board.convert_y(position[1])), int(position[0])] = -6 * ghost_multiplier board = self.value_iteration(state, board) # call value iteration expected_utility = self.calculate_expected_utility( state, board, board.convert_y(current_pos[1]), current_pos[0]) # returns action associated to the max utility out of all the legal actions. return api.makeMove( max([(utility, action) for utility, action in expected_utility if action in legal])[1], legal)
def runFromGhost(self, state): # Runs away from ghosts # # Returns any direction that moves pacman away from ghost # Removes option of going towards ghost # Makes random choice of remaining options self.update(state) # print "Running from ghosts" cur = api.whereAmI(state) ghosts = api.ghosts(state) legal = api.legalActions(state) legal.remove(Directions.STOP) for x in range(1, 4): #Ghost seen south of pacman if (cur[0], cur[1] - x) in ghosts: if Directions.SOUTH in legal: #Stop pacman from going south towards ghost if len(legal) > 1: legal.remove(Directions.SOUTH) #Let pacman go in any direction except south self.last = random.choice(legal) return self.last #Ghost seen west of pacman if (cur[0] - x, cur[1]) in ghosts: if Directions.WEST in legal: #Stop pacman from going west towards ghost if len(legal) > 1: legal.remove(Directions.WEST) #Let pacman go in any direction except west self.last = random.choice(legal) return self.last #Ghost seen north of pacman if (cur[0], cur[1] + x) in ghosts: if Directions.NORTH in legal: #Stop pacman going north towards ghost if len(legal) > 1: legal.remove(Directions.NORTH) #Let pacman go in any direction except south self.last = random.choice(legal) return self.last #Ghost seen east of pacman if (cur[0] + x, cur[1]) in ghosts: if Directions.EAST in legal: #Stop pacman going east towards ghost if len(legal) > 1: legal.remove(Directions.EAST) #Let pacman go in any direction except east self.last = random.choice(legal) return self.last self.last = random.choice(legal) return self.last
def registerInitialState(self, state): print "Running registerInitialState!" # Make a map of the right size self.makeMap(state) self.addWallsToMap(state) self.updateFoodInMap(state) self.map.display() #Run the value iteration 1000 times at the start as it will stabilise the values for later on self.updateUtilities(api.walls(state), api.food(state), api.ghosts(state), 1000, state) self.counter = 0
def map_negative(self, state, size): weight_negative = {} (map_x, map_y) = size ghost = api.ghosts(state) for i in range(map_x + 1): for j in range(map_y + 1): if (i, j) in ghost: weight_negative[(i, j)] = self.weight_ghost else: weight_negative[(i, j)] = self.weight_blank return weight_negative
def updateGhostsToMap(self, state): ghost = api.ghosts(state) for i in range(len(ghost)): if (api.ghostStates(state)[i][1] != 1): self.map.setValue(int(ghost[i][0]), int(ghost[i][1]), (-self.initialFood, 0)) self.aroundGhosts(int(ghost[i][0]), int(ghost[i][1]), -self.initialFood, 0) else: self.map.setValue(int(ghost[i][0]), int(ghost[i][1]), (-0.02, 0))
def ghost_value(direction, state): ghosts = api.ghosts(state) location = api.whereAmI(state) danger = 0 for ghost in ghosts: distance = util.manhattanDistance(location, ghost) if distance: danger += directional_weight(location, ghost)[direction] / distance else: danger += float('inf') return danger
def updateGhosts(self,state): ghosts = api.ghosts(state) ghostStatesWithTimes= api.ghostStatesWithTimes(state) for g in ghostStatesWithTimes: ghostVal = 1.2*g[1]-20 self.map.setValue(int(g[0][0]),int(g[0][1]),ghostVal) #g[0] here is the coordinates of the respective ghost # and g[1] is how much time till ghosts revert from edible state to hunting pacman # with 0 being not edible anymore self.dankMap =self.map #update map to dankMap
def getAction(self, state): ghosts = api.ghosts(state) self.map.updatePunishments(ghosts) location = api.whereAmI(state) self.map.updateRewards(location) self.map.updateUtilities() legal = api.legalActions(state) if CAN_STOP: if Directions.STOP in legal: legal.remove(Directions.STOP) return api.makeMove(self.map.optimalMove(location, legal), legal)
def updateMap(self, state): ghost = api.ghosts(state) ghostStates = api.ghostStates(state) capsule = api.capsules(state) food = api.food(state) wall = api.walls(state) for node in self.mapDictionary: if node in wall: self.mapDictionary.update({node: 'X'}) return self.mapDictionary
def value_iteration(self, state, board): """ The function to carry out value iteration. Parameters: board (Board): Chosen board to use. Returns: Board: Board with updated utility values stored in each cell of board. """ board_copy = copy.deepcopy(board) # Positions where value stored should not be altered. ghosts = api.ghosts(state) gamma = 0.9 iterations = 10 threshold = 0.01 convergence = False height = board_copy.get_board_height() width = board_copy.get_board_width() iterations = 15 while iterations > 0: # while True: U = copy.deepcopy(board_copy) totalDifference = 0 for row in range(height): for col in range(width): value = board_copy[row, col] if isinstance(value, numbers.Number) and ( col, (height - 1) - row) not in ghosts: # Check to make sure this position is not where a wall or a ghost is. expected_utility = [ utility[0] for utility in self.calculate_expected_utility( state, U, row, col) ] max_expected_utility = max(expected_utility) board_copy[row, col] = board[row, col] + \ gamma * max_expected_utility iterations -= 1 # for row in range(height): # for col in range(width): # value = board[row, col] # if isinstance(value, numbers.Number) and (col, (height - 1) - row) not in ghosts: # totalDifference += round(value - U[row, col], 4) # # if abs(totalDifference) <= threshold: # break return board_copy
def getAction(self, state): moves = api.legalActions(state) if Directions.STOP in moves: moves.remove(Directions.STOP) successors = [(state.generateSuccessor(0, action), action) for action in moves] scores = [(self.ghostScore(api.whereAmI(state), api.ghosts(state)), action) for state, action in successors] bestScore = max(scores)[0] bestActions = [pair[1] for pair in scores if pair[0] == bestScore] return random.choice(bestActions)
def updateMap(self, state): corners = api.corners(state) ghosts = api.ghosts(state) me = api.whereAmI(state) walls = api.walls(state) capsules = api.capsules(state) foods = api.food(state) # Width and Height of Map width, height = corners[3][0] + 1, corners[3][1] + 1 # Generate empty world Map if (self.worldMap is None): self.worldMap = [[[' ', self.emptyReward, 0, Directions.STOP] for x in range(width)] for y in range(height)] self.setMap(me[0], me[1], ['M', self.meReward, 0, Directions.STOP]) for food in foods: self.setMap(food[0], food[1], ['F', self.foodReward, 0, Directions.STOP]) for capsule in capsules: self.setMap(capsule[0], capsule[1], ['C', self.capsuleReward, 0, Directions.STOP]) for wall in walls: self.setMap(wall[0], wall[1], ['W', self.wallReward, 0, Directions.STOP]) for ghost in ghosts: self.setMap(ghost[0], ghost[1], ['G', self.ghostReward, 0, Directions.STOP]) else: self.clearMapKeepState(state) self.setThing(me[1], me[0], 'M') for food in foods: self.setThing(food[1], food[0], 'F') for capsule in capsules: self.setThing(capsule[1], capsule[0], 'C') for wall in walls: self.setThing(wall[1], wall[0], 'W') for ghost in ghosts: self.setThing(ghost[1], ghost[0], 'G') self.setReward(me[0], me[1], self.meReward) for food in foods: self.setReward(food[0], food[1], self.foodReward) for capsule in capsules: self.setReward(capsule[0], capsule[1], self.capsuleReward) for wall in walls: self.setReward(wall[0], wall[1], self.wallReward) for ghost in ghosts: self.setReward(ghost[0], ghost[1], self.ghostReward)
def getAction(self, state): # Get the actions we can try, and remove "STOP" if that is one of them. legal = api.legalActions(state) if Directions.STOP in legal: legal.remove(Directions.STOP) # Get current location of pacman pacman = api.whereAmI(state) # Get list of ghost locations ghosts = api.ghosts(state) # Compute manhattan distance to each ghost location ghostsDistances = [] for i in range(len(ghosts)): ghostsDistances.append(util.manhattanDistance(pacman, ghosts[i])) minDistance = min(ghostsDistances) print "Min Distance: ", minDistance minDistanceIndex = ghostsDistances.index(minDistance) print "Min Ghosts index: ", minDistanceIndex nearestGhost = ghosts[minDistanceIndex] print "Pacman: ", pacman print "Nearest Ghost: ", nearestGhost diffX = pacman[0] - nearestGhost[0] diffY = pacman[1] - nearestGhost[1] print "legal", legal print diffX, diffY moveX = Directions.STOP moveY = Directions.STOP # Determine whether to move east or west if diffX >= 0: print "Go right" moveX = Directions.EAST elif diffX < 0: print "Go left" moveX = Directions.WEST # Determine whether to move north or south if diffY >= 0: print "Go up" moveY = Directions.NORTH elif diffY < 0: print "Go down" moveY = Directions.SOUTH # Determine whether to move in X or Y print "diffX: ", diffX, " diffY", diffY if abs(diffX) >= abs(diffY) and moveX in legal: return api.makeMove(moveX, legal) elif abs(diffY) >= 0 and moveY in legal: return api.makeMove(moveY, legal) elif abs(diffX) >= 0 and moveX in legal: return api.makeMove(moveX, legal) else: return api.makeMove(random.choice(legal), legal)
def value_iteration(self, state, board): """ The function to carry out value iteration. Parameters: board (Board): Chosen board to use. Returns: Board: Board with updated utility values stored in each cell of board. """ board_copy = copy.deepcopy(board) gamma = 0.9 # discount factor iterations = 14 # max number of iterations threshold = 0.1 # Positions where value stored should not be altered. protected_pos = api.ghosts(state) + api.walls(state) while iterations > 0: U = copy.deepcopy(board_copy) # total differences between previous board and new board which has been made # at the end of the iteration total_difference = 0 for row in range(self.height): for col in range(self.width): value = board_copy[row, col] # Check to make sure this position is not where a wall or a ghost is. if (col, board.convert_y(row)) not in protected_pos: # just take the utility from the list returned by calculate_expected_utility expected_utility = [ utility[0] for utility in self.calculate_expected_utility( state, U, row, col) ] max_expected_utility = max(expected_utility) board_copy[row, col] = board[row, col] + gamma * \ max_expected_utility # Bellman's equation # calculate differences for each position using the old board(U) and new board(board_copy) for row in range(self.height): for col in range(self.width): if (col, board.convert_y(row)) not in protected_pos: value = board_copy[row, col] total_difference += abs(round(value - U[row, col], 4)) if total_difference <= threshold: break iterations -= 1 return board_copy
def getAction(self, state): legal = api.legalActions(state) if Directions.STOP in legal: legal.remove(Directions.STOP) coners = api.corners(state) pacman = api.whereAmI(state) food = api.food(state) Capsules = api.capsules(state) ghosts = api.ghosts(state) if len(self.detected) == 0: self.states.push((pacman, Directions.STOP)) if not self.states.isEmpty(): self.detected.append(pacman) success_node = [] for directs in legal: if directs == Directions.WEST: success_node.append((pacman[0] - 1, pacman[1])) if directs == Directions.EAST: success_node.append((pacman[0] + 1, pacman[1])) if directs == Directions.NORTH: success_node.append((pacman[0], pacman[1] + 1)) if directs == Directions.SOUTH: success_node.append((pacman[0], pacman[1] - 1)) for index in range(len(success_node)): if not success_node[index] in self.detected and ( success_node[index] in food or success_node[index] in Capsules): self.states.push((success_node[index], legal[index])) return (api.makeMove(legal[index], legal)) last, acted = self.states.pop() if acted == Directions.NORTH: return (api.makeMove(Directions.SOUTH, legal)) if acted == Directions.SOUTH: return (api.makeMove(Directions.NORTH, legal)) if acted == Directions.WEST: return (api.makeMove(Directions.EAST, legal)) if acted == Directions.EAST: return (api.makeMove(Directions.WEST, legal)) return (api.makeMove(Directions.STOP, legal))
def ghostRegion1(self,state): ghosts = api.ghosts(state) region1 = [] # for loop creates a list of lists for k in range(len(ghosts)): region1.append(self.getSuccessor(state, ghosts[k][0], ghosts[k][1])) # Create a list containing every element in the previously created list of lists flat_list = [item for sublist in region1 for item in sublist] # Remove any duplicates in the list flat_list = list(set(flat_list)) return flat_list
def bellmanUpdate( self, state ): #preforms bellmans over the entire map using bellmans equation on each cell ghostList = api.ghosts(state) foodList = api.food(state) wallList = api.walls(state) scaredTime = api.ghostStatesWithTimes(state)[0][1] capsuleList = api.capsules(state) width = self.map.width height = self.map.height done = False while not done: #loops over map preforming bellmans until previous map from the last iteration is equal to the map at the end of the new iteration oldMap = deepcopy(self.map) for x in range(0, width): for y in range(0, height): if oldMap[x][y] != None: bestUtil = -1000 moves = [ oldMap[x][y + 1], oldMap[x + 1][y], oldMap[x][y - 1], oldMap[x - 1][y] ] # list of all possible moves from the current cell for i in range( len(moves) ): # finds the best util possible based on all legal moves to uses in value iteration if moves[i] != None: tutil = moves[i] * 0.8 if moves[i - 1] != None: tutil += moves[i - 1] * 0.1 else: tutil += oldMap[x][y] * 0.1 if moves[(i + 1) % 4] != None: tutil += moves[(i + 1) % 4] * 0.1 else: tutil += oldMap[x][y] * 0.1 if tutil > bestUtil: bestUtil = deepcopy(tutil) self.map[x][y] = (bestUtil * 0.9) + self.reward( x, y, state, ghostList, foodList, capsuleList, scaredTime, wallList) #bellmans equation using rewards functon done = self.checkSame( oldMap, self.map ) #checks to see whether old map is the same as new map
def getAction(self, state): #Initialise all variables walls = api.walls(state) ghostArray = api.ghosts(state) food = api.food(state) legal = api.legalActions(state) #Run value iteration and update the map self.valueIteration(walls, food, ghostArray, state) #Get the direction based on MEU direction = self.getNextMoveBasedOnMEU(state) #return with a move return api.makeMove(direction, legal)