Example #1
0
def score_planet(pw: planet_wars.PlanetWars, p: planet_wars.Planet):
    """
    Function to give a planet a score based on many factors.
    :param pw: `PlanetWars` object
    :param p: `Planet` object
    :return: `float` score of planet
    """

    raw_score = get_raw_score(p)

    structural_score = 1 - (pythag(MY_PLANETS_CENTER,
                                   (p.x(), p.y())) / pw.map_size)

    surrounding_score = 0
    for planet in filter(lambda _p: _p != p, pw.planets()):
        temp = (
            1 -
            (pw.distance(p.planet_id(), planet.planet_id()) / pw.map_size))**5
        surrounding_score += get_raw_score(planet) * temp
    surrounding_score /= pw.total_growth

    latency_score = p.latency / pw.map_size

    center_score = 1 - (pw.distance(p.planet_id(), 0) / pw.map_size)

    score = 0
    score += raw_score
    score += STRUCTURAL_FACTOR * structural_score
    score += SURROUNDING_FACTOR * surrounding_score
    score += LATENCY_FACTOR * latency_score
    score += CENTER_FACTOR * center_score

    return score
Example #2
0
def get_info(pw: planet_wars.PlanetWars):
    """
    Gets basic info about the map. Saves everything in global variables.
    :param pw: `PlanetWars` object
    :return: None
    """

    # get the euclidean center of my and enemy's planets
    global MY_PLANETS_CENTER, ENEMY_PLANETS_CENTER
    MY_PLANETS_CENTER = sum(map(lambda p: p.x(), pw.my_planets())) / len(pw.my_planets()), \
                        sum(map(lambda p: p.y(), pw.my_planets())) / len(pw.my_planets())
    ENEMY_PLANETS_CENTER = sum(map(lambda p: p.x(), pw.enemy_planets())) / len(pw.enemy_planets()), \
                           sum(map(lambda p: p.y(), pw.enemy_planets())) / len(pw.enemy_planets())
Example #3
0
def furthest_meaningful_planet(pw: planet_wars.PlanetWars,
                               planet: planet_wars.Planet, owner: int):
    planets = tuple(filter(lambda p: p.owner() == owner, pw.planets()))
    fleets = tuple(filter(lambda f: f.owner() == owner, pw.fleets()))

    furthest_distance = 0
    for other_planet in planets:
        furthest_distance = max(
            furthest_distance,
            pw.distance(other_planet.planet_id(), planet.planet_id()))
    for fleet in fleets:
        furthest_distance = max(
            furthest_distance,
            fleet.turns_remaining() +
            pw.distance(fleet.destination_planet(), planet.planet_id()))

    return furthest_distance
Example #4
0
    def __init__(self, **kwargs):
        # rip out the game settings we want
        players = kwargs.pop('players')
        gamestate = kwargs.pop('gamestate')
        self.game = PlanetWars(gamestate)
        for p in players:
            self.game.add_player(p)
        self.max_tick = kwargs.pop('max_game_length')
        self.max_tick += self.max_tick / 2

        # set and use pyglet window settings
        kwargs.update({
            'width': 500,
            'height': 500,
            'vsync': True,
            'resizable': False,
        })
        super(PlanetWarsWindow, self).__init__(**kwargs)
        # create a pyglet window and set glOptions
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glClearColor(0., 0., 0., 1.0)  # Grey

        # current "pen" colour of lines
        self.pen_color = (1, 0, 0, 1.)
        self.stroke = 1.0  # - thickness default
        self.qobj = gluNewQuadric()
        # gluQuadricDrawStyle(self.qobj, GLU_FILL) #GLU_SILHOUETTE)

        # prep the fps display and some labels
        self.fps_display = clock.ClockDisplay()
        clWhite = (255, 255, 255, 255)
        self.step_label = Label('STEP', x=5, y=self.height - 20, color=clWhite)
        self.fps = 0
        self.set_fps(20)
        self.paused = True
        self.view_id = 0
        self.label_type = 'num_ships'

        # create adaptor to help with drawing
        self.adaptor = PlanetWarsScreenAdapter(self.game, self.circle)

        # prep the game (space!)
        self.reset_space()
        # add extra event handlers we need
        self.add_handlers()
