Esempio n. 1
0
    def __init__(self, *player_names):
        self.logger = logging.getLogger('code_empire.models.World')

        self.tilemap = TileMap(World.MAP_SIZE)
        self.creatures = {}  #CreatureADT()
        self.resources = {}  #ResourceADT()
        self.fortresses = {}  #FortressADT()
        self.players = {}  # maps player_name (string) to a dict
        for player_name in player_names:
            self.players[player_name] = dict(fortress=None, creatures=Set([]))
Esempio n. 2
0
    def __init__(self, *player_names):
        self.logger = logging.getLogger('code_empire.models.World') 

        self.tilemap = TileMap(World.MAP_SIZE)
        self.creatures = {} #CreatureADT()
        self.resources = {} #ResourceADT()
        self.fortresses = {} #FortressADT()
        self.players = {} # maps player_name (string) to a dict
        for player_name in player_names:
            self.players[player_name] = dict(fortress=None, creatures=Set([]))
Esempio n. 3
0
class World(object):
    MAP_SIZE = 9 # Always an odd number!
    STARTING_AREA_SIZE = 3

    def __init__(self, *player_names):
        self.logger = logging.getLogger('code_empire.models.World') 

        self.tilemap = TileMap(World.MAP_SIZE)
        self.creatures = {} #CreatureADT()
        self.resources = {} #ResourceADT()
        self.fortresses = {} #FortressADT()
        self.players = {} # maps player_name (string) to a dict
        for player_name in player_names:
            self.players[player_name] = dict(fortress=None, creatures=Set([]))

    def get_entity_at(self, x, y):
        return self.tilemap.get_tile_at(x, y)

    def generate(self, random):
        # For now, hard code 2 players
        self.generate_starting_area(
            random, 
            self.players.keys()[0], 
            Point(World.MAP_SIZE - World.STARTING_AREA_SIZE), 
            Point(World.MAP_SIZE))

        self.generate_starting_area(
            random, 
            self.players.keys()[1], 
            Point(0), 
            Point(World.STARTING_AREA_SIZE))

    def generate_starting_area(self,
                               random,
                               player,
                               lower,
                               upper,
                               num_creatures=2,
                               start_gold=100,
                               num_resources=1,
                               gold_amount_func=lambda i: 100 / (i + 1),
                               gold_flux_func=lambda i: 10 * (i + 1)):
        """
        Randomically place fortresses, starting creatures and resources.

        Keyword arguments:
        random         -- Python's random module.
        player         -- The player's name.
        lower          -- 
        upper          -- 
        num_creatures  -- The number of starting creatures for each player.
        start_gold     -- The amount of starting gold for each player.
        num_resources  -- The number of starting resources scattered around
                           the map, one of which is a large resource
                           that is created near each player's fortress.
        """
        random_points = Point.generate(random,
                                       lower=lower,
                                       upper=upper,
                                       count=(1 + num_creatures + num_resources))

        self.insert_fortress(Fortress(player, start_gold, position=random_points.pop()))

        for i in range(num_creatures):
            self.insert_creature(Creature('Peon', player, position=random_points.pop()))

        for i in range(num_resources):
            self.insert_resource(Resource('Gold Mine', gold_amount_func(i), gold_flux_func(i), position=random_points.pop()))

    def insert_fortress(self, f):
        self.fortresses[f.id] = f
        self.players[f.player]['fortress'] = f
        self.tilemap.set_tile_at(f.position.x, f.position.y, f)

    def insert_creature(self, c):
        self.creatures[c.id] = c
        self.players[c.player]['creatures'].add(c)
        self.tilemap.set_tile_at(c.position.x, c.position.y, c)

    def insert_resource(self, r):
        self.resources[r.id] = r
        self.tilemap.set_tile_at(r.position.x, r.position.y, r)

    def remove_creature(self, c):
        del self.creatures[c.id]
        self.players[c.player]['creatures'].remove(c)
        self.tilemap.set_tile_at(c.position.x, c.position.y, TileMap.EMPTY_TILE)

    def move_creature(self, c, dx, dy):
        """
        Attempt to move a creature by a incrementing its x and y.
        Returns True if successful, False otherwise.
        """
        to_x = c.position.x + dx
        to_y = c.position.y + dy

        if self.tilemap.in_bounds(to_x, to_y) and self.tilemap.is_tile_empty(to_x, to_y):
            self.tilemap.set_tile_at(c.position.x, c.position.y, TileMap.EMPTY_TILE)
            self.tilemap.set_tile_at(to_x, to_y, c)
            c.position.x = to_x
            c.position.y = to_y
            return True
        else:
            return False

    def standing_players(self):
        return [pname for pname, pdict in self.players.items() if len(pdict['creatures']) > 0]

    def winner(self):
        # TODO: check win/draw special cases.
        # (eg: there are no more creatures and Player 1 has not enough resources)
        survivors = self.standing_players()
        if len(survivors) == 1:
            return survivors[0]
        else:
            return None

    def gather_fortress_info(self, c):
        return

    def handle_fortress_response(self, resp, c):
        return

    def update(self):
        dead_creatures = []

        for id in self.creatures:
            creature = self.creatures[id]

            if not creature.alive():
                dead_creatures.append(creature)
                continue

        self.clean(dead_creatures)

        return self.winner()

    def clean(self, dead_creatures=None):
        for dead in dead_creatures:
            self.remove_creature(dead)

    def handle_move(self, c, resp):
            dx, dy = resp.get('dx', 0), resp.get('dy', 0)
            self.move_creature(c, dx, dy)

    def handle_attack(self, c, resp):
        target_x, target_y = resp.get('target_x', 0), resp.get('target_y', 0)
        target_creature = self.tilemap.get_tile_at(target_x, target_y)
        if target_creature.__class__ == Creature:
            c.attack(target_creature)

    def handle_gather(self, c, resp):
        resource_x, resource_y = resp.get('resource_x', 0), resp.get('resource_y', 0)
        target_resource = self.tilemap.get_tile_at(resource_x, resource_y)
        if target_resource.__class__ == Resource:
            c.gather(target_resource)

    def handle_wander(self, c, resp):
        self.move_creature(c, random.randrange(3) - 1, random.randrange(3) - 1)

    def handle_creature_response(self, resp, c):
        """
        Handle a creature's response to the think method.
        """
        c.memory = resp['memory']

        # All possible actions a creature may perform.
        # TODO: Set this table as a Class constant, as this is probably slow.
        handle = {
            'move':     self.handle_move,
            'attack':   self.handle_attack,
            'gather':   self.handle_gather,
            'wander':   self.handle_wander
        }.get(resp['action'], None)

        if handle:
            handle(c, resp) # Calls the handler method
        else:
            raise UnknownActionError(action=resp['action'])

        # TODO: Check for errors (e.g.: 'target' is there but no 'target_x', target class, etc)
        # TODO: Add optional choice of 'target_id' over 'target_x' and 'target_y'
        if resp.get('log', None):
            for creature_log in resp['log']:
                self.logger.info("%s's %s (id=%s) : %s", c.player, c.name, c.id, creature_log)
