Example #1
0
class StartScene(Scene):
    """Start scene that welcomes the user.

    Attributes
    ----------
    font: pygame.font.Font
        Font that is to be used in this scene
    button: Button
        Button object for the user to go to the next scene
    background: Background
        Background object to display another background

    Methods
    -------
    render(screen)
        Renders background, the button and the title
    update()
        Just to pass the superclass notimplemented error
    handle_events(events)
        When a key is pressed or the button is pressed will move to the next scene
    """
    def __init__(self):
        Scene.__init__(self)
        self.font = pygame.font.Font("Images/Montserrat-ExtraBold.ttf", 38)

        self.button = Button(font_size=21, w=349, center=True)
        self.background = Background("Images/background.jpg", (0, 0))

    def render(self, screen):
        """Renders background, the button and the title"""
        self.background.render(screen)

        self.button.render(screen, "Press any key or click to start")

        title = self.font.render("Cooperative Agents in Multi-agent Systems",
                                 True, (124, 124, 124))
        shadow = pygame.Surface(title.get_size(), pygame.SRCALPHA)
        shadow.fill((124, 124, 124, 100))
        title.blit(shadow, (0, 0), special_flags=pygame.BLEND_RGBA_MULT)
        screen.blit(title, (34, 125))

        title = self.font.render("Cooperative Agents in Multi-agent Systems",
                                 True, (226, 215, 215))
        screen.blit(title, (31, 122))

    def update(self):
        """Just to pass the superclass notimplemented error"""
        pass

    def handle_events(self, events):
        """When a key is pressed or the button is pressed will move to the next scene"""
        Scene.handle_events(self, events)

        for event in events:
            self.button.handle_events(event)
            if event.type == pygame.KEYDOWN:
                self.manager.go_to(SelectAgentsScene())
            if self.button.handle_events(event):
                self.manager.go_to(SelectAgentsScene())