class PlanetTest(unittest.TestCase):
    def setUp(self):
        self.pw = PlanetWars()

    def _game_over_true(self, max_turn):
        try:
            self.pw.is_game_over(max_turn)
            self.fail("Exception expected")
        except EndOfTheGame:
            pass

    def _game_over_false(self, max_turn):
        try:
            self.pw.is_game_over(max_turn)
        except EndOfTheGame:
            self.fail("Exception unexpected")

    def test_is_game_over(self):
        self.pw.turn = 10
        self._game_over_true(9)

        self.pw.turn = 1

        self._game_over_true(1)
        self.pw.planets.append(Planet(1,1,10,5,10,10))
        self._game_over_true(1)
        self.pw.planets.append(Planet(2,2,10,5,10,10))
        self._game_over_false(1)

        self.pw.planets = []
        self._game_over_true(1)
        self.pw.fleets.append(Fleet(1, 10, 1, 2, 10, 10))
        self._game_over_true(1)
        self.pw.fleets.append(Fleet(2, 10, 1, 2, 10, 10))
        self._game_over_false(1)


    def test_pov(self):
        self.assertEqual(1, pov(1,1))
        self.assertEqual(2, pov(2,1))
        self.assertEqual(1, pov(2,2))
        self.assertEqual(2, pov(1,2))
        self.assertEqual(0, pov(0,1))
        self.assertEqual(0, pov(0,2))
Example #6
0
class PlanetTest(unittest.TestCase):
    def setUp(self):
        self.pw = PlanetWars()

    def _game_over_true(self, max_turn):
        try:
            self.pw.is_game_over(max_turn)
            self.fail("Exception expected")
        except EndOfTheGame:
            pass

    def _game_over_false(self, max_turn):
        try:
            self.pw.is_game_over(max_turn)
        except EndOfTheGame:
            self.fail("Exception unexpected")

    def test_is_game_over(self):
        self.pw.turn = 10
        self._game_over_true(9)

        self.pw.turn = 1

        self._game_over_true(1)
        self.pw.planets.append(Planet(1, 1, 10, 5, 10, 10))
        self._game_over_true(1)
        self.pw.planets.append(Planet(2, 2, 10, 5, 10, 10))
        self._game_over_false(1)

        self.pw.planets = []
        self._game_over_true(1)
        self.pw.fleets.append(Fleet(1, 10, 1, 2, 10, 10))
        self._game_over_true(1)
        self.pw.fleets.append(Fleet(2, 10, 1, 2, 10, 10))
        self._game_over_false(1)

    def test_pov(self):
        self.assertEqual(1, pov(1, 1))
        self.assertEqual(2, pov(2, 1))
        self.assertEqual(1, pov(2, 2))
        self.assertEqual(2, pov(1, 2))
        self.assertEqual(0, pov(0, 1))
        self.assertEqual(0, pov(0, 2))
Example #7
0
 def __init__(self, mapp, enemy_cmd, my_bot_class, timeout=1000, max_turns=200):
     super(Engine, self).__init__()
     self.mapp = mapp
     self.timeout = timeout
     self.max_turns = max_turns
     self.enemy_cmd = enemy_cmd
     self.pw = PlanetWars()
     try:
         self.my_bot = my_bot_class()
     except:
         self.my_bot = None
     self.debug_name = "engine"
     self.playback = ""
Example #8
0
def defensible(pw: planet_wars.PlanetWars, planet: planet_wars.Planet):
    quickest_planet = min(pw.my_planets(),
                          key=lambda p: turn_to_take(pw, p, planet))
    quickest_turns = turn_to_take(pw, quickest_planet, planet)
    for t in range(quickest_turns + 1,
                   furthest_meaningful_planet(pw, planet, 2) + 2):
        my_maximum_ships = max(
            0,
            sum(planet.my_maximum_ships[:t - 1]) - planet.num_ships() +
            planet.growth_rate() * (t - quickest_turns))
        enemy_maximum_ships = sum(planet.enemy_maximum_ships[:t])
        if my_maximum_ships < enemy_maximum_ships:
            return False
    return True
