def test_hex_to_pixel(self):
     """Test hex to pixel."""
     hexagon = Hex(0, 1, -1)
     pointy = Layout(10, (200, 200))
     self.assertEqual(pointy.hex_to_pixel(hexagon),
                      (208.6602540378444, 215.0))
class Game:
    """Class to represent client-side rendering of the game."""
    def __init__(self, game_state, logger, server_api):
        """Initialise display surface."""
        self._server_api = server_api
        pygame.init()
        pygame.font.init()
        civ_borders = [
            "civ1_border", "civ2_border", "civ3_border", "civ4_border"
        ]
        self._shutdown = False
        self._threads = []
        self._game_state = game_state
        self._civ_colours = dict(
            (civ, colour)
            for (civ,
                 colour) in zip(sorted(self._game_state.civs), civ_borders))
        self._flags = (pygame.DOUBLEBUF | pygame.HWSURFACE)
        self.infoObject = pygame.display.Info()
        self._window_size = (self.infoObject.current_w,
                             self.infoObject.current_h)
        self._camera_position = (self._window_size[0] / 2,
                                 self._window_size[1] / 2)
        self._screen = pygame.display.set_mode(self._window_size, self._flags,
                                               0)
        hud_flags = (pygame.HWSURFACE | pygame.SRCALPHA)
        self._hud_surface = pygame.Surface(self._window_size, hud_flags)
        self._hud_quick_surface = pygame.Surface(self._window_size, hud_flags)
        self._font = 'freesansbold.ttf'
        self._font_size = 115
        self._zoom = 30
        self._zoom_interval = 5
        self._min_zoom = 1
        self._max_zoom = 40
        self._hex_size = lambda x: (self.infoObject.current_w // x)
        self._select_menu = SelectMenu(self._screen)
        self._menu_displayed = False
        self._music_player = Music(
            "../resources/music/Egmont_Overture_Op_84.mp3")
        self._music_playing = True
        self._main_menu_options = [("Resume", self.close_main_menu),
                                   ("Toggle Music", self.toggle_music),
                                   ("Exit", self.quit)]
        self._main_menu = Menu(self._screen, self._main_menu_options)
        self._main_menu_displayed = False
        self._grid = self._game_state.grid
        self._layout = Layout(self._hex_size(
            self._zoom), (self._window_size[0] / 2, self._window_size[1] / 2))
        self._hud = HudOverlay(self._game_state, self._hud_surface,
                               self._hud_quick_surface, self._window_size,
                               self._layout)
        self._load_images = LoadImages()
        self._scaled_terrain_images = \
            self._load_images.load_terrain_images().copy()
        self._scaled_sprite_images = \
            self._load_images.load_sprite_images().copy()
        self._scaled_building_images = \
            self._load_images.load_building_images().copy()
        self._scaled_health_bar_images = \
            self._load_images.load_health_bar_images().copy()
        self._scaled_resource_images = \
            self._load_images.load_resource_images().copy()
        self._currently_selected_object = None
        self._currently_selected_tile = None
        self._current_available_moves = {}

    def start(self):
        """Initialize the game."""
        self.scale_images_to_hex_size()
        self.scale_sprites_to_hex_size()
        self.scale_buildings_to_hex_size()
        self.scale_resources_to_hex_size()
        self._music_player.play()
        self.draw_map()
        count = 0
        t = threading.Thread(group=None,
                             target=self.render_hud,
                             name="HUD_render",
                             args=(),
                             daemon=True)
        self._threads.append(t)
        t.start()
        while True:
            self.check_for_events()
            time.sleep(0.004)
            count += 1
            if count == 100:
                count = 0
                self.draw_map()

    def check_for_events(self):
        """Check for mouse and keyboard events."""
        for event in pygame.event.get():  # something happened
            if event.type == pygame.QUIT:
                self.quit()
            elif event.type == pygame.KEYDOWN:
                pressed = pygame.key.get_pressed()
                if pressed[pygame.K_ESCAPE]:
                    self._main_menu_displayed = True
                if pressed[306] == 1 and pressed[99] == 1:  # 306 CTRL,99 C
                    self.quit()
                elif pressed[32] == 1:
                    self._server_api.end_turn()
            if event.type == pygame.MOUSEBUTTONDOWN:
                self.mouse_button_down(event)
            if event.type == pygame.MOUSEBUTTONUP:
                self.mouse_button_up(event)

    def quit(self):
        """Close game."""
        for thread in self._threads:
            self._shutdown = True
            thread.join()
        sys.exit()

    def close_main_menu(self):
        """
        Close the main menu
        """
        self._main_menu_displayed = False

    def toggle_music(self):
        """
        Pause the background music.
        """
        if self._music_playing:
            self._music_player.pause()
            self._music_playing = False
        else:
            self._music_player.unpause()
            self._music_playing = True

    def mouse_button_down(self, event):
        """
        Perform an action depending on the mouse event taking place.

        :param event: a user inputted event.
        """
        if event.button == 1:  # Left click
            self.panning()
        elif event.button == 2:  # Middle click
            pass
        elif event.button == 3:  # Right click
            pass
        elif event.button == 4:  # Scroll up
            self.zoom_in()
        elif event.button == 5:  # Scroll down
            self.zoom_out()

    def mouse_button_up(self, event):
        """
        Perform an action depending on the mouse event taking place.

        :param event: a user inputted event.
        """
        if event.button == 1:  # Left click
            pass
        elif event.button == 2:  # Middle click
            pass
        elif event.button == 3:  # Right click
            if self._main_menu_displayed:
                click = pygame.mouse.get_pos()
                self._main_menu.menu_click(click)
            self.select_object(self._layout)

    def panning(self):
        """
        Pan around the map.

        Method that allows the user to move around the map
        while the left mouse button is being held down.
        """
        pygame.mouse.get_rel()
        if self._menu_displayed:
            self._menu_displayed = False
            self._currently_selected_object = False
        holding = True
        while holding:
            pygame.event.get()
            change = pygame.mouse.get_rel()
            c_hex = self._layout.pixel_to_hex(self._camera_position)
            c_hex_coords = self._grid.hex_round((c_hex.x, c_hex.y, c_hex.z))
            wrap = self._grid.get_hextile(c_hex_coords)
            if (wrap.x, wrap.y, wrap.z) != c_hex_coords:
                pix_change = self._layout.hex_to_pixel(wrap)
                change = (self._camera_position[0] - pix_change[0],
                          self._camera_position[1] - pix_change[1])
            self._layout.change_origin(change)
            self.draw_map()
            holding = pygame.mouse.get_pressed()[0]

    def zoom_in(self):
        """
        Zoom in method.

        Method that allows the user to zoom in when the scroll wheel is used.
        """
        self._zoom -= self._zoom_interval
        if self._zoom <= self._min_zoom:
            self._zoom = self._min_zoom
        else:
            self._layout.size = self._hex_size(self._zoom)
            self.scale_images_to_hex_size()
            self.scale_sprites_to_hex_size()
            self.scale_buildings_to_hex_size()
            self.scale_resources_to_hex_size()
            self.draw_map()

    def zoom_out(self):
        """
        Zoom out method.

        Method that allows the user to zoom out when the scroll wheel is used.
        """
        self._zoom += self._zoom_interval
        if self._zoom >= self._max_zoom:
            self._zoom = self._max_zoom
        else:
            self._layout.size = self._hex_size(self._zoom)
            self.scale_images_to_hex_size()
            self.scale_sprites_to_hex_size()
            self.scale_buildings_to_hex_size()
            self.scale_resources_to_hex_size()
            self.draw_map()

    def select_object(self, layout):
        """
        Select a unit or city and display the menu options.

        :param layout: The layout object being used
        """
        click = pygame.mouse.get_pos()
        c_hex = layout.pixel_to_hex(click)
        c_hex_coords = self._grid.hex_round((c_hex.x, c_hex.y, c_hex.z))
        hexagon = self._grid.get_hextile(c_hex_coords)
        if self._menu_displayed:
            self._menu_displayed = False
            self._select_menu.menu_click(click)
        else:
            if hexagon in self._current_available_moves:
                self._server_api.move_unit(self._currently_selected_object,
                                           hexagon)
                self._game_state.get_civ(
                    self._game_state.my_id).calculate_vision()
                self._currently_selected_object = None
                self._current_available_moves = {}
                self._currently_selected_tile = None
            elif isinstance(self._currently_selected_object, Soldier) \
                    and hexagon.unit != self._currently_selected_object \
                    and hexagon.unit is not None:
                self._server_api.attack(self._currently_selected_object,
                                        hexagon.unit)
            elif hexagon.unit not in [None, self._currently_selected_object] \
                    and hexagon.unit.civ_id == self._game_state.my_id:
                self._currently_selected_object = hexagon.unit
                self.unit_menu(layout)
            elif hexagon.building is not None:
                if hexagon.building.building_type == BuildingType.CITY \
                        and hexagon.building.civ_id == self._game_state.my_id:
                    self._currently_selected_object = hexagon.building
                    self.city_menu()

    def highlight_selected_movement(self, layout):
        """
        Highlight tiles that can be moved to by currently selected unit.

        :param layout: The Layout object being drawn on
        :return:
        """
        for k in self._current_available_moves:
            hexagon_coords = layout.hex_to_pixel(k)
            self._screen.blit(
                self._scaled_terrain_images["move-highlight"],
                (hexagon_coords[0] - math.ceil(layout.size *
                                               (math.sqrt(3) / 2)),
                 hexagon_coords[1] - layout.size))

    def unit_menu(self, layout):
        """
        Create a menu pertaining to unit actions.

        :param layout: Layout object being drawn on.

        """
        unit = self._currently_selected_object
        click = pygame.mouse.get_pos()
        c_hex = layout.pixel_to_hex(click)
        c_hex_coords = self._grid.hex_round((c_hex.x, c_hex.y, c_hex.z))
        hexagon = self._grid.get_hextile(c_hex_coords)
        self._current_available_moves = {}

        def move_unit():
            """Move a unit and redraw the map."""
            self._current_available_moves = self._grid.dijkstra(
                hexagon, unit.movement_range)
            self.draw_map()

        def build_city():
            """Build a city and redraw the map."""
            self._server_api.build_city(unit)
            self._game_state.get_civ(self._game_state.my_id).calculate_vision()
            self._currently_selected_object = None
            self._currently_selected_tile = None
            self.draw_map()

        def build_farm():
            """Build a farm and redraw the map."""
            self._server_api.build(unit, BuildingType.FARM)
            self._game_state.get_civ(self._game_state.my_id).calculate_vision()
            self._currently_selected_object = None
            self._currently_selected_tile = None
            self.draw_map()

        def build_trade_post():
            """Build a trade post and redraw the map."""
            self._server_api.build(unit, BuildingType.TRADE_POST)
            self._game_state.get_civ(self._game_state.my_id).calculate_vision()
            self._currently_selected_object = None
            self._currently_selected_tile = None
            self.draw_map()

        def build_uni():
            """Build a university and redraw the map."""
            self._server_api.build(unit, BuildingType.UNIVERSITY)
            self._game_state.get_civ(self._game_state.my_id).calculate_vision()
            self._currently_selected_object = None
            self._currently_selected_tile = None
            self.draw_map()

        def work_resource():
            """Work a resource and redraw the map."""
            self._server_api.work_resource(unit)
            self._game_state.get_civ(self._game_state.my_id).calculate_vision()
            self._currently_selected_object = None
            self._currently_selected_tile = None
            self.draw_map()

        if self._menu_displayed is False:
            self._menu_displayed = True
            if unit.__class__.__name__ == "Worker":
                if unit.position.building is not None:
                    self._select_menu.set_options(click, [("Move", move_unit)])
                elif unit.position.terrain.resource is None:
                    self._select_menu.set_options(
                        click, [("Move", move_unit),
                                ("Build City", build_city),
                                ("Build Farm", build_farm),
                                ("Build Trade Post", build_trade_post),
                                ("Build Uni", build_uni)])
                elif unit.position.terrain.resource is not None and \
                        unit.position.terrain.resource._is_worked is False:
                    self._select_menu.set_options(
                        click, [("Move", move_unit),
                                ("Work Resource", work_resource)])
                else:
                    self._select_menu.set_options(click, [("Move", move_unit)])
            else:
                self._select_menu.set_options(click, [("Move", move_unit)])

    def city_menu(self):
        """
        Create a menu pertaining to city actions.

        :param layout: Layout object being drawn on.

        """
        city = self._currently_selected_object
        click = pygame.mouse.get_pos()
        self._current_available_moves = {}

        def buy_archer():
            """Buy an archer and redraw the map."""
            self._server_api.purchase(city, Archer, 1)
            self._currently_selected_object = None
            self._currently_selected_tile = None
            self.draw_map()

        def buy_worker():
            """Buy an worker and redraw the map."""
            self._server_api.purchase(city, Worker, 1)
            self._currently_selected_object = None
            self._currently_selected_tile = None
            self.draw_map()

        def buy_swordsman():
            """Buy an swordsman and redraw the map."""
            self._server_api.purchase(city, Swordsman, 1)
            self._currently_selected_object = None
            self._currently_selected_tile = None
            self.draw_map()

        if self._menu_displayed is False:
            self._menu_displayed = True
            self._select_menu.set_options(click,
                                          [("Buy Archer", buy_archer),
                                           ("Buy Swordsman", buy_swordsman),
                                           ("Buy Worker", buy_worker)])

    def scale_images_to_hex_size(self):
        """
        Scale images.

        Takes each image in the terrain_images dictionary,
        scales it to the current hex_size, then stores the
        new image in a copy of the dictionary to preserve
        image quality.
        """
        for k in self._load_images.load_terrain_images():
            self._scaled_terrain_images[k] = pygame.transform.smoothscale(
                self._load_images.load_terrain_images()[k],
                (math.ceil(
                    (self._hex_size(self._zoom) * 2) * math.sqrt(3) / 2),
                 self._hex_size(self._zoom) * 2))

    def scale_sprites_to_hex_size(self):
        """
        Scale sprites.

        Takes each sprite in the sprite_images dictionary,
        scales it to the current hex_size, then stores the
        new image in a copy of the dictionary to preserve
        image quality.
        """
        adjusted_size = math.floor(1800 / self._zoom)
        for k in self._load_images.load_sprite_images():
            self._scaled_sprite_images[k] = pygame.transform.smoothscale(
                self._load_images.load_sprite_images()[k],
                (adjusted_size, adjusted_size))
        for k in self._load_images.load_health_bar_images():
            self._scaled_health_bar_images[k] = pygame.transform.smoothscale(
                self._load_images.load_health_bar_images()[k],
                (adjusted_size, adjusted_size))
        for l in self._load_images.load_resource_images():
            self._scaled_resource_images[l] = pygame.transform.smoothscale(
                self._load_images.load_resource_images()[l],
                (adjusted_size, adjusted_size))

    def scale_resources_to_hex_size(self):
        """
        Take each sprite in the sprite_images dictionary.

        scales it to the current hex_size, then stores the
        new image in a copy of the dictionary to preserve
        image quality.
        """
        adjusted_size = math.floor(1800 / self._zoom)
        for k in self._load_images.load_resource_images():
            self._scaled_resource_images[k] = pygame.transform.smoothscale(
                self._load_images.load_resource_images()[k],
                (adjusted_size, adjusted_size))

    def scale_buildings_to_hex_size(self):
        """
        Scale sprites.

        Takes each sprite in the sprite_images dictionary,
        scales it to the current hex_size, then stores the
        new image in a copy of the dictionary to preserve
        image quality.
        """
        adjusted_size = math.floor(1800 / self._zoom)
        for k in self._load_images.load_building_images():
            self._scaled_building_images[k] = pygame.transform.smoothscale(
                self._load_images.load_building_images()[k],
                (adjusted_size, adjusted_size))

    def draw_building(self, hexagon_coords, sprite):
        """
        Draw sprite on hextile terrain.

        :param hexagon_coords: the coordinates of the center of the hexagon.
        :param sprite: the sprite image to draw.
        """
        center_x, center_y = hexagon_coords
        offset = 1800 / (self._zoom * 2)
        self._screen.blit(sprite,
                          (floor(center_x - offset), floor(center_y - offset)))

    def draw_sprite(self, hexagon_coords, sprite):
        """
        Draw sprite on hextile terrain.

        :param hexagon_coords: the coordinates of the center of the hexagon.
        :param sprite: the sprite image to draw.
        """
        center_x, center_y = hexagon_coords
        offset = 1800 / (self._zoom * 2)
        self._screen.blit(sprite,
                          (floor(center_x - offset), floor(center_y - offset)))

    def draw_hex_grid(self, layout):
        """
        Draw the hexgrid.

        Draws all currently visible hextiles to the screen,
        along with any units or structures contained on those tiles.

        :param layout: The layout of the grid to draw. Either the
                       main layout or one of it's mirrors.
        """
        my_civ = self._game_state.get_civ(self._game_state.my_id)
        my_vision = my_civ.vision
        size = pygame.display.get_surface().get_size()
        for hex_point in self._grid.get_hextiles():
            hexagon = self._grid.get_hextile(hex_point)
            hexagon_coords = layout.hex_to_pixel(hexagon)
            if size[0] + 100 > hexagon_coords[0] > -100 and\
               size[1] + 100 > hexagon_coords[1] > -100:
                terrain = hexagon.terrain
                terrain_image = self._scaled_terrain_images[(
                    terrain.terrain_type.value, terrain.biome.value)]
                self._screen.blit(
                    terrain_image,
                    (hexagon_coords[0] - math.ceil(self._layout.size *
                                                   (math.sqrt(3) / 2)),
                     hexagon_coords[1] - self._layout.size))
                if hexagon.civ_id is not None:
                    self._screen.blit(
                        self._scaled_terrain_images[self._civ_colours[
                            hexagon.civ_id]],
                        (hexagon_coords[0] - math.ceil(self._layout.size *
                                                       (math.sqrt(3) / 2)),
                         hexagon_coords[1] - self._layout.size))
                if hexagon.building is not None:
                    build = hexagon.building
                    hexagon_coords = layout.hex_to_pixel(hexagon)
                    self.draw_building(
                        hexagon_coords,
                        self._scaled_building_images[build.building_type])
                if hexagon.terrain.resource is not None:
                    resource = hexagon.terrain.resource
                    hexagon_coords = layout.hex_to_pixel(hexagon)
                    if resource._is_worked is True:
                        if resource.resource_type is ResourceType.COAL:
                            image_key = "W_COAL"
                        elif resource.resource_type is ResourceType.IRON:
                            image_key = "W_IRON"
                        elif resource.resource_type is ResourceType.LOGS:
                            image_key = "W_LOGS"
                        elif resource.resource_type is ResourceType.GEMS:
                            image_key = "W_GEMS"
                    else:
                        image_key = resource.resource_type
                    self.draw_sprite(hexagon_coords,
                                     self._scaled_resource_images[image_key])
                if hexagon.unit is not None and hexagon in my_vision:
                    unit = hexagon.unit
                    unit_level = unit.level
                    unit_health = unit.get_health_percentage()
                    hexagon_coords = layout.hex_to_pixel(unit.position)
                    self._screen.blit(
                        self._scaled_terrain_images[self._civ_colours[
                            unit.civ_id]],
                        (hexagon_coords[0] - math.ceil(self._layout.size *
                                                       (math.sqrt(3) / 2)),
                         hexagon_coords[1] - self._layout.size))
                    self.draw_sprite(
                        hexagon_coords,
                        self._scaled_sprite_images[unit.__class__.__name__ +
                                                   str(unit_level)])
                    self.draw_sprite(
                        hexagon_coords,
                        self._scaled_health_bar_images[unit_health])
                if hexagon not in my_vision:
                    self._screen.blit(
                        self._scaled_terrain_images["fogofwar"],
                        (hexagon_coords[0] - math.ceil(self._layout.size *
                                                       (math.sqrt(3) / 2)),
                         hexagon_coords[1] - self._layout.size))

    def get_mirrors(self):
        """Store each hexgrid mirror layout in a list."""
        mirror_centers = self._grid.mirrors
        layouts = []
        for mirror in mirror_centers:
            layout = Layout(
                self._layout.size,
                self._layout.hex_to_pixel(Hex(mirror[0], mirror[1],
                                              mirror[2])))
            layouts.append(layout)
        return layouts

    def draw_map(self):
        """
        Draw the current instance of the hex grid to the screen.

        Also draws the hexgrid mirrors.
        """
        if not self._main_menu_displayed:
            self._screen.fill((0, 0, 0))
            self.draw_hex_grid(self._layout)
            layouts = self.get_mirrors()
            for layout in layouts:
                self.draw_hex_grid(layout)
            self.highlight_selected_movement(self._layout)
            for layout in layouts:
                self.highlight_selected_movement(layout)
            self._screen.blit(self._hud_surface, (0, 0))
            self._hud.draw_quick_surface(layouts)
            self._screen.blit(self._hud_quick_surface, (0, 0))
            pygame.display.flip()
            if self._menu_displayed:
                self._select_menu.display_menu()
        else:
            self._main_menu.display_menu()

    def render_hud(self):
        """Render heads up display."""
        while not self._shutdown:
            self._hud.draw()
            time.sleep(1)
class HudOverlay:
    """Class to represent a HUD Overlay."""
    def __init__(self, game_state, screen_surface, quick_surface, resolution,
                 layout):
        """
        Construct hud_overlay.

        :param game_state: ref to current game state object.
        :param screen_surface: pygame display surface.
        :param resolution: tuple or screen resolution (w, h).
        """
        self._game_state = game_state
        self._grid = game_state.grid
        self._myciv = game_state.get_civ(self._game_state.my_id)
        self._screen = screen_surface
        self._quick_surface = quick_surface
        self._resolution = resolution
        self._layout = layout
        civ = game_state.get_civ(game_state.my_id)
        self._GUI_tree = TreeGUI(quick_surface, civ.tree)
        self.font = pygame.font.Font('freesansbold.ttf', 12)
        path = "../resources/images/hud/"
        x, y = 50, 50
        self._hud_images = {
            CurrencyType.GOLD:
            self._load_img(path + "gold_logo.png", x, y),
            CurrencyType.FOOD:
            self._load_img(path + "food_logo.png", x, y),
            CurrencyType.SCIENCE:
            self._load_img(path + "science_logo.png", x, y),
            ResourceType.GEMS:
            self._load_img(path + "gems.png", x, y),
            ResourceType.LOGS:
            self._load_img(path + "logs.png", x, y),
            ResourceType.COAL:
            self._load_img(path + "coal.png", x, y),
            ResourceType.IRON:
            self._load_img(path + "iron.png", x, y),
            0:
            self._load_img(path + "research_logo.png",
                           (x - (x // 5) - (x // 10)), (y - (y // 10))),
            1:
            self._load_img(path + "research_background.png", x, y),
            2:
            self._load_img(path + "button_disabled.png", x * 2, y),
            3:
            self._load_img(path + "button_active.png", x * 2, y)
        }
        path = "../resources/images/tiles/"
        scale = round(200 / self._grid.size)
        x, y = math.ceil((scale * 2 * math.sqrt(3) / 2)), scale * 2
        self._map_layout = Layout(scale, (200, self._resolution[1] - 170))
        self.map_imgs = {
            (0, 0): self._load_img(path + "tundra_flat.png", x, y),
            (0, 1): self._load_img(path + "grassland_flat.png", x, y),
            (0, 2): self._load_img(path + "desert_flat.png", x, y),
            (1, 0): self._load_img(path + "tundra_hill.png", x, y),
            (1, 1): self._load_img(path + "grassland_hill.png", x, y),
            (1, 2): self._load_img(path + "desert_hill.png", x, y),
            (2, 0): self._load_img(path + "tundra_mountain.png", x, y),
            (2, 1): self._load_img(path + "grassland_mountain.png", x, y),
            (2, 2): self._load_img(path + "desert_mountain.png", x, y),
            (3, 0): self._load_img(path + "ocean.png", x, y),
            (3, 1): self._load_img(path + "ocean.png", x, y),
            (3, 2): self._load_img(path + "ocean.png", x, y),
            0: self._load_img(path + "view-highlight.png", x, y)
        }
        self._background = (74, 74, 74)
        self._color1 = (0, 0, 0)
        self._color2 = (255, 255, 255)
        self._color3 = (124, 252, 0)

    def _load_img(self, img, size_w, size_h):
        image = pygame.image.load(img).convert_alpha()
        return self._img_scale(image, size_w, size_h)

    def _img_scale(self, img, size_w, size_h):
        return pygame.transform.smoothscale(img, (size_w, size_h))

    def draw(self):
        """Draw all HUD elements."""
        self._screen.fill((0, 0, 0, 0))
        self.draw_resource_panel()
        self.draw_info_panel()
        self.draw_minimap()
        self.draw_button_panel()

    def draw_quick_surface(self, layouts):
        """Draw quick moving HUD elements."""
        self._quick_surface.fill((0, 0, 0, 0))
        self.draw_view(layouts)

    def draw_view(self, layouts):
        """Draw box showing current view."""
        self.highlight_view(self._layout)
        for layout in layouts:
            self.highlight_view(layout)

    def highlight_view(self, layout):
        """Highlight viewed tiles."""
        size = pygame.display.get_surface().get_size()
        image = self.map_imgs[0]
        for hex_point in self._grid.get_hextiles():
            hexagon = self._grid.get_hextile(hex_point)
            hexagon_coords = layout.hex_to_pixel(hexagon)
            if (size[0] + 100 > hexagon_coords[0] > -100
                    and size[1] + 100 > hexagon_coords[1] > -100):
                hexagon_coords = self._map_layout.hex_to_pixel(hexagon)
                self._quick_surface.blit(
                    image,
                    (hexagon_coords[0] - math.ceil(self._map_layout.size *
                                                   (math.sqrt(3) / 2)),
                     hexagon_coords[1] - self._map_layout.size))

    def draw_resource_panel(self):
        """Draw resource panel."""
        mapresources = self._myciv.resources
        resources = {
            CurrencyType.GOLD: self._myciv.gold,
            CurrencyType.FOOD: self._myciv.food,
            CurrencyType.SCIENCE: self._myciv.science,
            ResourceType.GEMS: mapresources[ResourceType.GEMS],
            ResourceType.LOGS: mapresources[ResourceType.LOGS],
            ResourceType.COAL: mapresources[ResourceType.COAL],
            ResourceType.IRON: mapresources[ResourceType.IRON]
        }
        points = [(450, 0), (0, 0), (0, 60), (430, 60), (450, 40)]
        pygame.draw.polygon(self._screen, self._background, points, 0)
        offset = 10
        for resource in resources:
            value = resources[resource]
            if value is not None:
                logo = self._hud_images[resource]
                self._screen.blit(logo, (offset, 5))
                self.draw_text(value, (offset + 5, 30), self._color2)
                offset += 60

    def draw_info_panel(self):
        """Draw info panel containing turn details and ping."""
        points = [(self._resolution[0] - 240, 0), (self._resolution[0], 0),
                  (self._resolution[0], 40), (self._resolution[0] - 220, 40),
                  (self._resolution[0] - 240, 20)]
        pygame.draw.polygon(self._screen, self._background, points, 0)
        offset = self._resolution[0] - 200
        turn_count = self._game_state.turn_count
        self.draw_text("Turn: {}".format(turn_count), (offset, 20),
                       self._color2)
        offset += 80
        my_turn = self._game_state.my_turn
        if my_turn:
            color = self._color3
        else:
            color = self._color2
        value = "Player{}\'s Turn".format(self._game_state._current_player)
        self.draw_text(value, (offset + 20, 20), color)

    def draw_minimap(self):
        """Draw minimap."""
        lay = Layout(200, (200, self._resolution[1] - 170), False)
        points = lay.polygon_corners(self._grid.get_hextile(self._color1))
        x, y = 0, self._resolution[1] - 344
        pygame.draw.rect(self._screen, self._background, (x, y, 100, 350), 0)
        pygame.draw.polygon(self._screen, self._background, points, 0)
        self.draw_hex_grid()

    def draw_button_panel(self):
        """Draw button to open science tree."""
        points = [(self._resolution[0] - 200, self._resolution[1]),
                  (self._resolution[0], self._resolution[1]),
                  (self._resolution[0], self._resolution[1] - 60),
                  (self._resolution[0] - 180, self._resolution[1] - 60),
                  (self._resolution[0] - 200, self._resolution[1] - 40)]
        pygame.draw.polygon(self._screen, self._background, points, 0)
        logo_background = self._hud_images[1]
        logo_forground = self._hud_images[0]
        x, y = self._resolution[0] - 55, self._resolution[1] - 55
        self._screen.blit(logo_background, (x, y))
        z = 50
        self._screen.blit(logo_forground, (x + ((z // 5) + (z // 10) // 2),
                                           (y + ((z // 10) // 2))))
        my_turn = self._game_state.my_turn
        if my_turn:
            image = self._hud_images[3]
        else:
            image = self._hud_images[2]
        x, y = self._resolution[0] - 170, self._resolution[1] - 55
        self._screen.blit(image, (x, y))
        self.draw_text("End Turn", (x + 30, y + 25), self._color1)

    def draw_text(self, text, position, color):
        """
        Draw text to screen.

        :param text: text to be drawn.
        :param position: tuple (x,y).
        """
        text = str(text)
        text = self.font.render(text, True, color)
        rect = text.get_rect()
        rect.center = (position[0] + 20, position[1])
        self._screen.blit(text, rect)

    def draw_hex_grid(self):
        """Draw the hexgrid."""
        grid = self._grid
        for hex_point in grid.get_hextiles():
            hexagon = grid.get_hextile(hex_point)
            hexagon_coords = self._map_layout.hex_to_pixel(hexagon)
            terrain = hexagon.terrain
            terrain_image = self.map_imgs[(terrain.terrain_type.value,
                                           terrain.biome.value)]
            self._screen.blit(
                terrain_image,
                (hexagon_coords[0] - math.ceil(self._map_layout.size *
                                               (math.sqrt(3) / 2)),
                 hexagon_coords[1] - self._map_layout.size))

    def draw_tree(self):
        """Draw Research Tree."""
        self._GUI_tree.display_menu()