Example #2
0
class PlayTournamentScene(Scene):
    """Scene where the user can see the simulation and interact with its objects.
    
    Attributes
    ----------
    font: pygame.font.Font
        Font that is to be used in this scene
    running: bool
        Store if the simulation is running or not
    was_running: bool
        Store if the simulation was running or not
    new_generation: bool
        Store if the components is over or not
    run: Tournament.start()
        Method that initializes the components
    UPDATE: pygame.USEREVENT
        Event that will call the next step in the simulation
    speed: int
        speed of the simulation
    blobs: dict
        Dictionary of blobs to represent agents
    agents: list
        List of agents
    playing_agents: list
        List of playing agents
    reset_button: Button
        Button object to reset the game (return to the previous page)
    speed_slider: Slider
        Slider object to handle the simulation speed
    message_box: MessageBox
        MessageBox object to ask the user if they want to continue to the next components

    Methods
    -------
    render(screen)
        Renders the blobs, buttons, radio buttons, sliders, labels, and lines
    update()
        Updates the blobs status, messagebox, and slider
    handle_events()
        If the start button is pressed, starts the simulation; if the next button is pressed, gets the next round;
        if the slider is changed, changes the speed; if the reset button is pressed, goes back to the select agents
        scene; when the graph buttons are pressed, calls the plot_graph function
    plot_graph(name, xs, ys, x_label, y_label, title)
        Creates a Graph object, adds it to the list of graphs
    """
    def __init__(self):
        Scene.__init__(self)
        size = pygame.display.get_window_size()
        pygame.display.set_mode((size[0], size[1]), pygame.RESIZABLE)

        self.font = pygame.font.Font("Images/Montserrat-Regular.ttf", 21)
        self.font2 = pygame.font.Font("Images/Montserrat-Regular.ttf", 15)
        self.font3 = pygame.font.Font("Images/Montserrat-ExtraBold.ttf", 15)

        self.tournament = Tournament()
        self.run = self.tournament.start()
        self.agents = self.tournament.get_agents()
        self.conductors = self.tournament.get_conductors()
        self.blobs = dict()
        self.playing_agents = None

        self.running = False
        self.was_running = False
        self.new_generation = False
        self.generation = self.tournament.generation
        self.total_generations = self.tournament.total_generations
        self.total_rounds = self.tournament.total_rounds
        self.total_giving_encounters = self.tournament.total_giving_encounters
        self.total_gossip_encounters = self.tournament.total_gossip_encounters

        self.UPDATE = pygame.USEREVENT + 1
        self.speed = 99
        pygame.time.set_timer(self.UPDATE, self.speed, True)

        self.tab = 0
        self.home_tab = DropdownItem(pygame.Rect(18, 8, 47, 19),
                                     0,
                                     "Home",
                                     underline=0,
                                     font=15,
                                     center=False)
        self.info_tab = DropdownItem(pygame.Rect(89, 8, 29, 19),
                                     1,
                                     "Info",
                                     underline=0,
                                     font=15,
                                     center=False)

        self.reset_button = Button(w=90, pos=(16, 39), center=True)
        self.start_stop_button = Button(w=80, pos=(130, 39), center=True)
        self.next_button = Button(w=80, pos=(234, 39), center=True)

        self.speed_label = self.font.render("Speed", True, (255, 255, 255))
        self.speed_outside_im = pygame.image.load(
            "Images/speedometer_outside.png")
        self.speed_outside_im = pygame.transform.smoothscale(
            self.speed_outside_im, (30, 30))
        self.speed_inside_im = pygame.image.load(
            "Images/speedometer_inside.png")
        self.speed_inside_im = pygame.transform.smoothscale(
            self.speed_inside_im, (15, 15))
        self.speed_slider = Slider((465, 57), 240, fro=5, to=100)

        self.message_box = MessageBox(400, 133)

        self.shift = False
        self.check_shift = True
        self.max_shift = None
        self.min_shift_x = None
        self.min_shift_y = None
        self.shift_x = 0
        self.shift_y = 0
        self.border = 0

        self.zoom = 100
        self.show_zoom = False
        self.BACK_TO_NORMAL = pygame.USEREVENT + 2
        self.min_zoom = 25
        self.max_zoom = 400

        self.simulation_size_w_padding = None
        self.simulation_size_wo_padding = None

    def render(self, screen):
        """Renders the blobs, buttons, radio buttons, labels and lines"""
        Scene.render(self, screen)

        pos1 = pos2 = None
        if self.tournament.receiver_agent and self.tournament.giver_agent:
            pos1 = self.blobs[self.tournament.receiver_agent].get_pos()
            pos2 = self.blobs[self.tournament.giver_agent].get_pos()
        if self.tournament.gossiping_agents:
            pos1 = self.blobs[self.tournament.gossiping_agents[0]].get_pos()
            pos2 = self.blobs[self.tournament.gossiping_agents[1]].get_pos()

        render_after = []
        for agent in self.blobs:
            w, h = pygame.display.get_window_size()
            if 0 - self.blobs[agent].radius / 2 < self.blobs[agent].get_pos(
            )[0] < w + self.blobs[agent].radius / 2:
                if 87 - self.blobs[agent].radius / 2 < self.blobs[
                        agent].get_pos()[1] < h + self.blobs[agent].radius / 2:
                    if self.blobs[agent].show_name:
                        render_after.append(agent)
                    if agent in [
                            self.tournament.giver_agent,
                            self.tournament.receiver_agent
                    ]:
                        render_after.append(agent)
                    if agent in self.tournament.gossiping_agents:
                        render_after.append(agent)
                    self.blobs[agent].render(screen)

        if pos1 and pos2:
            color = (255, 255, 255)
            if self.tournament.encounter_type == "Gossip":
                if self.tournament.gossip:
                    color = (0, 0, 255)
            else:
                if self.tournament.cooperate is not None:
                    if self.tournament.cooperate:
                        color = (0, 255, 0)
                    else:
                        color = (255, 0, 0)
            pygame.draw.aaline(screen,
                               color, (pos1[0] - 2, pos1[1]),
                               (pos2[0] - 2, pos2[1]),
                               blend=100)
            pygame.draw.aaline(screen,
                               color, (pos1[0] - 1, pos1[1]),
                               (pos2[0] - 1, pos2[1]),
                               blend=100)
            pygame.draw.aaline(screen, color, pos1, pos2, blend=100)
            pygame.draw.aaline(screen,
                               color, (pos1[0], pos1[1] - 1),
                               (pos2[0], pos2[1] - 1),
                               blend=100)
            pygame.draw.aaline(screen,
                               color, (pos1[0], pos1[1] - 2),
                               (pos2[0], pos2[1] - 2),
                               blend=100)

        for ra in render_after:
            self.blobs[ra].render(screen)

        pygame.draw.rect(screen, (30, 30, 30), (0, 0, 100000, 85))

        self.home_tab.render(screen)
        self.info_tab.render(screen)

        if self.tab == 0:
            self.reset_button.render(screen, "Reset")
            # self.prev_button.render(screen, "Prev")
            if not self.running:
                self.start_stop_button.render(screen, "Start")
            else:
                self.start_stop_button.render(screen, "Stop")
            self.next_button.render(screen, "Next")

            screen.blit(self.speed_label, (338, 42))
            screen.blit(self.speed_outside_im, (412, 42))
            speed_inside_im = rot_center(self.speed_inside_im,
                                         -(abs(self.speed) * 2.7 - 135))
            screen.blit(speed_inside_im, (419, 51))
            self.speed_slider.render(screen)
            speed_label = self.font.render(str(self.speed), True,
                                           (255, 255, 255))
            screen.blit(speed_label, (729, 44))
        elif self.tab == 1:
            generation_label = self.font2.render(
                f"{self.tournament.generation} Generation / {self.total_generations} Generations",
                True, (255, 255, 255))
            screen.blit(generation_label, (16, 35))
            round_label = self.font2.render(
                f"{self.tournament.round} Round / {self.total_rounds} Rounds",
                True, (255, 255, 255))
            screen.blit(round_label, (407, 35))
            giving_encounter_label = self.font2.render(
                f"{self.tournament.giving_encounters} Giving Encounter / {self.total_giving_encounters} Rounds",
                True, (255, 255, 255))
            screen.blit(giving_encounter_label, (664, 35))
            gossip_encounter_label = self.font2.render(
                f"{self.tournament.gossip_encounters} Gossip Encounter / {self.total_gossip_encounters} Rounds",
                True, (255, 255, 255))
            screen.blit(gossip_encounter_label, (200, 58))
            encounter_type_label = self.font2.render(
                f"Encounter type: {self.tournament.encounter_type}", True,
                (255, 255, 255))
            screen.blit(encounter_type_label, (544, 58))

        pygame.draw.line(screen, (247, 95, 23), (0, 85), (100000, 85), 2)

        if self.show_zoom:
            zoom_label = self.font3.render(f"Zoom: {self.zoom}%", True,
                                           (255, 255, 255))
            screen.blit(zoom_label, (840, 97))

        if self.new_generation:
            self.message_box.render(
                screen, "Do you want to continue to a new tournament?")

    def update(self):
        """Updates the blobs status, messagebox, and slider"""
        self.agents = self.tournament.get_agents()
        self.conductors = self.tournament.get_conductors()

        if self.new_generation:
            if self.message_box.ask_again:
                self.message_box.show = True
            else:
                self.running = self.was_running
                self.new_generation = False
                self.message_box.show = False
                self.message_box.answer = ""
                self.blobs = dict()
            if self.message_box.answer == "yes":
                self.running = self.was_running
                self.new_generation = False
                self.message_box.show = False
                self.message_box.answer = ""
                self.blobs = dict()
            elif self.message_box.answer == "":
                pass
            else:
                pygame.quit()
                exit(0)
        else:
            length = len(self.agents) + len(self.conductors)
            size = (38, 18)
            shift = 0
            while length > size[0] * size[1]:
                size = size[0] + 2, size[1] + 2
                shift += 1

            w = int(25 * self.zoom / 100)
            self.border = shift * w
            self.max_shift = (shift + 2) * w
            self.simulation_size_w_padding = (size[0] + 2) * w, (size[1] +
                                                                 2) * w
            self.simulation_size_wo_padding = size[0] * w, size[1] * w
            self.min_shift_x = -self.simulation_size_w_padding[
                0] + 950 + shift * w
            self.min_shift_y = -self.simulation_size_w_padding[
                1] + 465 + shift * w

            if self.blobs:
                self.blobs[self.conductors[0]].update(shift=(self.shift_x,
                                                             self.shift_y),
                                                      zoom=self.zoom,
                                                      width=w)
                for agent in self.agents:
                    if agent == self.tournament.giver_agent:
                        self.blobs[agent].update(giver=True,
                                                 shift=(self.shift_x,
                                                        self.shift_y),
                                                 zoom=self.zoom,
                                                 width=w)
                        continue
                    if agent == self.tournament.receiver_agent:
                        self.blobs[agent].update(receiver=True,
                                                 shift=(self.shift_x,
                                                        self.shift_y),
                                                 zoom=self.zoom,
                                                 width=w)
                        continue
                    if agent in self.tournament.gossiping_agents:
                        self.blobs[agent].update(gossiping=True,
                                                 shift=(self.shift_x,
                                                        self.shift_y),
                                                 zoom=self.zoom,
                                                 width=w)
                        continue
                    self.blobs[agent].update(shift=(self.shift_x,
                                                    self.shift_y),
                                             zoom=self.zoom,
                                             width=w)
            else:
                zoom = self.zoom
                self.zoom = 100
                w = int(25 * self.zoom / 100)
                self.border = shift * w
                self.max_shift = (shift + 2) * w
                self.simulation_size_w_padding = (size[0] + 2) * w, (size[1] +
                                                                     2) * w
                self.simulation_size_wo_padding = size[0] * w, size[1] * w
                self.min_shift_x = -self.simulation_size_w_padding[
                    0] + 950 + shift * w
                self.min_shift_y = -self.simulation_size_w_padding[
                    1] + 465 + shift * w
                self.min_zoom = int(465 / self.simulation_size_w_padding[1] *
                                    100)
                self.zoom = zoom

                x = y = -shift
                for agent in self.agents:
                    if x == int(size[0] / 2) - shift and y == int(
                            size[1] / 2) - shift:
                        self.blobs[self.conductors[0]] = Blob(
                            (x, y), w, 20, self.conductors[0], conductor=True)
                        x += 1
                    self.blobs[agent] = Blob((x, y), w, 20, agent, player=True)
                    x += 1
                    if x == size[0] - shift:
                        x = -shift
                        y += 1

        self.speed_slider.update()
        if int(self.speed_slider.number) != self.speed:
            self.speed = int(self.speed_slider.number)

        self.home_tab.update(self.tab == self.home_tab.index)
        self.info_tab.update(self.tab == self.info_tab.index)

    def handle_events(self, events):
        """If the start button is pressed, starts the simulation; if the next button is pressed, gets the next round;
        if the slider is changed, changes the speed; if the reset button is pressed, goes back to the select agents
        scene; when the graph buttons are pressed, calls the plot_graph function"""
        Scene.handle_events(self, events)
        for event in events:
            if event.type == self.UPDATE:
                pygame.time.set_timer(self.UPDATE, self.speed, True)
                if self.running:
                    if next(self.run):
                        self.new_generation = True
                        self.was_running = self.running
                        self.running = False

            if not self.message_box.handle_events(event):
                for agent in self.blobs:
                    self.blobs[agent].handle_events(event)

                if self.tab == 0:
                    self.speed_slider.handle_events(event)

                    if self.reset_button.handle_events(event):
                        self.manager.go_to(self.manager.previous)

                    if self.start_stop_button.handle_events(event):
                        self.running = not self.running

                    if self.next_button.handle_events(event):
                        if next(self.run):
                            self.new_generation = True
                            self.was_running = self.running
                            self.running = False

                if self.check_shift:
                    if event.type == pygame.MOUSEBUTTONDOWN:
                        if event.button == 2:
                            self.shift = True

                    if event.type == pygame.MOUSEBUTTONUP:
                        self.shift = False

                    if event.type == pygame.MOUSEMOTION:
                        if self.shift:
                            self.shift_x += event.rel[0]
                            self.shift_y += event.rel[1]

                    if self.shift_x < self.min_shift_x:
                        self.shift_x = self.min_shift_x
                    if self.shift_x > self.max_shift:
                        self.shift_x = self.max_shift

                    if self.shift_y < self.min_shift_y:
                        self.shift_y = self.min_shift_y
                    if self.shift_y > self.max_shift:
                        self.shift_y = self.max_shift

                if event.type == pygame.MOUSEWHEEL:
                    self.check_shift = True
                    zoom = self.zoom
                    if event.y != 0:
                        if self.zoom <= 200:
                            self.zoom += 25 * event.y
                        else:
                            self.zoom += 100 * event.y

                    if self.zoom > self.max_zoom:
                        self.zoom = self.max_zoom
                    elif self.zoom <= self.min_zoom:
                        self.zoom = self.min_zoom
                        zoom = self.zoom
                        shift_x = int(
                            (950 - self.simulation_size_w_padding[0]) /
                            2) + self.max_shift
                        shift_y = int(
                            (465 - self.simulation_size_w_padding[1]) /
                            2) + self.max_shift
                        self.min_shift_x = shift_x - 1
                        self.max_shift = shift_x + 1
                        self.shift_x = shift_x
                        self.shift_y = shift_y
                        self.check_shift = False
                    if zoom != self.zoom:
                        mouse_pos = pygame.mouse.get_pos(
                        )[0], pygame.mouse.get_pos()[1] - 87
                        new_pos = mouse_pos[0] * self.zoom / 100, mouse_pos[
                            1] * self.zoom / 100
                        self.shift_x = int(mouse_pos[0] - new_pos[0])
                        self.shift_y = int(mouse_pos[1] - new_pos[1])

                    self.show_zoom = True
                    pygame.time.set_timer(self.BACK_TO_NORMAL, 600, True)

                if event.type == self.BACK_TO_NORMAL:
                    self.show_zoom = False

                if event.type == pygame.KEYDOWN:
                    if pygame.key.get_mods() and pygame.KMOD_ALT:
                        if event.key == pygame.K_h:
                            self.tab = self.home_tab.index
                        if event.key == pygame.K_i:
                            self.tab = self.info_tab.index
                    if event.key == pygame.K_SPACE:
                        self.running = not self.running
                    if event.key == pygame.K_RIGHT:
                        if next(self.run):
                            self.new_generation = True
                            self.was_running = self.running
                            self.running = False

                if self.home_tab.handle_events(event):
                    self.tab = self.home_tab.index
                if self.info_tab.handle_events(event):
                    self.tab = self.info_tab.index