Example #9
0
    def __init__(self, **kwargs):
        # rip out the game settings we want
        players = kwargs.pop('players')
        gamestate = kwargs.pop('gamestate')
        self.game = PlanetWars(gamestate)
        for p in players:
            self.game.add_player(p)
        self.max_tick = kwargs.pop('max_game_length')

        # set and use pyglet window settings
        kwargs.update({
            'width': 500,
            'height': 500,
            'vsync': True,
            'resizable': False,
        })
        super(PlanetWarsWindow, self).__init__(**kwargs)
        # create a pyglet window and set glOptions
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glClearColor(0., 0., 0., 1.0)  # Grey

        # current "pen" colour of lines
        self.pen_color = (1, 0, 0, 1.)
        self.stroke = 1.0  # - thickness default
        self.qobj = gluNewQuadric()
        # gluQuadricDrawStyle(self.qobj, GLU_FILL) #GLU_SILHOUETTE)

        # prep the fps display and some labels
        self.fps_display = clock.ClockDisplay()
        clWhite = (255, 255, 255, 255)
        self.step_label = Label('STEP', x=5, y=self.height - 20, color=clWhite)
        self.fps = 0
        self.set_fps(20)
        self.paused = True
        self.view_id = 0
        self.label_type = 'num_ships'

        # create adaptor to help with drawing
        self.adaptor = PlanetWarsScreenAdapter(self.game, self.circle)

        # prep the game (space!)
        self.reset_space()
        # add extra event handlers we need
        self.add_handlers()
Example #10
0
def turn_to_take(pw: planet_wars.PlanetWars, my_planet: planet_wars.Planet,
                 neutral_planet: planet_wars.Planet):
    """
    Finds the minimum turns to take `neutral_planet` with `my_planet`.
    :param pw: `PlanetWars` object
    :param my_planet: `Planet` object
    :param neutral_planet: `Planet` object
    :return: `int` turns to take the planet
    """

    distance = pw.distance(my_planet.planet_id(), neutral_planet.planet_id())
    if my_planet.num_ships() > neutral_planet.num_ships():
        return distance
    else:
        lacking_ships = neutral_planet.num_ships() - my_planet.num_ships() + 1
        for t in range(pw.map_size):
            lacking_ships -= my_planet.my_arriving_ships[
                t] + my_planet.growth_rate()
            if lacking_ships <= 0:
                break
        else:
            return 999999
        return distance + t
 def setUp(self):
     self.pw = PlanetWars()
Example #12
0
 def load_init_state(self):
     '''load map data and make initial game state'''
     self.pw = PlanetWars()
     self.pw.load_data(self.load_map_data())
     self.playback = ":".join(["%.10f,%.10f,%d,%d,%d" % (p.x, p.y, p.owner, p.num_ships, p.growth_rate)
                               for p in self.pw.planets]) + "|"
