def configuration(self, turns): ''' this is going to configure the snake in n-d given segment lengths and list of oriented angles between the segments if the snake would intercept itself, return an Overlap exception if it doesn't overlap, return shape. First segment always goes horizontally (from coordinates [0, 0] to [length-1,0]), then turns specify left or right turns. ''' head = (0, 0, 0) conf = set([head]) d = Direction(1, 0, 0) #step first, then turn (so dummy turn at the end doesn't matter) for length, turn in zip(self.lengths, turns+[Rotation.CLOCKWISE]): for step in range(length): next = d.step(head) #print "Head is {1}, Next is {0}, dir={2} turn={3}".format(next, head, d, turn) if next in conf: raise OverlapException('Overlap at {0}'.format(next)) conf.add(next) head = next d.turn(turn) return conf
def check_distance(self, world): """ Checks the if there is an object is within the vision cone. Does not return coordinates! Args:\n world - The 3d list of the world. Returns:\n Normalized distance to the closest object (0-1). 1 if there is no object in range. """ if isinstance(self.x, float) or isinstance( self.y, float) or isinstance(self.z, float): print( "Matt, you screwed up somewhere. Why is the sensor coordinates a float" ) shortest_distance = 1 #Right now is starting from coordnates 1 for i in range(1, self.view_distance + 1): #Forward-Back for j in range(-1 * math.floor(self.view_height / 2), math.floor(self.view_height / 2) + 1): #Up-Down for k in range(-1 * math.floor(self.view_width / 2), math.floor(self.view_width / 2) + 1): #Left-Right coords = Direction.calculate_coords( self.direction, i, self.x, self.y, self.z) d = Direction.calculate_distance(self.direction, self.x, self.y, self.z, coords[0], coords[1], coords[2]) if (not (coords[0] >= len(world.tunnel_world)) and not world.check_space(coords)): temp = d / self.view_distance if (temp < shortest_distance): shortest_distance = temp return shortest_distance
def _go_to_max(self): """Return to the location of the largest focus value seen so far and perform a local search to find the exact location of the peak.""" current_pos = self.camera.last_position() maximum_pos = max(self.camera.visited_positions, key=(lambda pos : self.camera.get_fvalue(pos))) if maximum_pos < current_pos: direction = Direction("left") elif maximum_pos > current_pos: direction = Direction("right") elif current_pos < self.camera.visited_positions[-2]: direction = Direction("left") else: direction = Direction("right") rev_direction = direction.reverse() # Take as many coarse steps as needed to go back to the maximum # without going over it. distance = abs(current_pos - maximum_pos) coarse_steps = distance / 8 self.camera.move_coarse(direction, coarse_steps) # Keep going in fine steps to see if we can find a higher position. start_pos = self.camera.last_position() self._do_local_search(direction, rev_direction) # If we didn't move further, we might want to look in the other # direction too. if start_pos == self.camera.last_position(): self._do_local_search(rev_direction, direction) self.status = "foundmax"
def next_fig(self, direct: str) -> Any: """Dynamically generate next Figure. Arguments: direct (str): direction ('UP', 'DOWN', 'LEFT', 'RIGHT') Returns: Any: Figure or a subclass of Figure object """ if direct == 'UP': offset = Direction(self.base).up_offset() # up offset-Figure elif direct == 'DOWN': offset = Direction(self.base).down_offset() # down offset-Figure elif direct == 'LEFT': offset = Direction(self.base).left_offset() # left offset-Figure elif direct == 'RIGHT': offset = Direction(self.base).right_offset() # right offset-Figure else: # TODO more elegant handler print(f'warning: received invalid {direct}') next_one = self.base + offset # calculate next Figure # dynamically geneate next Figure or subclass of Figure object return type(self.base)(next_one.x, next_one.y, next_one.size, next_one.color)
class Ant(object): def __init__(self, n): self.board = Board(n) self.i = int(n) / 2 self.j = int(n) / 2 self.d = Direction() def step(self): if self.board[self.i, self.j]: # Square is black self.d.turn_right() else: # Square is white self.d.turn_left() self.board.flip(self.i, self.j) self._move_forward() def _move_forward(self): i, j = self.i, self.j board = self.board if self.d == 'up': self.i, self.j = board.move_up(i, j) elif self.d == 'right': self.i, self.j = board.move_right(i, j) elif self.d == 'down': self.i, self.j = board.move_down(i, j) else: self.i, self.j = board.move_left(i, j) def __repr__(self): s = 'Ant(i={}, j={})'.format(self.i, self.j) return s + '\n' + str(self.board)
def initialize_directions(self): """initializes each of the 4 direction objects""" self.up = Direction((0, -1)) self.right = Direction((1, 0)) self.down = Direction((0, 1)) self.left = Direction((-1, 0)) self.current_direction = None
def test_place(self): test_pacman = Pacman() result_pacman = Pacman(direction=Direction(1.0, 2.0), facing=0.5, grid=grid, orientations=orientations) test_pacman = test_pacman.place(direction=Direction(0.0, 0.0), facing=0.0, grid=grid) test_pacman.__eq__(result_pacman)
def change(self, dir: Direction): if dir.get_direction() == Direction.SOUTH: self.row += 1 elif dir.get_direction() == Direction.EAST: self.col += 1 elif dir.get_direction() == Direction.NORTH: self.row -= 1 elif dir.get_direction() == Direction.WEST: self.col -= 1 return self
def __init__(self, inputManager, updateManager, graphicsManager, soundManager, networkManager, filedesc): self.world = World() self.worldView = WorldView(self.world) self.iMngr = inputManager self.uMngr = updateManager self.gMngr = graphicsManager self.sMngr = soundManager self.nMngr = networkManager self.connection = filedesc self.isRunning = True self.ownPlayer = Player(Direction((2,0)), Position(50, 50),Direction((2,0)))
def __init__(self, screen_temp): image = pygame.image.load("./feiji/hero1.png") BasePlane.__init__( self, screen_temp, 240 - image.get_rect().width / 2, 630, "./feiji/hero1.png") self.dir = Direction()
def test_move(self): test_pacman = Pacman(direction=Direction(0.0, 0.0), facing=0.0, grid=grid, orientations=orientations) test_pacman = test_pacman.move() result_pacman = Pacman(direction=Direction(0.0, 1.0), facing=0.0, grid=grid, orientations=orientations) test_pacman.__eq__(result_pacman)
def start(self): ''' Start the A star algorithm ''' expansion_count = 0 while not self.open_set.empty(): current = self.open_set.get() # print "Expanding node {0}".format(current) expansion_count += 1 # If we reached the goal, stop if current == self.world.goal: break evaluator = Agent(current, self.facing[current], self.heuristic_num, self.world) for next in self.world.get_adjacent_cells(current): # Tally total cost g_score = self.cost_so_far[current] \ + evaluator.forward(next) + evaluator.turn(next) # Consider the adjacent node, 'next'... if next not in self.cost_so_far or g_score < self.cost_so_far[next]: self.cost_so_far[next] = g_score h_score = evaluator.estimate(next, self.world.goal) f_score = g_score + h_score #Add the node to the priority queue self.open_set.put(next, f_score) #Save the direction the node is facing new_dir = Direction().set_dir(Direction.vector(current, next)) self.facing[next] = new_dir turn_string = "turn," * evaluator.dir.count_turns_needed(current, next) self.actions_taken[next] = turn_string + "forward" #Add the node to the path of traversed nodes self.came_from[next] = current for bash_cell in self.world.get_bashable_cells(current): g_score = self.cost_so_far[current] \ + evaluator.bash(bash_cell) + evaluator.turn(bash_cell) #Consider the bash node, next if bash_cell not in self.cost_so_far or g_score < self.cost_so_far[bash_cell]: self.cost_so_far[bash_cell] = g_score h_score = evaluator.estimate(bash_cell, self.world.goal) f_score = g_score + h_score self.open_set.put(bash_cell, f_score) new_dir = Direction().set_dir(Direction.vector(current, bash_cell)) self.facing[bash_cell] = new_dir turn_string = "turn," * evaluator.dir.count_turns_needed(current, bash_cell) self.actions_taken[bash_cell] = turn_string + "bash,forward," self.came_from[bash_cell] = current score = 100 - self.cost_so_far[self.world.goal] self.trace_path() self.output(score, expansion_count)
def find_direction(self): """ This is an example of direction solver subroutine.""" _direction = Direction('NULL').to_string() if self._board.is_my_bomberman_dead(): print("Bomberman is dead. Sending 'NULL' command...") return _direction # here's how we find the current Point of our bomberman _bm = self._board.get_bomberman() _bm_x, _bm_y = _bm.get_x(), _bm.get_y() # Let's check whether our bomberman is not surrounded by walls if 4 == self._board.count_near(_bm_x, _bm_y, Element('DESTROY_WALL')): print("It seems like walls surround you. Self-destroying.") return Direction('ACT').to_string() # Let's drop a bomb then #print(self._board.to_string()) print("Found your Bomberman at {}".format(_bm)) #put the bomb near something that could blow if self._board.is_at(_bm_x, _bm_y, Element('BOMB_BOMBERMAN')): print("Run") else: print("Lets watch out") _targets = self._board.get_targets() for target in _targets: target_element = self._board.get_at(target.get_x(), target.get_y()) if self._board.is_near(_bm_x, _bm_y, target_element): print("Seems we've got the target, lets drop the bomb!".format(target_element)) return Direction('ACT').to_string() # Let's drop a bomb then # here's how we get the list of barriers Points _barriers = self._board.get_barriers() _deadline = time() + 30 while time() < _deadline: # here we get the random direction choise __dir = Direction(choice(('LEFT', 'RIGHT', 'DOWN', 'UP'))) # now we calculate the coordinates of potential point to go _x, _y = __dir.change_x(_bm.get_x()), __dir.change_y(_bm.get_y()) # if there's no barrier at random point if not self._board.is_barrier_at(_x, _y): # here we count the attempt to choose the way self._count += 1 # and check whether it's not the one we just came from if not self._last == (_x, _y) or self._count > 5: # but we will go back if there were no others twice _direction = __dir.to_string() self._last = _bm.get_x(), _bm.get_y() self._count = 0 break else: # it seem that we are surrounded print("It's long time passed. Let's drop a bomb") _direction = Direction('ACT').to_string() # let's drop a bomb :) return _direction
def __init__(self): min = Point(0, 10) max = Point(self.width - 1, self.height - 1) pyxel.init(self.width, self.height, caption=self.title, fps=18) pyxel.load("my_resource.pyxres") self.snake = Snake(self.width / 2, self.height / 2) self.fruits = [ Fruit(min, max, 8), Fruit(min, max, 9), Fruit(min, max, 10) ] self.direction = Direction() self._reset() pyxel.run(self.update, self.draw)
def get(self, board_string): """ The method that should be implemented.""" self._board = Board(board_string) _command = Direction('ACT').to_string() print("Sending Command {}".format(_command)) return _command
def build(self): """ Building the maze is implemented as a coroutine to allow the visualization of the build progress. """ self._start = np.zeros_like(self._rooms.shape) self._start[0] = random.randrange(self._rooms.shape[0]) position = self._start egress = Direction.South distance = 1 while position in self: room = self[position] room.egress = egress room.distance = distance yield position options = {} for direction in Direction.range(): if direction != egress: new_position = position + direction.offset() if new_position in self: if self.is_sealed(new_position): options[direction] = new_position if options: direction = random.choice(tuple(options.keys())) room.remove_wall(direction) position = options[direction] egress = direction.reverse() distance += 1 else: position += egress.offset() if position in self: egress = self[position].egress distance = self[position].distance
def once(self, state): if not util.packet_queue.empty(): return player = state.me() self.tryPutBomb(state, player) safe_map = state.game_map.safeMap() playerPos = util.coordToPos(player.x, player.y) gridX, gridY = util.posToGrid(playerPos) if safe_map[gridX][gridY]: return def __internal_safe(pos): gridX, gridY = util.posToGrid(pos) return safe_map[gridX][gridY] actions = search.bfs(state.game_map, playerPos, __internal_safe) move = actions[0] if state.moveValidForMe(actions[0]): self.goMove(player, move) else: # If unable to go to specified pos now, go to current center first centerX, centerY = util.posToCoord(playerPos) dx, dy = (centerX - player.x, centerY - player.y) self.goMove(player, Direction.byDistance(dx, dy))
def __init__(self, x=None, y=None, name=None): self.genes: Genes = Genes(x, y) self.body: BaseMonster = self.genes.phenotype # don't use male, female for gender # if random.randint(0, 1) == 1: # self.gender = True # else: # self.gender = False self.gender = self.genes.phenotype.gender self.directions: Direction = Direction() self.health = 100 self.food = 80 self.water = 80 self.maximum = 100 self.owner_id = 0 self.monster_id = 0 if name is None: # generate string consisting of three numbers (can be 003) self.name = str(random.randint(0, 9)) + str(random.randint( 0, 9)) + str(random.randint(0, 9)) self.alive = True
def params(self, values): BaseCommand.params.fset(self, values) try: self._position = Point(values[0], values[1]) self._direction = Direction(values[2]) except: raise InvalidParametersError("Invalid parameters for PLACE")
def _move_cell(self, cell: Cell): # find possible directions possible_directions = Direction.all_directions() for c in self.__cells: if c.column - cell.column == 0: if c.row - cell.row == 1: possible_directions.remove(Direction.DOWN) elif c.row - cell.row == -1: possible_directions.remove(Direction.UP) elif c.row - cell.row == 0: if c.column - cell.column == 1: possible_directions.remove(Direction.RIGHT) elif c.column - cell.column == -1: possible_directions.remove(Direction.LEFT) if cell.column == self._size - 1: possible_directions.remove(Direction.RIGHT) if cell.column == 0: possible_directions.remove(Direction.LEFT) if cell.row == self._size - 1: possible_directions.remove(Direction.DOWN) if cell.row == 0: possible_directions.remove(Direction.UP) # move if possible if len(possible_directions) == 0: return cell.move(list(possible_directions)[0])
def main(): if len(sys.argv) != 2: "please pass the file of the commands" exit(0) Commands = readFile(sys.argv[1]) orientations = ["NORTH", "EAST", "SOUTH", "WEST"] grid = Grid() pacman = Pacman(orientations=orientations) if "PLACE" not in Commands[0]: print("The first valid command to the pacman is a PLACE command, please specify it") elif "PLACE" in Commands[0]: for command in Commands: if "PLACE" in command: command_splitted = preprocessCommands(command) x_axis = float(command_splitted[0]) y_axis = float(command_splitted[1]) facing = command_splitted[2] orientations_index = orientations.index(facing) pacman_position = Direction(x_axis=x_axis, y_axis=y_axis) pacman = pacman.place(Direction=pacman_position,grid=grid,facing=orientations_index/2.0) else: pacman = getattr(pacman,command.lower())()
def __in_dead_end(self, pos): end = True for dir in range(4): # check all four directions if not self.__behind_wall_is_treated(pos, Direction(dir)): end = False break return end
def playGame(self): g = Game(); while not g.isGameOver(): print g.grid.fields; move = self.analyze(g); g.move(move); print "-> {}".format(Direction.getName(move)); print "----- Score {} ------------".format(g.score);
def check_touch(self, world): """ Returns: True if the sensor is touching something, False if the sensor is not. """ return (Direction.calculate_coords(self.direction, 1, self.x, self.y, self.z) == 1)
def _is_connected_from(self, direction): neighbour = self._get_neighbouring_symbol(direction) neighbour_port = neighbour.get_port( Direction.get_opposite_direction(direction)) if isinstance(self.get_port(direction), Input) and isinstance( neighbour_port, Output): return True return False
def setUp(self): self.north = Direction('north') self.south = Direction('south') self.west = Direction('west') self.pool_table = Item('pool table', 'A felt lined pool table', 100, 10) self.room1 = Location("Ballroom", "A well furnished ballroom") self.room1.add_item(self.pool_table) self.tv = Item('TV', 'The family television', 10, 50) self.couch = Item('couch', 'A comfy couch', 20, 100) self.room2 = Location("Family Room", "A well furnished family room") self.room2.add_item(self.couch) self.room2.add_item(self.tv) self.room1.add_exit(self.north, self.room2) self.room2.add_exit(self.south, self.room1) self.player = Player(location=self.room1, game=Game())
def readFile(fileName): nodes = list() count = 0 with open(fileName, 'r') as file: reader = csv.reader(file, delimiter=' ') for row in reader: if (len(row) > 1): id1 = int(row[0]) id2 = int(row[1]) direction = row[2] while (len(nodes) < id1 + 1 or len(nodes) < id2 + 1): nodes.append(node(count)) count += 1 direction = Direction.getDirection(direction) nodes[id1].addConnection(id2, direction) direction = Direction.getOppositeDirection(direction.name) nodes[id2].addConnection(id1, direction) return nodes
def find_direction(self): """ This is an example of direction solver subroutine.""" _direction = Direction('NULL').to_string() if self._board.is_my_snake_dead(): print("Snake is dead. Sending 'NULL' command...") return _direction # here's how we find the current Point of our snake head _bm = self._board.get_head() _bm_x, _bm_y = _bm.get_x(), _bm.get_y() # print("Snake head at {}".format(_bm)) print(self._board.to_string()) # TODO: Implement your logic here _dir = Direction(choice(('LEFT', 'RIGHT', 'DOWN', 'UP'))) _direction = _dir.to_string() self._last = _bm.get_x(), _bm.get_y() return _direction
def choose_direction(self): counter = 0 while counter := counter + 1: direction = Direction.get_direction(randrange(0, 4)) if self.__world.is_field_empty(self.__x + direction.value[1], self.__y + direction.value[0]): return direction if counter > 10000: raise Exception("bad world")
def change_direction(self, new_dir): """ Changes the direction the snake's head is travelling to new_dir. :param new_dir: a Direction object. """ # The snake cannot move in an opposite direction. If the direction does not changes, do nothing. if not Direction.is_opposite(self.last_head_motion, new_dir) and new_dir is not self.last_head_motion: self.motion[0] = new_dir self.turning_points[self.head] = new_dir
def suggest_direction(self): prob_accum = 0 probabilities = np.array([self.transition_probability(direction) for direction in Direction.to_list()]) prob_sum = np.sum(probabilities) r = random.uniform(0, prob_sum) for i, prob in enumerate(probabilities): prob_accum += prob if prob_accum > r: return Direction.to_list()[i], prob
def get_future_blasts(self): _bombs = set() _bombs.update(self.get_bombs()) _bombs.update(self._find_all(Element('OTHER_BOMB_BOMBERMAN'))) _points = set() for _bomb in _bombs: _bx, _by = _bomb.get_x(), _bomb.get_y() _points.add(_bomb) for _d in ('LEFT', 'RIGHT', 'DOWN', 'UP'): __dir = Direction(_d) __x, __y = _bx, _by for _ in range(3): __x, __y = __dir.change_x(__x), __dir.change_y(__y) __pt = Point(__x, __y) if not (__pt.is_bad(self._size) or __pt in self.get_walls()): break _points.add(__pt) return list(_points)
def exits(self): """ >>> Room().exits() [] >>> r= Room() >>> r.remove_wall(Direction.North) >>> r.exits() == [Direction.North] True """ return Direction.range(~self._walls)
def test_move_refuses_bad_position(): any_direction = Direction(dx=0, dy=1) with pytest.raises(AssertionError): move((-1, 0), any_direction) with pytest.raises(AssertionError): move((200, 0), any_direction) with pytest.raises(AssertionError): move((0, -10), any_direction) with pytest.raises(AssertionError): move((0, 300), any_direction)
def transition_probability(self, new_direction): pheromones = self.pheromone_map.map[self.ant.pos] l_p = self.length_probability(self.ant.direction, new_direction) prob_numerator = (pheromones[new_direction.value] ** self.pheromone_importance) * ( l_p ** self.length_importance) prob_denominator = 0 for direction in Direction.to_list(): l_p = self.length_probability(direction, new_direction) prob_denominator += (pheromones[direction.value] ** self.pheromone_importance) * ( l_p ** self.length_importance) return prob_numerator / prob_denominator
def __init__(self, s): m = regex.match(s) if m == None: print('Error invalid Message: #' + s + '#') return self.dest_x = int(m.group(1)) self.dest_y = int(m.group(2)) self.self_x = int(m.group(3)) self.self_y = int(m.group(4)) self.self_direction = Direction.from_str(m.group(5)) self.team = m.group(6) self.message = m.group(7)
def test_right(self): test_pacman_1 = Pacman(direction=Direction(0.0, 0.0), facing=1.5, grid=grid, orientations=orientations) result_pacman_1 = Pacman(direction=Direction(0.0, 0.0), facing=0.0, grid=grid, orientations=orientations) test_pacman_2 = Pacman(direction=Direction(0.0, 0.0), facing=2.5, grid=grid, orientations=orientations) result_pacman_2 = Pacman(direction=Direction(0.0, 0.0), facing=1.0, grid=grid, orientations=orientations) test_pacman_1.__eq__(result_pacman_1) test_pacman_2.__eq__(result_pacman_2)
def __init__(self, pheromone_map, pos=(0, 0), size=200): self.pos = pos self.pheromone_map = pheromone_map self.ants = [] for i in range(size): ant = Ant(colony_pos=pos, direction=random.choice(Direction.to_list())) ant.motion = Motion(pheromone_map=pheromone_map, ant=ant, direction_distr=[0.7, 0.2, 0.1], pheromone_importance=0.9) self.ants.append(ant)
def __init__(self, position, field, direction=None, reserves=None, channel=0): assert position is not None assert field is not None # Focused on a position AND a pixelel at that position self.position = copy(position) # !!! copy self.pixelelIndex = channel # defaults to first channel (R or GRAY) self.field = field # an automata knows its field if reserves is None: self._reserves = 0 else: self._reserves = reserves if direction is None: self.direction = Direction() else: self.direction = direction
def parse(db, raw_recipe): """parsing recipe download into recipe structure""" (raw_name, raw_ingredients, raw_directions) = raw_recipe tokenized_dirs = [ nltk.word_tokenize(d) for d in raw_directions] tagged_directions = [ nltk.pos_tag(d) for d in tokenized_dirs ] name = raw_name ingredients = [Ingredient.parse(db, i) for i in raw_ingredients] directions = [ Direction.parse(d, ingredients) for d in tagged_directions ] methods = Method.find_methods(directions) tok_text = [ word for d in tokenized_dirs for word in d ] tools = Tool.find_tools(tok_text) return Recipe(name, ingredients, tools, methods, directions)
def search_standard(scenes, scene_to_print): print ("Perform a standard hill-climbing search, where coarse steps are\n" "taken until some stopping condition occurs, at which point the\n" "movement is reversed, at which point fine steps are taken to\n" "maximize the focus value. This is the method described in\n" "[He2003] and [Li2005].\n\n" "To visualize the steps taken for simulation of a specific scene,\n" "use the command-line argument --scene-to-print=something.txt") step_size = 8 data_rows = [("filename", "success %", "steps")] # Redirect stdout to a file for printing R script. orig_stdout = sys.stdout file_to_print = open("comparison.R", "w+") sys.stdout = file_to_print total_success = 0 for scene in scenes: success_count = 0 total_step_count = 0 initial_positions = range(0, scene.step_count - step_size) for initial_position in initial_positions: camera = CameraModel(scene, initial_position, simulate_backlash=simulate_backlash, simulate_noise=simulate_noise) first_measure = camera.last_fmeasure() camera.move_coarse(Direction("right")) # Determine whether to start moving left or right. if camera.last_fmeasure() < first_measure: direction = Direction("left") else: direction = Direction("right") # If the first step decreases focus value, switch direction. # This is a simple backtracking, basically. first_measure = camera.last_fmeasure() camera.move_coarse(direction) if camera.last_fmeasure() < first_measure: direction = direction.reverse() # Sweep max_value = camera.last_fmeasure() while not camera.will_hit_edge(direction): camera.move_coarse(direction) max_value = max(max_value, camera.last_fmeasure()) # Have we found a peak? if camera.last_fmeasure() < max_value * 0.9: # Stop searching break # Hillclimb until we're back at the peak. while not camera.will_hit_edge(direction.reverse()): prev_measure = camera.last_fmeasure() camera.move_fine(direction.reverse()) if prev_measure > camera.last_fmeasure(): camera.move_fine(direction) break # Record if we succeeded. if scene.distance_to_closest_peak(camera.last_position()) <= 1: success_count += 1 evaluation = "succeeded" else: evaluation = "failed" if scene.filename == scene_to_print: camera.print_script(evaluation) total_step_count += camera.steps_taken success = float(success_count) / len(initial_positions) * 100 line = (scene.name, "%.1f" % success, "%.1f" % (float(total_step_count) / len(initial_positions))) data_rows.append(line) total_success += success # Restore original stdout sys.stdout = orig_stdout file_to_print.close() print_aligned_data_rows(data_rows) print "average success : %.1f" % (total_success / len(scenes))
def __init__(self, n): self.board = Board(n) self.i = int(n) / 2 self.j = int(n) / 2 self.d = Direction()
class Flow: ''' Represents TCP traffic across a given socket, ideally between a TCP handshake and clean connection termination. Members: * fwd, rev = tcp.Direction, both sides of the communication stream * socket = ((srcip, sport), (dstip, dport)). Used for checking the direction of packets. Taken from SYN or first packet. * packets = list of tcp.Packet's, all packets in the flow * handshake = None or (syn, synack, ack) or False. None while a handshake is still being searched for, False when we've given up on finding it. ''' def __init__(self): self.fwd = Direction(self) self.rev = Direction(self) self.handshake = None self.socket = None self.packets = [] def add(self, pkt): ''' called for every packet coming in, instead of iterating through a list ''' # maintain an invariant that packets are ordered by ts; # perform ordered insertion (as in insertion sort) if they're # not in order because sometimes libpcap writes packets out of # order. # the correct position for pkt is found by looping i from # len(self.packets) descending back to 0 (inclusive); # normally, this loop will only run for one iteration. for i in xrange(len(self.packets), -1, -1): # pkt is at the correct position if it is at the # beginning, or if it is >= the packet at its previous # position. if i == 0 or self.packets[i - 1].ts <= pkt.ts: break self.packets.insert(i, pkt) # look out for handshake # add it to the appropriate direction, if we've found or given up on # finding handshake if self.handshake is not None: self.merge_pkt(pkt) else: # if handshake is None, we're still looking for a handshake if len(self.packets) > 13: # or something like that # give up self.handshake = False self.socket = self.packets[0].socket self.flush_packets() # merge all stored packets # check last three packets elif tcp.detect_handshake(self.packets[-3:]): # function handles packets < 3 case self.handshake = tuple(self.packets[-3:]) self.socket = self.handshake[0].socket self.flush_packets() def flush_packets(self): ''' Flush packet buffer by merging all packets into either fwd or rev. ''' for p in self.packets: self.merge_pkt(p) def merge_pkt(self, pkt): ''' Merges the packet into either the forward or reverse stream, depending on its direction. ''' if self.samedir(pkt): self.fwd.add(pkt) else: self.rev.add(pkt) def finish(self): ''' Notifies the flow that there are no more packets. This finalizes the handshake and socket, flushes any built-up packets, and calls finish on fwd and rev. ''' # handle the case where no handshake was detected if self.handshake is None: self.handshake = False self.socket = self.packets[0].socket self.flush_packets() self.fwd.finish() self.rev.finish() def samedir(self, pkt): ''' returns whether the passed packet is in the same direction as the assumed direction of the flow, which is either that of the SYN or the first packet. Raises RuntimeError if self.socket is None ''' if not self.socket: raise RuntimeError("called tcp.Flow.samedir before direction is determined") src, dst = pkt.socket if self.socket == (src, dst): return True elif self.socket == (dst, src): return False else: raise ValueError("TCPFlow.samedir found a packet from the wrong flow") def writeout_data(self, basename): ''' writes out the data in the flows to two files named basename-fwd.dat and basename-rev.dat. ''' f = open(basename + '-fwd.dat', 'wb') f.write(self.fwd.data) f.close() f = open(basename + '-rev.dat', 'wb') f.write(self.rev.data) f.close()
def __init__(self): self.fwd = Direction(self) self.rev = Direction(self) self.handshake = None self.socket = None self.packets = []
class Automata(object): """ Worm automata: it moves. Contrast with cellular automata, where each automata is usually stationary (on a cell of a grid.) A worm automata is like a single-celled, motile, biological organism. See 'Patterson worms': - move only one unit, in only 6 directions on a triangular grid - die if there is no food (no direction not already traversed.) - only one worm exists at a time This is different from a Patterson worm: - there can be many worms on the same field - they can divide - each worm can move in 8 directions on a rectangular grid. - worms can move off the field (wander), and then MIGHT wander back on to the field. - worms if starved can migrate (jump more than one step, in more than 8 directions), again even off the field - worms if starved don't die, they continue to move and migrate (they just don't poop.) Operates on an image, where image has 3 dimensions: 2D coord and 1D pixelel (channel) """ changeDirectionMethod = None @classmethod def setChangeDirectionMethod(cls, greedy): # Set behaviour by binding to one of two methods if greedy: Automata.changeDirectionMethod = Automata._greedyChangeDirection else: Automata.changeDirectionMethod = Automata._nonGreedyChangeDirection mouth = None @classmethod def setMouth(cls, grain, food): if grain == 0: # Single pixel mouth gives fine grain Automata.mouth = SinglePixelMouth(food) elif grain == 1: Automata.mouth = WideMouth(food) else: Automata.mouth = DeepMouth(food) def __init__(self, position, field, direction=None, reserves=None, channel=0): assert position is not None assert field is not None # Focused on a position AND a pixelel at that position self.position = copy(position) # !!! copy self.pixelelIndex = channel # defaults to first channel (R or GRAY) self.field = field # an automata knows its field if reserves is None: self._reserves = 0 else: self._reserves = reserves if direction is None: self.direction = Direction() else: self.direction = direction """ Most of this class is about position i.e. Coord only, but some methods need a pixelelID. """ def pixelelID(self): return PixelelID(self.position, self.pixelelIndex) def live(self): """ Behaviour: do every life cycle. !!! It is not invariant that current position is on the field. """ # eat and poop at current position, if it is on the field !!! mealConsumed = self.metabolize() self.tryPoop(mealConsumed) # Change direction just before move, otherwise other automata may swoop in and eat what I am greedily changing direction toward self.changeDirection() self.move() self.tryDivide() self.tryExhaustion(mealConsumed) def isEating(self): return self.field.food.isAvailableAt(self.pixelelID()) def isStarved(self): return self._reserves == 0 def setStarved(self): ##print("Starved", self.position) self._reserves = 0 def metabolize(self): """ Try to eat. Return mealConsumed. Adjust reserves. """ mealConsumed = self.field.food.eat(automata=self) # A mealConsumed larger than metabolic rate increases reserves. self._reserves += mealConsumed.calories() - config.burnCalories if self._reserves <= 0: self.setStarved() return mealConsumed def move(self): """ To adjacent pixel in self.direction. May move out of frame. """ self.position = self.position + self.direction.unitCoordFor() def migrate(self): """ To pixel a middle distance away, uniformly random, OR to a uniformly random coord on field. TODO 'middle distance' i.e. 15 should be a fraction of the image size In earlier designs, we allowed an automata to migrate off the field. The reasoning was, that would let automata migrate off and back on, and avoid edge effects. However, it probably wasted a lot of CPU cycles on automata off the field. So here, migration stays on field. Note that automata can still move off field, but then they exhaust, and then die or migrate. """ randomCoord = Coord(random.randint(-15, 15), random.randint(-15, 15)) self.position = self.position + randomCoord if self.field.food.pixmap.isClipped(self.position): self.position = self.field.randomCoordOn() ##print("migrate to", self.position) def changeDirection(self): """ Random direction change from set [ diagonally left of current direction, diagonally right of current direction] (Not hard left, or reverse.) """ # Call the method bound at init time # TODO subclasses and factories Automata.changeDirectionMethod(self) def _nonGreedyChangeDirection(self): """ Random direction change from set [ diagonally left of current direction, diagonally right of current direction] (Not hard left, or reverse.) """ self.direction.tweak() def _greedyChangeDirection(self): """ Greedy: choose direction toward more food. """ left, right = self.direction.fork() leftNeighbor = self.position + left.unitCoordFor() rightNeighbor = self.position + right.unitCoordFor() # TODO this biases toward right when neighbors equal # Identify self's pixelel at self's position leftPixelel = PixelelID(leftNeighbor, self.pixelelIndex) rightPixelel = PixelelID(rightNeighbor, self.pixelelIndex) if self.field.food.at(leftPixelel) > self.field.food.at(rightPixelel): self.direction = left else: self.direction = right def tryDivide(self): """ If self has enough reserves, and the field is not overpopulated, divide. """ if self._reserves > config.reservesToDivide and not self.field.isOverPopulated(): self.divide() def divide(self): """ Spawn a new automata. """ # Divide self's reserves evenly self._reserves /= 2 # integer divide # child and parent directions diverge, slightly left and right left, right = self.direction.fork() self.direction = left """ Create child, on same pixelel (position and channel.) Note we don't hardcode a class of automata, but ask field to create clone of correct subclass """ newAutomata = self.field.automataFactory.produce( position=self.position, channel=self.pixelelIndex, field=self.field, reserves=self._reserves, direction=right, ) ## ALTERNATIVE child move in opposite direction ## newAutomata.direction.setOpposite(self.direction) self.field.append(newAutomata) def tryExhaustion(self, mealConsumed): """ Test whether exhausted: starved and did not eat. Alternative: migrate if starved regardless whether we ate. """ if self.isStarved() and mealConsumed.isEmpty(): if config.exhaustion == 0: """ Perish: remove myself from population. Self will be garbage collected. Some other automate may repopulate (by dividing.) """ self.field.kill(self) else: self.migrate() def tryPoop(self, mealConsumed): """ Artifact of metabolism i.e. eating. Self need not be exhausted (might have reserves). But might not have just eaten (mealConsumed might be 0.) Self may have reserves but in some designs, might be wandered off field. Whether current position has food, is on the field, etc. depends on the order in which sub-behaviours are called. TODO mealConsumed is what I consumed this period, not what is in my gut from last period. """ # if self.isEating(): """ Note we may have just eaten, but could still be starved, if we did not eat enough to equal our daily metabolism. """ ##self._poopMealIfNotStarved(mealConsumed) self._poopMealIfAte(mealConsumed) # Alternative 1 def _poopMealIfNotStarved(self, mealConsumed): """ Poop mealConsumed if not starved. Not true to life as we know it: - should poop yesterday's mealConsumed. - should poop if gut is not empty, regardless of starving state """ if not self.isStarved(): # !!! Cannot assert: not isClipped(self.position) self.field.artifacts.depositAt(self, amount=mealConsumed) # Alternative 2 def _poopMealIfAte(self, mealConsumed): """ Deposit mealConsumed if it has portions in my channel at my position. (That's what not isEssentiallyEmpty() means.) Some mouths make non-empty meals that don't have a portion in my channel at my position. Don't deposit if mealConsumed.isEssentiallyEmpty() since some compose methods might ignore amount of mealConsumed e.g. maximize """ if not mealConsumed.isEssentiallyEmpty(): self.field.artifacts.depositAt(self, meal=mealConsumed)