Esempio n. 1
0
class MineSweeper(object):
    '''
    The minesweeper class.
    '''
    def __init__(self):
        self.brain = NeuralNet(settings.NUM_INPUTS, settings.NUM_OUTPUTS,
                               settings.NUM_HIDDEN,
                               settings.NEURONS_PER_HIDDEN)

        self.position = Vector2D(random() * settings.WINDOW_WIDTH,
                                 random() * settings.WINDOW_HEIGHT)

        self.look_at = Vector2D()
        self.rotation = random() * 2 * math.pi
        self.ltrack = 0.16
        self.rtrack = 0.16
        self.fitness = 0.0
        self.scale = settings.SWEEPER_SCALE
        self.closest_mine = 0
        self.speed = 0.0

    def reset(self):
        self.position = Vector2D(random() * settings.WINDOW_WIDTH,
                                 random() * settings.WINDOW_HEIGHT)

        self.fitness = 0.0
        self.rotation = random() * 2 * math.pi

    def get_closest_mine(self, all_mines):
        '''
        finds and returns a Vector2D that is the position of the mine closest to
        this minesweeper. Expects an iterable of `Mine`s as the parameter
        `all_mines`.
        '''
        closest_so_far = INFINITY
        closest_object = Vector2D(0, 0)
        ctr = 0
        for mine in all_mines:
            l = (mine.position - self.position).length()
            if l < closest_so_far:
                closest_so_far = l
                closest_object = self.position - mine.position
                self.closest_mine = ctr

            ctr += 1

        return closest_object

    def update(self, all_mines):
        '''
        This is the real brains function. Takes an iterable of mines. It first
        takes sensor readings and feed these to the ANN of our minesweeper.
        The inputs are:
            1) A vector (Vector2D) to the closest mine,
            2) The "look at" vector (also a Vector2D).
        
        The brain(ANN) returns 2 outputs, ltrack and rtrack - which are forces
        applied on left and right tracks, respectively. Depending on these, the
        acceleration and/or the rotation is calculated and the position vector
        is updated accordingly.
        '''
        # Inputs to the brain.
        inputs = []
        # First input: vector to the closest mine.
        closest_mine = self.get_closest_mine(all_mines)
        closest_mine.normalize()
        # Place the inputs on the input list
        inputs.append(closest_mine.x)
        inputs.append(closest_mine.y)
        inputs.append(self.look_at.x)
        inputs.append(self.look_at.y)
        # Now, excite the brain and get the feedback
        output = self.brain.excite(inputs, settings.BIAS, filter_sigmoid=True)
        # Make sure we get back the expected number of outputs
        if len(output) != settings.NUM_OUTPUTS:
            raise Exception('An error occurred: The number of outputs from ' +
                            'the ANN is not what was expected.')

        self.ltrack, self.rtrack = output

        rot_force = self.ltrack - self.rtrack
        rot_force = clamp(rot_force, -settings.MAX_TURN_RATE,
                          settings.MAX_TURN_RATE)
        # New rotation and speed:
        self.rotation += rot_force
        self.speed = self.ltrack + self.rtrack
        # Get the new look at:
        self.look_at.x = -math.sin(self.rotation)
        self.look_at.y = math.cos(self.rotation)
        # Get the new position:
        self.position += (self.look_at * self.speed)
        # Wrap around the screen
        if self.position.x > settings.WINDOW_WIDTH:
            self.position.x = 0

        if self.position.x < 0:
            self.position.x = settings.WINDOW_WIDTH

        if self.position.y > settings.WINDOW_HEIGHT:
            self.position.y = 0

        if self.position.y < 0:
            self.position.y = settings.WINDOW_HEIGHT
        # End update()

    def check_for_mine(self, mines, size):
        '''
        checks for a collision with the closest mine.
        '''
        d = self.position - mines[self.closest_mine].position
        if d.length() < (size + 5):
            return self.closest_mine

        return -1

    def inc_fitness(self):
        self.fitness += 1

    def put_weights(self, weights):
        self.brain.put_weights(weights)

    def get_num_weights(self):
        return self.brain.get_num_weights()

    def __repr__(self):
        return '<MineSweeper: ({0}, {1})>'.format(self.position.x,
                                                  self.position.y)