Example #13
0
def expand(pw: planet_wars.PlanetWars,
           expand_limit: int = 99,
           possible_planets=None,
           reckless: bool = False):
    """
    Expand to neutral planets with all ships. Designed to come after `defend_possible()` because this doesn't account
    for possible attacks from the opponent.
    :param pw: `PlanetWars` object
    :param expand_limit: `int` the maximum number of planets to expand to.
    :param possible_planets: `list` of `Planet` objects, the planets to consider expanding to. None -> all
    :param reckless: `bool` whether to care about the defensibility of the planet
    :return: None
    """

    expand_limit = min(expand_limit, len(pw.neutral_planets()))

    if possible_planets is None:
        possible_planets = filter(lambda p: p not in pw.my_future_neutrals,
                                  pw.neutral_planets())

    possible_planets = filter(lambda p: p not in pw.enemy_future_neutrals,
                              possible_planets)
    sorted_planets = sorted(
        possible_planets,
        key=lambda p:
        (score_planet(pw, p) - get_raw_score(p) + return_ships(pw, p) /
         (pw.map_size / 2)) / (p.num_ships() + 1),
        reverse=True)

    for _ in range(expand_limit):
        for attack_planet in sorted_planets[:expand_limit]:
            if not (attack_planet.latency > 0 and attack_planet.num_ships() < attack_planet.growth_rate()) and \
                    not reckless and not defensible(pw, attack_planet):
                continue
            # if not reckless and not defensible(pw, attack_planet):
            #     continue

            quickest_planet = min(
                pw.my_planets(),
                key=lambda p: turn_to_take(pw, p, attack_planet))

            closest_distance = pw.map_size
            for enemy_planet in pw.enemy_planets():
                closest_distance = min(
                    closest_distance,
                    pw.distance(enemy_planet.planet_id(),
                                attack_planet.planet_id()))
            for enemy_planet in pw.enemy_future_neutrals:
                closest_distance = min(
                    closest_distance,
                    pw.distance(enemy_planet.planet_id(),
                                attack_planet.planet_id()) +
                    pw.enemy_future_neutrals[enemy_planet][0])

            if turn_to_take(pw, quickest_planet,
                            attack_planet) > closest_distance:
                continue

            if quickest_planet.num_ships() > attack_planet.num_ships():
                pw.issue_order(quickest_planet.planet_id(),
                               attack_planet.planet_id(),
                               attack_planet.num_ships() + 1)
                quickest_planet.remove_ships(attack_planet.num_ships() + 1)
                pw.my_future_neutrals[attack_planet] = (pw.distance(
                    quickest_planet.planet_id(), attack_planet.planet_id()), 1)

                for planet in pw.planets():
                    planet.my_maximum_ships[pw.distance(quickest_planet.planet_id(), planet.planet_id()) - 1] -= \
                        attack_planet.num_ships()
                    planet.my_maximum_ships[
                        pw.distance(quickest_planet.planet_id(),
                                    attack_planet.planet_id()) +
                        pw.distance(attack_planet.planet_id(),
                                    planet.planet_id())] += 1
                    for t in range(
                            pw.distance(quickest_planet.planet_id(),
                                        attack_planet.planet_id()) +
                            pw.distance(attack_planet.planet_id(),
                                        planet.planet_id()), 2 * pw.map_size):
                        planet.my_maximum_ships[
                            t] += attack_planet.growth_rate()

                expand_limit -= 1
                sorted_planets.remove(attack_planet)
                break
            else:
                quickest_planet.num_ships(0)
                return
        else:
            break
Example #14
0
def return_ships(pw: planet_wars.PlanetWars, planet: planet_wars.Planet):
    quickest_planet = min(pw.my_planets(),
                          key=lambda p: turn_to_take(pw, p, planet))
    quickest_turns = turn_to_take(pw, quickest_planet, planet)
    return planet.growth_rate() * (pw.map_size / 2 - quickest_turns)