Example #3
0
class SelectAgentsScene(Scene):
    """Select agents scene where the user can select the amount of agents and number of rounds.

    Attributes
    ----------
    font: pygame.font.Font
        Font that is to be used in this scene
    tournament_manager: TournamentManager
        TournamentManager that takes control of switching between tournaments.
    dr_rb: RadioButton
        Direct reciprocity radio button
    ir_rb: RadioButton
        Indirect reciprocity radio button
    true_rb: RadioButton
        Radio button for asking that agents having an option to chose if they want to play is true
    false_rb: RadioButton
        Radio button for asking that agents having an option to chose if they want to play is false
    input_boxes: list [InputBox]
        list of input boxes where the user enters the amount of agents they want
    input_label: list [pygame.Surface]
        list of labels for the input boxes
    round_input_box: InputBox
        input box to ask the user the number of rounds they want
    start_button: Button
        The button that will take the user to the playing screen
    user_input: list
        list that will store the values the user has chosen
    selection: int
        Stores the selection process the user chose
    selection1_rb: RadioButton
        First selection process radio button
    selection2_rb: RadioButton
        Second selection process radio button

    Methods
    -------
    render(screen)
        Renders the radio buttons for components selection, labels for description, input boxes to get the values, and
        the button
    update()
        Update input box text, and radio buttons
    get_user_input()
        Gets user input from input boxes
    handle_events(events)
        Handles all the objects events, and when the button is pressed will move to the next scene
    """
    def __init__(self):
        Scene.__init__(self)
        self.font = pygame.font.Font("Images/Montserrat-Regular.ttf", 21)
        self.font2 = pygame.font.Font("Images/Montserrat-Regular.ttf", 15)

        self.item = DropdownItem((100, 100), 1, "12345678")

        self.player_label = self.font.render("Player Agent", True, (255, 255, 255))
        self.gossip_type_list = ["Fair", "Selection 2", "Selection 3", "Selection 4", "Selection 5", "Selection 6"]
        self.gossip_type_dropdown = Dropdown("Gossip Type", w=131, pos=(177, 16), selections=self.gossip_type_list)
        self.discrimination_type_list = ["Cooperator", "Stern", "Defector", "Selection 4", "Selection 5", "Selection 6"]
        self.discrimination_type_dropdown = Dropdown("Discrimination Type", w=193, pos=(334, 16), selections=self.discrimination_type_list)

        self.discrimination_threshold_label = self.font2.render("Discrimination Threshold (-5 to 5.5):", True, (255, 255, 255))
        self.discrimination_threshold_input = InputBox((833, 16), w=101, h=27, text="0.543", fro=-5, to=5.5, decimal=True, negative=True)
        self.gossip_weight_label = self.font2.render("Gossip Weight (0 to 1):", True, (255, 255, 255))
        self.gossip_weight_input = InputBox((196, 55), w=101, h=27, text="0.543", fro=0, to=1, decimal=True)
        self.trust_criteria_label = self.font2.render("Trust Criteria (0 to 1):", True, (255, 255, 255))
        self.trust_criteria_input = InputBox((521, 55), w=101, h=27, text="0.543", fro=0, to=1, decimal=True)
        self.number_of_players_label = self.font2.render("Number of Players:", True, (255, 255, 255))
        self.number_of_players_input = InputBox((833, 55), w=101, h=27, text="1000")

        self.self_advertisement = True
        self.self_advertisement_radio_label = self.font2.render("Self Advertisement:", True, (255, 255, 255))
        self.self_advertisement_radio_yes_label = self.font2.render("Yes", True, (255, 255, 255))
        self.self_advertisement_radio_yes = RadioButton((170 + 12, 100 + 12), on=True)
        self.self_advertisement_radio_no_label = self.font2.render("No", True, (255, 255, 255))
        self.self_advertisement_radio_no = RadioButton((231 + 12, 100 + 12), on=False)
        self.self_advertisement_radio_no.bind(self.self_advertisement_radio_yes, self.change_self_advertisement)

        self.add_button = Button(w=75, pos=(859, 92), center=True)

        self.added = []
        self.agents = []
        self.agents2 = []
        self.chips = []
        self.scroll = HorizontalScroll(items=self.chips, pos=(16, 139))

        self.conductor_label = self.font.render("Conductor Agent", True, (255, 255, 255))
        self.number_of_conductors_label = self.font2.render("Number of Conductors:", True, (255, 255, 255))
        self.number_of_conductors_input = InputBox((460, 221), w=101, h=27, text="1000")
        self.number_of_rounds_label = self.font2.render("Total Number of Rounds:", True, (255, 255, 255))
        self.number_of_rounds_input = InputBox((833, 221), w=101, h=27, text="1000")
        self.giving_encounters_label = self.font2.render("Total Giving Encounters:", True, (255, 255, 255))
        self.giving_encounters_input = InputBox((513, 260), w=101, h=27, text="1000")
        self.gossip_encounters_label = self.font2.render("Total Giving Encounters:", True, (255, 255, 255))
        self.gossip_encounters_input = InputBox((833, 260), w=101, h=27, text="1000")

        self.starting_order = True
        self.starting_order_radio_label = self.font2.render("Starting Order:", True, (255, 255, 255))
        self.starting_order_radio_giving_label = self.font2.render("Giving", True, (255, 255, 255))
        self.starting_order_radio_giving = RadioButton((131 + 12, 261 + 12), on=True)
        self.starting_order_radio_gossip_label = self.font2.render("Gossip", True, (255, 255, 255))
        self.starting_order_radio_gossip = RadioButton((215 + 12, 261 + 12), on=False)
        self.starting_order_radio_gossip.bind(self.starting_order_radio_giving, self.change_starting_order)

        self.events_file_name_label = self.font2.render("Events File Name:", True, (255, 255, 255))
        self.events_file_name_input = InputBox((162, 326), w=236, h=27, text="example.event", file=True)
        self.results_file_name_label = self.font2.render("Results File Name:", True, (255, 255, 255))
        self.results_file_name_input = InputBox((162, 365), w=236, h=27, text="example.res", file=True)
        self.benefit_cooperation_label = self.font2.render("Benefit of Cooperation:", True, (255, 255, 255))
        self.benefit_cooperation_input = InputBox((607, 326), w=101, h=27, text="10")
        self.cost_cooperation_label = self.font2.render("Cost of Cooperation:", True, (255, 255, 255))
        self.cost_cooperation_input = InputBox((585, 365), w=101, h=27, text="10")
        self.start_time_label = self.font2.render("Start Time:", True, (255, 255, 255))
        self.start_time_input = InputBox((833, 365), w=101, h=27, text="10")

        self.evolution_type_list = ["Cultural", "Genetic", "Selection 3", "Selection 4", "Selection 5", "Selection 6"]
        self.evolution_type_dropdown = Dropdown("Evolution Type", w=157, pos=(777, 326), selections=self.evolution_type_list)

        self.generation_range_label = self.font.render("Generation Range", True, (255, 255, 255))
        self.min_generation_range_label = self.font2.render("Minimum Generation Range:", True, (255, 255, 255))
        self.min_generation_range_input = InputBox((246, 468), w=101, h=27, text="-5", negative=True)
        self.max_generation_range_label = self.font2.render("Maximum Generation Range:", True, (255, 255, 255))
        self.max_generation_range_input = InputBox((246, 507), w=101, h=27, text="5")

        self.image_score_range_label = self.font.render("Image Score Range", True, (255, 255, 255))
        self.min_image_score_range_label = self.font2.render("Minimum Image Score:", True, (255, 255, 255))
        self.min_image_score_range_input = InputBox((680, 468), w=101, h=27, text="-5", negative=True)
        self.max_image_score_range_label = self.font2.render("Maximum Image Score:", True, (255, 255, 255))
        self.max_image_score_range_input = InputBox((680, 507), w=101, h=27, text="5")

        self.start_button = Button(w=80, pos=(854, 499), center=True)

    def change_starting_order(self):
        self.starting_order = not self.starting_order

    def change_self_advertisement(self):
        self.self_advertisement = not self.self_advertisement

    def render(self, screen):
        """Renders the radio buttons for components selection, labels for description, input boxes to get the values,
                and the button"""
        Scene.render(self, screen)

        screen.blit(self.player_label, (16, 16))
        screen.blit(self.discrimination_threshold_label, (553, 20))
        self.discrimination_threshold_input.render(screen)
        screen.blit(self.gossip_weight_label, (19, 59))
        self.gossip_weight_input.render(screen)
        screen.blit(self.trust_criteria_label, (357, 59))
        self.trust_criteria_input.render(screen)
        screen.blit(self.number_of_players_label, (682, 59))
        self.number_of_players_input.render(screen)

        screen.blit(self.self_advertisement_radio_label, (19, 102))
        screen.blit(self.self_advertisement_radio_yes_label, (198, 102))
        self.self_advertisement_radio_yes.render(screen)
        screen.blit(self.self_advertisement_radio_no_label, (259, 102))
        self.self_advertisement_radio_no.render(screen)

        self.add_button.render(screen, "Add")

        self.scroll.render(screen)

        pygame.draw.line(screen, (247, 95, 23), (16, 201), (934, 201), 5)
        gfxdraw.filled_circle(screen, 16, 201, 2, (247, 95, 23))
        gfxdraw.aacircle(screen, 16, 201, 2, (247, 95, 23))
        gfxdraw.filled_circle(screen, 934, 201, 2, (247, 95, 23))
        gfxdraw.aacircle(screen, 934, 201, 2, (247, 95, 23))

        screen.blit(self.conductor_label, (16, 222))
        screen.blit(self.number_of_conductors_label, (275, 225))
        self.number_of_conductors_input.render(screen)
        screen.blit(self.number_of_rounds_label, (638, 225))
        self.number_of_rounds_input.render(screen)
        screen.blit(self.giving_encounters_label, (322, 264))
        self.giving_encounters_input.render(screen)
        screen.blit(self.gossip_encounters_label, (642, 264))
        self.gossip_encounters_input.render(screen)

        screen.blit(self.starting_order_radio_label, (16, 263))
        self.starting_order_radio_giving.render(screen)
        screen.blit(self.starting_order_radio_giving_label, (159, 263))
        self.starting_order_radio_gossip.render(screen)
        screen.blit(self.starting_order_radio_gossip_label, (243, 263))

        pygame.draw.line(screen, (247, 95, 23), (16, 306), (934, 306), 5)
        gfxdraw.filled_circle(screen, 16, 306, 2, (247, 95, 23))
        gfxdraw.aacircle(screen, 16, 306, 2, (247, 95, 23))
        gfxdraw.filled_circle(screen, 934, 306, 2, (247, 95, 23))
        gfxdraw.aacircle(screen, 934, 306, 2, (247, 95, 23))

        screen.blit(self.events_file_name_label, (16, 330))
        self.events_file_name_input.render(screen)
        screen.blit(self.results_file_name_label, (16, 369))
        self.results_file_name_input.render(screen)
        screen.blit(self.benefit_cooperation_label, (425, 330))
        self.benefit_cooperation_input.render(screen)
        screen.blit(self.cost_cooperation_label, (425, 369))
        self.cost_cooperation_input.render(screen)
        screen.blit(self.start_time_label, (744, 369))
        self.start_time_input.render(screen)

        pygame.draw.line(screen, (247, 95, 23), (16, 411), (934, 411), 5)
        gfxdraw.filled_circle(screen, 16, 411, 2, (247, 95, 23))
        gfxdraw.aacircle(screen, 16, 411, 2, (247, 95, 23))
        gfxdraw.filled_circle(screen, 934, 411, 2, (247, 95, 23))
        gfxdraw.aacircle(screen, 934, 411, 2, (247, 95, 23))

        screen.blit(self.generation_range_label, (16, 431))
        screen.blit(self.min_generation_range_label, (16, 472))
        self.min_generation_range_input.render(screen)
        screen.blit(self.max_generation_range_label, (16, 511))
        self.max_generation_range_input.render(screen)

        pygame.draw.line(screen, (247, 95, 23), (421, 412), (421, 534), 5)
        gfxdraw.filled_circle(screen, 421, 534, 2, (247, 95, 23))
        gfxdraw.aacircle(screen, 421, 534, 2, (247, 95, 23))

        screen.blit(self.image_score_range_label, (493, 431))
        screen.blit(self.min_image_score_range_label, (493, 472))
        self.min_image_score_range_input.render(screen)
        screen.blit(self.max_image_score_range_label, (493, 511))
        self.max_image_score_range_input.render(screen)

        self.start_button.render(screen, "Save")

        self.discrimination_type_dropdown.render(screen)
        self.evolution_type_dropdown.render(screen)
        self.gossip_type_dropdown.render(screen)

    def update(self):
        """Update input box text, and radio buttons"""
        if self.agents != self.agents2:
            self.agents2 = self.agents.copy()
            self.chips = []
            start = 0
            for i, item in enumerate(self.agents):
                chip = Chip(item, pos=(start, 0))
                self.chips.append(chip)
                start += chip.rect.w + 16
        self.scroll.update(self.chips)
        self.gossip_type_dropdown.update()
        self.discrimination_type_dropdown.update()
        self.evolution_type_dropdown.update()

    def handle_events(self, events):
        """Handles all the objects events, and when the button is pressed will move to the next scene"""
        Scene.handle_events(self, events)

        for event in events:
            active = False
            active = active or self.discrimination_type_dropdown.handle_events(event)
            active = active or self.evolution_type_dropdown.handle_events(event)
            active = active or self.gossip_type_dropdown.handle_events(event)

            if not active:
                self.discrimination_threshold_input.handle_events(event)
                self.gossip_weight_input.handle_events(event)
                self.trust_criteria_input.handle_events(event)
                self.number_of_players_input.handle_events(event)
                self.number_of_conductors_input.handle_events(event)
                self.number_of_rounds_input.handle_events(event)
                self.giving_encounters_input.handle_events(event)
                self.gossip_encounters_input.handle_events(event)
                self.events_file_name_input.handle_events(event)
                self.results_file_name_input.handle_events(event)
                self.benefit_cooperation_input.handle_events(event)
                self.cost_cooperation_input.handle_events(event)
                self.start_time_input.handle_events(event)
                self.min_image_score_range_input.handle_events(event)
                self.min_generation_range_input.handle_events(event)
                self.max_image_score_range_input.handle_events(event)
                self.max_generation_range_input.handle_events(event)

                if self.add_button.handle_events(event):
                    discrimination_type = self.discrimination_type_list[self.discrimination_type_dropdown.selected]
                    discrimination_threshold = self.discrimination_threshold_input.get_text()
                    gossip_type = self.gossip_type_list[self.gossip_type_dropdown.selected]
                    gossip_weight = self.gossip_weight_input.get_text()
                    trust_criteria = self.trust_criteria_input.get_text()
                    self_advertisement = "yes" if self.self_advertisement else "no"
                    number_of_players = self.number_of_players_input.get_text()

                    self.agents.append(discrimination_type + " " + str(number_of_players))
                    self.added.append(
                        {"d_ty": discrimination_type, "d_th": discrimination_threshold, "g_t": gossip_type,
                         "g_w": gossip_weight, "t_c": trust_criteria, "s_a": self_advertisement,
                         "n": number_of_players})

                if self.start_button.handle_events(event):
                    for item in self.added:
                        items = list(item.values())
                        items = ','.join(items)
                        print("make(" + item["n"] + ",player(" + items + ")),")
                    giving = "on" if self.starting_order else "off"
                    gossip = "off" if self.starting_order else "on"
                    items = ','.join(
                        [self.number_of_conductors_input.get_text(), "1", self.number_of_rounds_input.get_text(), "1",
                         self.giving_encounters_input.get_text(), self.gossip_encounters_input.get_text(), giving,
                         gossip, "active"])
                    print("make(1,conductor(0," + items + ")),")
                    print("set(imagescorerange(" + self.min_image_score_range_input.get_text() + "," + self.max_image_score_range_input.get_text() + ")),")
                    print("set(cooperationcost(" + self.cost_cooperation_input.get_text() + ")),")
                    print("set(cooperationbenefit(" + self.benefit_cooperation_input.get_text() + ")),")
                    print("set(generationinfo(" + self.min_generation_range_input.get_text() + "," + self.max_generation_range_input.get_text() + ")),")
                    print("set(starttime(" + self.start_time_input.get_text() + ")),")
                    print("set(evolutiontype(" + self.evolution_type_list[self.evolution_type_dropdown.selected] + ")),")
                    print("output(resultsin('" + self.results_file_name_input.get_text() + "')),")
                    print("output(eventsin('" + self.events_file_name_input.get_text() + "'))")

                    self.manager.go_to(PlayTournamentScene())

                self.self_advertisement_radio_no.handle_events(event)
                self.self_advertisement_radio_yes.handle_events(event)
                self.starting_order_radio_gossip.handle_events(event)
                self.starting_order_radio_giving.handle_events(event)
                if i := self.scroll.handle_events(event):
                    self.agents.pop(i - 1)
                    self.added.pop(i - 1)