def getFeatures(self, state, action): # extract the grid of food and wall locations and get the ghost locations food = state.getFood() walls = state.getWalls() ghosts = state.getGhostPositions() features = CustomCounter() features["bias"] = 1.0 # compute the location of pacman after he takes the action x, y = state.getPacmanPosition() # features["pacman"] = [x, y] dx, dy = Actions.directionToVector(action) next_x, next_y = int(x + dx), int(y + dy) # count the number of ghosts 1-step away features["#-of-ghosts-1-step-away"] = sum( (next_x, next_y) in Actions.getLegalNeighbors(g, walls) for g in ghosts) # if there is no danger of ghosts then add the food feature if not features["#-of-ghosts-1-step-away"] and food[next_x][next_y]: features["eats-food"] = 1.0 dist, pos_x, pos_y = closestFood((next_x, next_y), food, walls) if dist is not None: # make the distance a number less than one otherwise the update # will diverge wildly features["closest-food"] = round( float(dist) / (walls.width * walls.height), 5) # features["dist"] = dist # features["food-location"] = [pos_x, pos_y] # features.divideAll(10.0) return features
def distance_to_the_nearest_item_from_list(pos, items_positions, walls, cutout=3): """ returns the distance to the item from items_positions (ghosts, capsules,...) cutout is used to stop searching when distance is getting higher than cutout value """ fringe = [(pos[0], pos[1], 0)] expanded = set() while fringe: pos_x, pos_y, dist = fringe.pop(0) if (pos_x, pos_y) in expanded: continue if dist > cutout: continue expanded.add((pos_x, pos_y)) # if we find a food at this location then exit if (pos_x, pos_y) in items_positions: return dist # otherwise spread out from the location to its neighbours nbrs = Actions.getLegalNeighbors((pos_x, pos_y), walls) for nbr_x, nbr_y in nbrs: if nbr_x == pos[0] and nbr_y == pos[ 1] or nbr_x == pos_x and nbr_y == pos_y: continue fringe.append((nbr_x, nbr_y, dist + 1)) # no ghost found return None
def getFeatures(self, state, action): # extract the grid of food and wall locations and get the ghost locations food = state.getFood() walls = state.getWalls() ghosts = state.getGhostPositions() features = CustomCounter() features["bias"] = 1.0 # compute the location of pacman after he takes the action x, y = state.getPacmanPosition() dx, dy = Actions.directionToVector(action) next_x, next_y = int(x + dx), int(y + dy) # count the number of ghosts 1-step away # get position of ghost only when it is not scared # in this way pacman may learn to eat scared ghost features["#-of-ghosts-1-step-away"] = sum( (next_x, next_y) in Actions.getLegalNeighbors(g_s.getPosition(), walls) for g_s in state.getGhostStates() if not g_s.scaredTimer) # if there is no danger of ghosts then add the food feature if not features["#-of-ghosts-1-step-away"] and food[next_x][next_y]: features["eats-food"] = 1.0 else: features["eats-food"] = 0.0 dist = closestFood((next_x, next_y), food, walls) if dist is not None: # make the distance a number less than one otherwise the update # will diverge wildly features["closest-food"] = float(dist) / (walls.width * walls.height) features.divideAll(10.0) return features
def closestFood(pos, food, walls): fringe = [(pos[0], pos[1], 0)] expanded = set() while fringe: pos_x, pos_y, dist = fringe.pop(0) if (pos_x, pos_y) in expanded: continue expanded.add((pos_x, pos_y)) # if we find a food at this location then exit if food[pos_x][pos_y]: return dist, pos_x, pos_y # otherwise spread out from the location to its neighbours nbrs = Actions.getLegalNeighbors((pos_x, pos_y), walls) for nbr_x, nbr_y in nbrs: fringe.append((nbr_x, nbr_y, dist + 1)) # no food found return None
def closest_cell(pos, cells, walls): dists = {c: -1 for c in cells} fringe = [(pos[0], pos[1], 0)] expanded = set() while fringe: pos_x, pos_y, dist = fringe.pop(0) if (pos_x, pos_y) in expanded: continue expanded.add((pos_x, pos_y)) if (pos_x, pos_y) in cells: if dists[(pos_x, pos_y)] == -1: dists[(pos_x, pos_y)] = dist if all([v != -1 for v in dists.values()]): break nbrs = Actions.getLegalNeighbors((pos_x, pos_y), walls) for nbr_x, nbr_y in nbrs: fringe.append((nbr_x, nbr_y, dist + 1)) return min(list(dists.items()), key=lambda cd: cd[1])
def closestFood(pos, food, walls): """ closestFood -- this is similar to the function that we have worked on in the search project; here its all in one place """ fringe = [(pos[0], pos[1], 0)] expanded = set() while fringe: pos_x, pos_y, dist = fringe.pop(0) if (pos_x, pos_y) in expanded: continue expanded.add((pos_x, pos_y)) # if we find a food at this location then exit if food[pos_x][pos_y]: return dist # otherwise spread out from the location to its neighbours nbrs = Actions.getLegalNeighbors((pos_x, pos_y), walls) for nbr_x, nbr_y in nbrs: fringe.append((nbr_x, nbr_y, dist + 1)) # no food found return None
def getFeatures(self, state, action): # extract the grid of food and wall locations and get the ghost locations food = state.getFood() walls = state.getWalls() ghosts = state.getGhostPositions() features = CustomCounter() features["bias"] = 1.0 # compute the location of pacman after he takes the action x, y = state.getPacmanPosition() dx, dy = Actions.directionToVector(action) next_x, next_y = int(x + dx), int(y + dy) not_scared_ghosts_positions = [ g_s.getPosition() for g_s in state.getGhostStates() if not g_s.scaredTimer ] # count the number of ghosts 1-step away # get position of ghost only when it is not scared # in this way pacman may learn to eat scared ghost features["#-of-ghosts-1-step-away"] = sum( (next_x, next_y) in Actions.getLegalNeighbors(g_s, walls) for g_s in not_scared_ghosts_positions) # ghost_quarters = [get_quarter_from_position(ghost_position, walls) # for ghost_position in state.getGhostPositions()] # # if all(ghost_quarters) == get_quarter_from_position((x, y), walls): # features['pacman-and-ghosts-in-the-same-region'] = 1.0 # else: # features['pacman-and-ghosts-in-the-same-region'] = 0.0 ghost_distance_limit = 3 nearest_ghost = distance_to_the_nearest_item_from_list( (next_x, next_y), not_scared_ghosts_positions, walls, cutout=3) if nearest_ghost is not None: nearest_ghost = max(nearest_ghost - 1, 0) if nearest_ghost < 1: features['ghost-is-nearby'] = 1 else: features['ghost-is-nearby'] = ( ghost_distance_limit - nearest_ghost) / ghost_distance_limit else: features['ghost-is-nearby'] = 0 # nearest_capsule = distance_to_the_nearest_item_from_list((next_x, next_y), state.getCapsules(), walls, cutout=0) ## set 1.0 if the nearest capsule is closer than the nearest ghost # if nearest_capsule is not None and nearest_ghost is None or \ # nearest_capsule is not None and nearest_ghost is not None and nearest_capsule < nearest_ghost: # features["capsule-is-nearby"] = 1.0 # features["capsule-is-nearby"] = 1.0 if nearest_capsule is not None else 0.0 # if there is no danger of ghosts then add the food feature if not features["#-of-ghosts-1-step-away"] and food[next_x][next_y]: features["eats-food"] = 1.0 else: features["eats-food"] = 0.0 dist = closestFood((next_x, next_y), food, walls) if dist is not None: # make the distance a number less than one otherwise the update # will diverge wildly features["closest-food"] = float(dist) / (walls.width * walls.height) features.divideAll(10.0) return features
def getFeatures(self, state, action): # extract the grid of food and wall locations and get the ghost locations food = state.getFood() walls = state.getWalls() ghosts = state.getGhostPositions() capsulesLeft = len(state.getCapsules()) scaredGhost = [] activeGhost = [] features = CustomCounter() for ghost in state.getGhostStates(): if not ghost.scaredTimer: activeGhost.append(ghost) else: #print (ghost.scaredTimer) scaredGhost.append(ghost) pos = state.getPacmanPosition() def getManhattanDistances(ghosts): return map(lambda g: manhattan_distance(pos, g.getPosition()), ghosts) distanceToClosestActiveGhost = distanceToClosestScaredGhost = 0 features["bias"] = 1.0 # compute the location of pacman after he takes the action x, y = state.getPacmanPosition() dx, dy = Actions.directionToVector(action) next_x, next_y = int(x + dx), int(y + dy) # count the number of ghosts 1-step away features["#-of-ghosts-1-step-away"] = sum( (next_x, next_y) in Actions.getLegalNeighbors(g, walls) for g in ghosts) # if there is no danger of ghosts then add the food feature if not features["#-of-ghosts-1-step-away"] and food[next_x][next_y]: features["eats-food"] = 1.0 dist = closestFood((next_x, next_y), food, walls) if dist is not None: # make the distance a number less than one otherwise the update # will diverge wildly features["closest-food"] = float(dist) / (walls.width * walls.height) if scaredGhost: # and not activeGhost: distanceToClosestScaredGhost = min( getManhattanDistances(scaredGhost)) if activeGhost: distanceToClosestActiveGhost = min( getManhattanDistances(activeGhost)) else: distanceToClosestActiveGhost = 10 features["capsules"] = capsulesLeft #features["dist-to-closest-active-ghost"] = 2*(1./distanceToClosestActiveGhost) if distanceToClosestScaredGhost <= 8 and distanceToClosestActiveGhost >= 2: #features["#-of-ghosts-1-step-away"] >= 1: features["#-of-ghosts-1-step-away"] = 0 features["eats-food"] = 0.0 #features["closest-food"] = 0 features.divideAll(10.0) return features