Example #15
0
class PlanetWarsWindow(window.Window):
    def __init__(self, **kwargs):
        # rip out the game settings we want
        players = kwargs.pop('players')
        gamestate = kwargs.pop('gamestate')
        self.game = PlanetWars(gamestate)
        for p in players:
            self.game.add_player(p)
        self.max_tick = kwargs.pop('max_game_length')

        # set and use pyglet window settings
        kwargs.update({
            'width': 500,
            'height': 500,
            'vsync': True,
            'resizable': False,
        })
        super(PlanetWarsWindow, self).__init__(**kwargs)
        # create a pyglet window and set glOptions
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glClearColor(0., 0., 0., 1.0)  # Grey

        # current "pen" colour of lines
        self.pen_color = (1, 0, 0, 1.)
        self.stroke = 1.0  # - thickness default
        self.qobj = gluNewQuadric()
        # gluQuadricDrawStyle(self.qobj, GLU_FILL) #GLU_SILHOUETTE)

        # prep the fps display and some labels
        self.fps_display = clock.ClockDisplay()
        clWhite = (255, 255, 255, 255)
        self.step_label = Label('STEP', x=5, y=self.height - 20, color=clWhite)
        self.fps = 0
        self.set_fps(20)
        self.paused = True
        self.view_id = 0
        self.label_type = 'num_ships'

        # create adaptor to help with drawing
        self.adaptor = PlanetWarsScreenAdapter(self.game, self.circle)

        # prep the game (space!)
        self.reset_space()
        # add extra event handlers we need
        self.add_handlers()

    def reset_space(self):
        self.adaptor.screen_resize(self.width, self.height)
        self.adaptor.sync_all(self.view_id, self.label_type)

    def set_fps(self, fps):
        self.fps = max(fps, 5)
        clock.unschedule(self.update)
        clock.schedule_interval(self.update, 1.0 / self.fps)

    def update(self, args):
        # gets called by the scheduler at the step_fps interval set
        game = self.game
        if game:
            if not self.paused:
                game.update()
                self.adaptor.sync_all()

            # update step label
            msg = 'Step:' + str(game.tick)
            if self.paused:
                msg += ' [PAUSED]'
            msg += ', View:' + str(self.view_id)
            if self.view_id in game.players:
                msg += ' ' + game.players[self.view_id].name
            elif self.view_id == 0:
                msg += ' All '
            msg += str(game.tick)
            msg += ' Show: ' + self.label_type

            self.step_label.text = msg
            # Has the game ended? (Should we close?)
            if not self.game.is_alive() or self.game.tick >= self.max_tick:
                self.close()
        else:
            self.step_label.text = "---"

    def add_handlers(self):
        @self.event
        def on_resize(cx, cy):
            self.adaptor.screen_resize(cx, cy)
            pass

        @self.event
        def on_mouse_press(x, y, button, modifiers):
            pass

        @self.event
        def on_key_press(symbol, modifiers):
            # Single Player View, or All View
            if symbol == key.BRACKETLEFT:
                self.view_id = self.view_id - 1 if self.view_id > 1 else len(
                    self.game.players)
            if symbol == key.BRACKETRIGHT:
                self.view_id = self.view_id + 1 if self.view_id < len(
                    self.game.players) else 1
            # Everyone view
            elif symbol == key.A:
                self.view_id = 0  # == "all"
            # Planet attribute type to show?
            elif symbol == key.L:
                i = self.label_type
                l = ['id', 'num_ships', 'vision_age', 'owner_id']
                self.label_type = l[l.index(i) +
                                    1] if l.index(i) < (len(l) - 1) else l[0]
            # Reset?
            elif symbol == key.R:
                self.reset_space()
            # Do one step
            elif symbol == key.N:
                self.game.update()
            # Pause toggle?
            elif symbol == key.P:
                self.paused = not self.paused
            # Speed up (+) or slow down (-) the sim
            elif symbol in [key.PLUS, key.EQUAL]:
                self.set_fps(self.fps + 5)
            elif symbol == key.MINUS:
                self.set_fps(self.fps - 5)

            self.adaptor.sync_all(self.view_id, self.label_type)

        @self.event
        def on_draw():
            self.clear()
            self.fps_display.draw()
            self.step_label.draw()
            self.adaptor.draw()

    def set_pen_color(self, color=None, name=None):
        if name is not None:
            color = COLOR_NAMES[name]
        self.curr_color = color
        glColor4f(*self.curr_color)

    def set_stroke(self, stroke):
        self.stroke = stroke
        glLineWidth(self.stroke)

    def circle(self, pos, radius, color=None, filled=True):
        if color:
            self.set_pen_color(color)
        if filled:
            gluQuadricDrawStyle(self.qobj, GLU_FILL)
        else:
            gluQuadricDrawStyle(self.qobj, GLU_SILHOUETTE)
        glPushMatrix()
        glTranslatef(pos[0], pos[1], 0.0)
        gluDisk(self.qobj, 0, radius, 32, 1)
        glPopMatrix()

    def line(self, x1=0, y1=0, x2=0, y2=0, pos1=None, pos2=None):
        ''' Draw a single line. Either with xy values, or two position (that
            contain x and y values). Uses existing colour and stroke values. '''
        if pos1 is not None and pos2 is not None:
            x1, y1, x2, y2 = pos1[0], pos1[1], pos2[0], pos2[1]
        glBegin(GL_LINES)
        glVertex2f(x1, y1)
        glVertex2f(x2, y2)
        glEnd()
