acutesoftware/virtual-AI-simulator

View on GitHub
vais/simulator.py

Summary

Maintainability
A
3 hrs
Test Coverage
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# simulator.py

class Simulator(object):
    """
    Base simulator class
    """
    def __init__(self, name, world, agents, actions):
        self.name = name
        self.world = world
        self.actions = actions
        self.events = []
        self.log = []
        self.status = 'Started'
        self.agents = agents
        self._verify_agents()
        #self.agent_locations = agent_locations #[]
        #for num, a in enumerate(self.agents):
        #    print('Sim __init__, agent num:', num, ' = ', a)
        #    ag_loc = {}
        #    ag_loc['name'] = a.name
        #    ag_loc['x'] = agent_locations[num][0]
        #    ag_loc['y'] = agent_locations[num][1]
        #    self.agent_locations.append(ag_loc)
     
    def __str__(self):
        res = ' -= ' + self.name + ' =--\n'
        res += 'world   = ' + self.world.name + ' (' + str(self.world.grid_width) + 'x' + str(self.world.grid_height) + ')\n'
        res += 'actions = [' + ', '.join([a for a in self.actions]) + ']\n'
        res += 'agents  = ' + str(len(self.agents)) + ' (' + ','.join([c.name for c in self.agents]) + ')\n'
        res += 'agent_locations\n'
        for a in self.agents:
            res += 'Agent: ' + a.name + '\n'
            print('agent a = ', str(a))
            print('coords = ', a.coords)
            for c,v in a.coords.items():
                res += '  coord ' + str(c) + ' = ' + str(v) + '\n'
        return res + '\n'
    
    def _verify_agents(self):
        """
        verify agents passed to simulator by:
        1. checking for unique names
        2. TODO - other checks if needed
        """
        #print('verifying...')
        nmes = []
        for agt_num, a in enumerate(self.agents):
            #print('agent#', agt_num, 'is type', type(a))
            nmes.append(a.name)
        if len(nmes) == len(set(nmes)):
            return True
        print('Error - you need to pass unique list of agent names to simulator')
        return False
            
    


    
    def run(self, num_iterations=-1):
        """
        Abstract method to be subclassed by calling function.
        This runs the simulation num_iterations times.
        If the default -1 is used for num_iteractions this means
        it is a turn based simulation which is controlled externally
        (e.g. for a game with players, or run by the class BattleSimulator)
        
        """
        
        if num_iterations == -1:    # controlled fully externally   
            self.status = 'Waiting for Command'
            return
        self.status = 'Running'
        
    def stop(self):
        self.status = 'Halted'
    
    def add_event(self, event):
        """
        events can be added at the start of the sim in advance
        or during the simulation by AI or user.
        """
        self.events.append(event)
    
    def get_state(self):
        """
        called in loop by GUI display to get current state of
        simulation
        """
        return self.world, self.status, self.log # no this isn't permanent
    
    def command(self, cmd, agent, src='admin', password=''):
        """
        takes a command from a source 'src' and if 
        access is allowed (future implementation) 
        then execute the command on the 'agent'
        """
        print(src, 'says ' + cmd['type']  + ' agent', agent.name, '', cmd['direction'],' password=', password)
        if cmd['type'] == 'move':
            self._move_agent(agent, cmd['direction'], False)
        elif cmd['type'] == 'run':
            print(agent.name, 'runs in direction', cmd['direction'])
        elif cmd['type'] == 'fight':
            print(agent.name, 'fights')
            
    def _move_agent(self, agent, direction, wrap_allowed=True):
        """
        moves agent 'agent' in 'direction'
        """
        x,y = agent.coords['x'], agent.coords['y']
        print('moving agent ', agent.name, 'to x,y=', direction, 'wrap_allowed = ', wrap_allowed)
        agent.coords['x'] = x + direction[0]
        agent.coords['y'] = y + direction[1]
        #print('agent after move = ', str(agent))
        
    
class SimAdventureGame(Simulator):
    def __init__(self, name, world, agents, actions):
        Simulator.__init__(self, name, world, agents, actions)
        
    def __str__(self):
        return 'Adventure Game ' + Simulator.__str__(self)
    
class SimGameOfLife(Simulator):
    def __init__(self, name, world, agents, actions):
        Simulator.__init__(self, name, world, agents, actions)
        
    def __str__(self):
        return 'GAME OF LIFE ' + Simulator.__str__(self)