Esempio n. 4
0
class World(object):
    MAP_SIZE = 9  # Always an odd number!
    STARTING_AREA_SIZE = 3

    def __init__(self, *player_names):
        self.logger = logging.getLogger('code_empire.models.World')

        self.tilemap = TileMap(World.MAP_SIZE)
        self.creatures = {}  #CreatureADT()
        self.resources = {}  #ResourceADT()
        self.fortresses = {}  #FortressADT()
        self.players = {}  # maps player_name (string) to a dict
        for player_name in player_names:
            self.players[player_name] = dict(fortress=None, creatures=Set([]))

    def get_entity_at(self, x, y):
        return self.tilemap.get_tile_at(x, y)

    def generate(self, random):
        # For now, hard code 2 players
        self.generate_starting_area(
            random,
            self.players.keys()[0],
            Point(World.MAP_SIZE - World.STARTING_AREA_SIZE),
            Point(World.MAP_SIZE))

        self.generate_starting_area(random,
                                    self.players.keys()[1], Point(0),
                                    Point(World.STARTING_AREA_SIZE))

    def generate_starting_area(self,
                               random,
                               player,
                               lower,
                               upper,
                               num_creatures=2,
                               start_gold=100,
                               num_resources=1,
                               gold_amount_func=lambda i: 100 / (i + 1),
                               gold_flux_func=lambda i: 10 * (i + 1)):
        """
        Randomically place fortresses, starting creatures and resources.

        Keyword arguments:
        random         -- Python's random module.
        player         -- The player's name.
        lower          -- 
        upper          -- 
        num_creatures  -- The number of starting creatures for each player.
        start_gold     -- The amount of starting gold for each player.
        num_resources  -- The number of starting resources scattered around
                           the map, one of which is a large resource
                           that is created near each player's fortress.
        """
        random_points = Point.generate(random,
                                       lower=lower,
                                       upper=upper,
                                       count=(1 + num_creatures +
                                              num_resources))

        self.insert_fortress(
            Fortress(player, start_gold, position=random_points.pop()))

        for i in range(num_creatures):
            self.insert_creature(
                Creature('Peon', player, position=random_points.pop()))

        for i in range(num_resources):
            self.insert_resource(
                Resource('Gold Mine',
                         gold_amount_func(i),
                         gold_flux_func(i),
                         position=random_points.pop()))

    def insert_fortress(self, f):
        self.fortresses[f.id] = f
        self.players[f.player]['fortress'] = f
        self.tilemap.set_tile_at(f.position.x, f.position.y, f)

    def insert_creature(self, c):
        self.creatures[c.id] = c
        self.players[c.player]['creatures'].add(c)
        self.tilemap.set_tile_at(c.position.x, c.position.y, c)

    def insert_resource(self, r):
        self.resources[r.id] = r
        self.tilemap.set_tile_at(r.position.x, r.position.y, r)

    def remove_creature(self, c):
        del self.creatures[c.id]
        self.players[c.player]['creatures'].remove(c)
        self.tilemap.set_tile_at(c.position.x, c.position.y,
                                 TileMap.EMPTY_TILE)

    def move_creature(self, c, dx, dy):
        """
        Attempt to move a creature by a incrementing its x and y.
        Returns True if successful, False otherwise.
        """
        to_x = c.position.x + dx
        to_y = c.position.y + dy

        if self.tilemap.in_bounds(to_x, to_y) and self.tilemap.is_tile_empty(
                to_x, to_y):
            self.tilemap.set_tile_at(c.position.x, c.position.y,
                                     TileMap.EMPTY_TILE)
            self.tilemap.set_tile_at(to_x, to_y, c)
            c.position.x = to_x
            c.position.y = to_y
            return True
        else:
            return False

    def standing_players(self):
        return [
            pname for pname, pdict in self.players.items()
            if len(pdict['creatures']) > 0
        ]

    def winner(self):
        # TODO: check win/draw special cases.
        # (eg: there are no more creatures and Player 1 has not enough resources)
        survivors = self.standing_players()
        if len(survivors) == 1:
            return survivors[0]
        else:
            return None

    def gather_fortress_info(self, c):
        return

    def handle_fortress_response(self, resp, c):
        return

    def update(self):
        dead_creatures = []

        for id in self.creatures:
            creature = self.creatures[id]

            if not creature.alive():
                dead_creatures.append(creature)
                continue

        self.clean(dead_creatures)

        return self.winner()

    def clean(self, dead_creatures=None):
        for dead in dead_creatures:
            self.remove_creature(dead)

    def handle_move(self, c, resp):
        dx, dy = resp.get('dx', 0), resp.get('dy', 0)
        self.move_creature(c, dx, dy)

    def handle_attack(self, c, resp):
        target_x, target_y = resp.get('target_x', 0), resp.get('target_y', 0)
        target_creature = self.tilemap.get_tile_at(target_x, target_y)
        if target_creature.__class__ == Creature:
            c.attack(target_creature)

    def handle_gather(self, c, resp):
        resource_x, resource_y = resp.get('resource_x',
                                          0), resp.get('resource_y', 0)
        target_resource = self.tilemap.get_tile_at(resource_x, resource_y)
        if target_resource.__class__ == Resource:
            c.gather(target_resource)

    def handle_wander(self, c, resp):
        self.move_creature(c, random.randrange(3) - 1, random.randrange(3) - 1)

    def handle_creature_response(self, resp, c):
        """
        Handle a creature's response to the think method.
        """
        c.memory = resp['memory']

        # All possible actions a creature may perform.
        # TODO: Set this table as a Class constant, as this is probably slow.
        handle = {
            'move': self.handle_move,
            'attack': self.handle_attack,
            'gather': self.handle_gather,
            'wander': self.handle_wander
        }.get(resp['action'], None)

        if handle:
            handle(c, resp)  # Calls the handler method
        else:
            raise UnknownActionError(action=resp['action'])

        # TODO: Check for errors (e.g.: 'target' is there but no 'target_x', target class, etc)
        # TODO: Add optional choice of 'target_id' over 'target_x' and 'target_y'
        if resp.get('log', None):
            for creature_log in resp['log']:
                self.logger.info("%s's %s (id=%s) : %s", c.player, c.name,
                                 c.id, creature_log)