Example #16
0
 def setUp(self):
     self.pw = PlanetWars()
Example #17
0
class PlanetWarsWindow(window.Window):

    def __init__(self, **kwargs):
        # rip out the game settings we want
        players = kwargs.pop('players')
        gamestate = kwargs.pop('gamestate')
        self.game = PlanetWars(gamestate)
        for p in players:
            self.game.add_player(p)
        self.max_tick = kwargs.pop('max_game_length')

        # set and use pyglet window settings
        kwargs.update({
            'width': 500,
            'height': 500,
            'vsync': True,
            'resizable': False,
        })
        super(PlanetWarsWindow, self).__init__(**kwargs)
        # create a pyglet window and set glOptions
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glClearColor(0., 0., 0., 1.0)  # Grey

        # current "pen" colour of lines
        self.pen_color = (1, 0, 0, 1.)
        self.stroke = 1.0  # - thickness default
        self.qobj = gluNewQuadric()
        # gluQuadricDrawStyle(self.qobj, GLU_FILL) #GLU_SILHOUETTE)

        # prep the fps display and some labels
        self.fps_display = clock.ClockDisplay()
        clWhite = (255, 255, 255, 255)
        self.step_label = Label('STEP', x=5, y=self.height - 20, color=clWhite)
        self.fps = 0
        self.set_fps(20)
        self.paused = True
        self.view_id = 0
        self.label_type = 'num_ships'

        # create adaptor to help with drawing
        self.adaptor = PlanetWarsScreenAdapter(self.game, self.circle)

        # prep the game (space!)
        self.reset_space()
        # add extra event handlers we need
        self.add_handlers()

    def reset_space(self):
        self.adaptor.screen_resize(self.width, self.height)
        self.adaptor.sync_all(self.view_id, self.label_type)

    def set_fps(self, fps):
        self.fps = max(fps, 5)
        clock.unschedule(self.update)
        clock.schedule_interval(self.update, 1.0 / self.fps)

    def update(self, args):
        # gets called by the scheduler at the step_fps interval set
        game = self.game
        if game:
            if not self.paused:
                game.update()
                self.adaptor.sync_all()

            # update step label
            msg = 'Step:' + str(game.tick)
            if self.paused:
                msg += ' [PAUSED]'
            msg += ', View:' + str(self.view_id)
            if self.view_id in game.players:
                msg += ' ' + game.players[self.view_id].name
            elif self.view_id == 0:
                msg += ' All '
            msg += str(game.tick)
            msg += ' Show: ' + self.label_type

            self.step_label.text = msg
            # Has the game ended? (Should we close?)
            if not self.game.is_alive() or self.game.tick >= self.max_tick:
                self.close()
        else:
            self.step_label.text = "---"

    def add_handlers(self):
        @self.event
        def on_resize(cx, cy):
            self.adaptor.screen_resize(cx, cy)
            pass

        @self.event
        def on_mouse_press(x, y, button, modifiers):
            pass

        @self.event
        def on_key_press(symbol, modifiers):
            # Single Player View, or All View
            if symbol == key.BRACKETLEFT:
                self.view_id = self.view_id - 1 if self.view_id > 1 else len(self.game.players)
            if symbol == key.BRACKETRIGHT:
                self.view_id = self.view_id + 1 if self.view_id < len(self.game.players) else 1
            # Everyone view
            elif symbol == key.A:
                self.view_id = 0 # == "all"
            # Planet attribute type to show?
            elif symbol == key.L:
                i = self.label_type
                l = ['id','num_ships','vision_age','owner_id']
                self.label_type = l[l.index(i)+1] if l.index(i) < (len(l)-1) else l[0]
            # Reset?
            elif symbol == key.R:
                self.reset_space()
            # Do one step
            elif symbol == key.N:
                self.game.update()
            # Pause toggle?
            elif symbol == key.P:
                self.paused = not self.paused
            # Speed up (+) or slow down (-) the sim
            elif symbol in [key.PLUS, key.EQUAL]:
                self.set_fps(self.fps + 5)
            elif symbol == key.MINUS:
                self.set_fps(self.fps - 5)

            self.adaptor.sync_all(self.view_id, self.label_type)

        @self.event
        def on_draw():
            self.clear()
            self.fps_display.draw()
            self.step_label.draw()
            self.adaptor.draw()

    def set_pen_color(self, color=None, name=None):
        if name is not None:
            color = COLOR_NAMES[name]
        self.curr_color = color
        glColor4f(*self.curr_color)

    def set_stroke(self, stroke):
        self.stroke = stroke
        glLineWidth(self.stroke)

    def circle(self, pos, radius, color=None, filled=True):
        if color:
            self.set_pen_color(color)
        if filled:
            gluQuadricDrawStyle(self.qobj, GLU_FILL)
        else:
            gluQuadricDrawStyle(self.qobj, GLU_SILHOUETTE)
        glPushMatrix()
        glTranslatef(pos[0], pos[1], 0.0)
        gluDisk(self.qobj, 0, radius, 32, 1)
        glPopMatrix()

    def line(self, x1=0, y1=0, x2=0, y2=0, pos1=None, pos2=None):
        ''' Draw a single line. Either with xy values, or two position (that
            contain x and y values). Uses existing colour and stroke values. '''
        if pos1 is not None and pos2 is not None:
            x1, y1, x2, y2 = pos1[0], pos1[1], pos2[0], pos2[1]
        glBegin(GL_LINES)
        glVertex2f(x1, y1)
        glVertex2f(x2, y2)
        glEnd()