Esempio n. 2
0
class MineSweeper(object):
    '''
    The minesweeper class.
    '''
    def __init__(self):
        self.brain = NeuralNet(settings.NUM_INPUTS,
                               settings.NUM_OUTPUTS,
                               settings.NUM_HIDDEN,
                               settings.NEURONS_PER_HIDDEN)
        
        self.position = Vector2D(random() * settings.WINDOW_WIDTH, 
                                 random() * settings.WINDOW_HEIGHT)
        
        self.look_at = Vector2D()
        self.rotation = random() * 2 * math.pi
        self.ltrack = 0.16
        self.rtrack = 0.16
        self.fitness = 0.0
        self.scale = settings.SWEEPER_SCALE
        self.closest_mine = 0
        self.speed = 0.0
    
    def reset(self):
        self.position = Vector2D(random() * settings.WINDOW_WIDTH, 
                                 random() * settings.WINDOW_HEIGHT)
        
        self.fitness = 0.0
        self.rotation = random() * 2 * math.pi
    
    def get_closest_mine(self, all_mines):
        '''
        finds and returns a Vector2D that is the position of the mine closest to
        this minesweeper. Expects an iterable of `Mine`s as the parameter
        `all_mines`.
        '''
        closest_so_far = INFINITY
        closest_object = Vector2D(0, 0)
        ctr = 0
        for mine in all_mines:
            l = (mine.position - self.position).length()
            if l < closest_so_far:
                closest_so_far = l
                closest_object = self.position - mine.position
                self.closest_mine = ctr
            
            ctr += 1
            
        return closest_object
     
    def update(self, all_mines):
        '''
        This is the real brains function. Takes an iterable of mines. It first
        takes sensor readings and feed these to the ANN of our minesweeper.
        The inputs are:
            1) A vector (Vector2D) to the closest mine,
            2) The "look at" vector (also a Vector2D).
        
        The brain(ANN) returns 2 outputs, ltrack and rtrack - which are forces
        applied on left and right tracks, respectively. Depending on these, the
        acceleration and/or the rotation is calculated and the position vector
        is updated accordingly.
        '''
        # Inputs to the brain.
        inputs = []
        # First input: vector to the closest mine.
        closest_mine = self.get_closest_mine(all_mines)
        closest_mine.normalize()
        # Place the inputs on the input list
        inputs.append(closest_mine.x)
        inputs.append(closest_mine.y)
        inputs.append(self.look_at.x)
        inputs.append(self.look_at.y)
        # Now, excite the brain and get the feedback
        output = self.brain.excite(inputs, settings.BIAS, filter_sigmoid=True)
        # Make sure we get back the expected number of outputs
        if len(output) != settings.NUM_OUTPUTS:
            raise Exception( 'An error occurred: The number of outputs from '
                            +'the ANN is not what was expected.')
        
        self.ltrack, self.rtrack = output
        
        rot_force = self.ltrack - self.rtrack
        rot_force = clamp(rot_force, 
                          -settings.MAX_TURN_RATE, 
                          settings.MAX_TURN_RATE)
        # New rotation and speed:
        self.rotation += rot_force
        self.speed = self.ltrack + self.rtrack
        # Get the new look at:
        self.look_at.x = -math.sin(self.rotation)
        self.look_at.y = math.cos(self.rotation)
        # Get the new position:
        self.position += (self.look_at * self.speed)
        # Wrap around the screen
        if self.position.x > settings.WINDOW_WIDTH:
            self.position.x = 0
        
        if self.position.x < 0:
            self.position.x = settings.WINDOW_WIDTH
            
        if self.position.y > settings.WINDOW_HEIGHT:
            self.position.y = 0
        
        if self.position.y < 0:
            self.position.y = settings.WINDOW_HEIGHT
        # End update()
    
    def check_for_mine(self, mines, size):
        '''
        checks for a collision with the closest mine.
        '''
        d = self.position - mines[self.closest_mine].position
        if d.length() < (size + 5):
            return self.closest_mine
        
        return -1
    
    def inc_fitness(self):
        self.fitness += 1
    
    def put_weights(self, weights):
        self.brain.put_weights(weights)
    
    def get_num_weights(self):
        return self.brain.get_num_weights()
    
    def __repr__(self):
        return '<MineSweeper: ({0}, {1})>'.format(self.position.x,
                                                 self.position.y)