Example #18
0

# You don't need to change this function
def do_turn(state):
    behavior_tree.execute(planet_wars)


if __name__ == '__main__':
    logging.basicConfig(filename=__file__[:-3] + '.log',
                        filemode='w',
                        level=logging.DEBUG)

    behavior_tree = setup_behavior_tree()
    try:
        map_data = ''
        while True:
            current_line = input()
            if len(current_line) >= 2 and current_line.startswith("go"):
                planet_wars = PlanetWars(map_data)
                do_turn(planet_wars)
                finish_turn()
                map_data = ''
            else:
                map_data += current_line + '\n'

    except KeyboardInterrupt:
        print('ctrl-c, leaving ...')
    except Exception:
        traceback.print_exc(file=sys.stdout)
        logging.exception("Error in bot.")
Example #19
0
class Engine(Debuggable):
    def __init__(self, mapp, enemy_cmd, my_bot_class, timeout=1000, max_turns=200):
        super(Engine, self).__init__()
        self.mapp = mapp
        self.timeout = timeout
        self.max_turns = max_turns
        self.enemy_cmd = enemy_cmd
        self.pw = PlanetWars()
        try:
            self.my_bot = my_bot_class()
        except:
            self.my_bot = None
        self.debug_name = "engine"
        self.playback = ""

    @property
    def turn(self):
        return self.pw.turn

    def plus_turn(self):
        self.pw.turn += 1

    def load_map_data(self):
        f = open(self.mapp)
        data = "\n".join([line for line in f])
        f.close()
        return data

    def load_init_state(self):
        '''load map data and make initial game state'''
        self.pw = PlanetWars()
        self.pw.load_data(self.load_map_data())
        self.playback = ":".join(["%.10f,%.10f,%d,%d,%d" % (p.x, p.y, p.owner, p.num_ships, p.growth_rate)
                                  for p in self.pw.planets]) + "|"

    def _departure(self, enemy_fleets, my_fleets):
        for i, fleets in enumerate((my_fleets, enemy_fleets,)):
            for src, dest, num_ships in fleets:
                dist = self.pw.distance(src,dest)
                self.pw.fleets.append(Fleet(i+1,num_ships,src,dest,dist,dist))
                #TODO make check for ships availability
                self.pw.planets[src].num_ships -= num_ships
                
    def _advancement(self):
        for fl in self.pw.fleets:
            fl.turns_remaining -= 1
        for pl in self.pw.planets:
            if pl.owner > 0:
                pl.num_ships += pl.growth_rate

    def _get_participants(self, pl):
        participants = {pl.owner:pl.num_ships}
        updated_fleets = []
        for fl in self.pw.fleets:
            if fl.dest == pl.id and fl.turns_remaining <= 0:
                if not fl.owner in participants:
                    participants[fl.owner] = fl.num_ships
                else:
                    participants[fl.owner] += fl.num_ships
            else:
                updated_fleets.append(fl)
        self.pw.fleets = updated_fleets
        return participants

    def _get_winner_second(self, participants):
        winner = Fleet(0, 0)
        second = Fleet(0, 0)
        for k, v in participants.items():
            if v > second.num_ships:
                if v > winner.num_ships:
                    second = winner
                    winner = Fleet(k, v)
                else:
                    second = Fleet(k, v)
        return winner, second

    def _process_arrival(self, pl, winner, second):
        if winner.num_ships > second.num_ships:
            pl.num_ships = winner.num_ships - second.num_ships
            pl.owner = winner.owner
        else:
            pl.num_ships = 0

    def _arrival(self):
        for pl in self.pw.planets:
            participants = self._get_participants(pl)
            winner, second = self._get_winner_second(participants)
            self._process_arrival(pl, winner, second)

    def game_state_update(self, enemy_fleets, my_fleets):
        self._departure(enemy_fleets, my_fleets)
        self._advancement()
        self._arrival()

    @property
    def winner(self):
        return "Old" if self.pw.winner == 2 else "New" if self.pw.winner == 1 else "Draw"

    def set_enemy_standard_io(self):
        process = subprocess.Popen(self.enemy_cmd, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
        self.stdin, self.stdout = process.stdin, process.stdout

    def run(self):
        self.load_init_state()
        self.set_enemy_standard_io()
        self.my_bot.via_standard_io = False
        try:
            while True:
                self.make_turn()
        except EndOfTheGame:
            return

    def communicate_enemy_bot(self):
        self.stdin.write(self.pw.repr_for_enemy() + "go\n")
        self.stdin.flush()
        enemy_orders = []
        while True:
            line = self.stdout.readline().replace("\n", "")
            self.debug("> %s" % line)
            self.print_it("> %s" % line)
            if line.startswith("go"):
                break
            enemy_orders.append(map(int, line.split(" ")))
        return enemy_orders

    def communicate_my_bot(self):
        self.my_bot.load_data(repr(self.pw))
        self.my_bot.do_turn()
        self.print_it("\n".join(["< %d %d %d" % order for order in self.my_bot.real_orders]))

    def make_turn(self):
        self.plus_turn()
        self.print_it("Turn #%d" % self.turn)
        self.pw.is_game_over(self.max_turns)
        enemy_orders = self.communicate_enemy_bot()
        self.communicate_my_bot()
        self.game_state_update(enemy_orders, self.my_bot.real_orders)
        self.print_play_back()

    def print_play_back(self):
        if self.debug_enabled:
            planets = ["%d.%d" % (p.owner, p.num_ships) for p in self.pw.planets]
            fleets = ["%d.%d.%d.%d.%d.%d" % (f.owner, f.num_ships, f.src, f.dest, f.total_trip_length, f.turns_remaining)
                      for f in self.pw.fleets]
            self.playback += ",".join(planets + fleets) + ":"