Пример #1
0
    def makeWrappers(self):
        imports = "from abc import ABCMeta\n\nfrom pytgf.characters.moves import MoveDescriptor\n" \
                  "from pytgf.controls.wrappers import ControllerWrapper, HumanControllerWrapper, BotControllerWrapper" \
                  "\n\n\n"

        camel_case = to_camel_case(self.gameName, True)

        move_allowed = CodeBlock(
            "def isMoveDescriptorAllowed(self, move_descriptor: MoveDescriptor) -> bool",
            ["# FIXME if needed", "return True"],
            comment_lines=WRAPPER_MOVE_ALLOWED_COMMENTS)

        basic_wrapper = CodeBlock(
            "class " + camel_case +
            "ControllerWrapper(ControllerWrapper, metaclass=ABCMeta)",
            [move_allowed],
            comment_lines=["Basic controller wrapper for this game"],
            class_level=True)

        bot_wrapper = CodeBlock("class " + camel_case +
                                "BotControllerWrapper(BotControllerWrapper, " +
                                camel_case + "ControllerWrapper)", ["pass"],
                                comment_lines=["Bot wrapper for this game"],
                                class_level=True)

        human_wrapper = CodeBlock(
            "class " + camel_case +
            "HumanControllerWrapper(HumanControllerWrapper, " + camel_case +
            "ControllerWrapper)", ["pass"],
            comment_lines=["Human wrapper for this game"])
        code = imports + basic_wrapper.__str__() + bot_wrapper.__str__(
        ) + human_wrapper.__str__()
        write_file(code, join(self.controllersDir, "wrapper.py"))
Пример #2
0
    def makePlayer(self):
        camel_case = to_camel_case(self.gameName, True)
        file_name = to_file_name(self.gameName)
        imports = "from abc import ABCMeta\nfrom typing import List\n\n" \
                  "from pytgf.characters.moves import MoveDescriptor\n" \
                  "from pytgf.controls.controllers import Controller, Bot\n\n" \
                  "from ..rules." + file_name + "api import " + camel_case + "API\n" \
                                                                             "from ..rules." + file_name + "core import " + camel_case + "Core\n"
        basic_player = CodeBlock(
            "class " + camel_case + "Player(Controller, metaclass=ABCMeta)",
            ["pass"],
            comment_lines=[
                "Defines the basic player for the " + self.gameName + "game"
            ])

        possible_moves = CodeBlock(
            "def possibleMoves(self) -> List[MoveDescriptor]",
            ["# FIXME if needed", "return []"],
            decorators=["@property"],
            comment_lines=[
                "Returns: A list containing all the possible moves for this "
                "controller if they can be listed."
            ])

        get_api = CodeBlock("def _getGameStateAPI(self, game: " + camel_case +
                            "Core) -> " + camel_case + "API",
                            ["return " + camel_case + "API(game)"],
                            comment_lines=GAME_API_COMMENTS)

        is_move_interesting = CodeBlock(
            "def _isMoveInteresting(self, player_number: int, "
            "new_move_event: MoveDescriptor) -> bool",
            ["#FIXME if needed", "return True"],
            comment_lines=MOVE_INTERESTING_COMMENTS)

        move_allowed = CodeBlock(
            "def _isMoveAllowed(self, move: MoveDescriptor) -> bool",
            ["# FIXME if needed", "return move in self.possibleMoves"],
            comment_lines=MOVE_ALLOWED_COMMENTS)

        bot_player = CodeBlock(
            "class " + camel_case + "BotPlayer(" + camel_case +
            "Player, Bot, metaclass=ABCMeta)",
            [possible_moves, get_api, is_move_interesting, move_allowed],
            comment_lines=[
                "Defines the basic player for the " + self.gameName + "game"
            ],
            class_level=True)

        code = imports + basic_player.__str__(
        ) + "\n\n\n" + bot_player.__str__()
        write_file(code, join(self.controllersDir, "player.py"))
Пример #3
0
    def makeAPI(self):
        imports = "from pytgf.characters.moves import MoveDescriptor, Path\n" \
                  "from pytgf.characters.units import Unit\n" \
                  "from pytgf.board import Tile, TileIdentifier\nfrom pytgf.game import UnfeasibleMoveException\n"
        api_superclass = "API"
        if self.turnBased:
            api_superclass = "TurnBasedAPI"
            imports += "from pytgf.game.turnbased import TurnBasedAPI\n\n\n"
        else:
            imports += "from pytgf.game import API\n\n\n"

        move_gen = CodeBlock(
            "def createMoveForDescriptor(self, unit: Unit, move_descriptor, force=False, is_step: "
            "bool=False) -> Path", [
                "# TODO ",
                "raise UnfeasibleMoveException('The event couldn\"t create a valid move')"
            ],
            comment_lines=CREATE_MOVE_COMMENTS)
        encode = CodeBlock(
            "def _encodeMoveIntoPositiveNumber(self, player_number: int, "
            "move_descriptor: MoveDescriptor) -> int", [
                "# TODO",
                "raise NotImplementedError('Not yet implemented for this game')"
            ],
            comment_lines=ENCODE_COMMENTS)
        decode = CodeBlock(
            "def _decodeMoveFromPositiveNumber(self, player_number: int, "
            "encoded_move: int) -> MoveDescriptor", [
                "# TODO",
                "raise NotImplementedError('Not yet implemented for this game')"
            ],
            comment_lines=DECODE_COMMENTS)
        api_class = CodeBlock("class " + to_camel_case(self.gameName, True) +
                              "API(" + api_superclass + ")",
                              [move_gen, encode, decode],
                              comment_lines=[],
                              class_level=True)
        code = imports + api_class.__str__()
        write_file(code,
                   join(self.rulesDir,
                        to_file_name(self.gameName) + "api.py"))
Пример #4
0
    def makeUnit(self,
                 unit_name: str,
                 has_sprite: bool = False,
                 is_entity: bool = False):
        superclass = "Entity" if is_entity else "Unit"
        imports = "from pytgf.characters.units import " + superclass + "\n"
        if has_sprite:
            imports += "from pytgf.characters.units.sprite import UnitSprite\n"
        imports += "\n\n"

        sprite = ""

        camel_case = to_camel_case(unit_name, True)

        if has_sprite:
            image_path = CodeBlock("def imageRelativePath(self) -> str", [
                "# TODO",
                "raise NotImplementedError('The image path is not set yet')"
            ], ["@property"])
            sprite = CodeBlock("class " + camel_case + "Sprite(UnitSprite)",
                               [image_path],
                               class_level=True)

        init = CodeBlock(
            "def __init__(self, player_number: int, team_number: int, speed: int, graphics: bool=True)",
            [
                "super().__init__(player_number, sprite=" + camel_case +
                "Sprite(graphics), speed=speed)"
            ])

        unit = CodeBlock("class " + camel_case + "(" + superclass + ")",
                         [init],
                         class_level=True)

        code = imports + sprite.__str__() + unit.__str__()
        write_file(code, join(self.unitsDir, to_file_name(unit_name) + ".py"))
Пример #5
0
 def makeCore(self):
     imports = "from typing import Optional\nfrom pytgf.board import Tile, TileIdentifier, Board\n" \
               "from pytgf.characters.units import Entity, Unit\nfrom pytgf.game.core import Core\n" \
               "from pytgf.characters.moves import MoveDescriptor\n\n\n"
     init = ""
     suicide_property = CodeBlock("def _suicideAllowed(self) -> bool",
                                  ["return %s" % str(self.suicideAllowed)],
                                  ["@property"], [SUICIDE_ALLOWED_COMMENT])
     team_kill_property = CodeBlock(
         "def _teamKillAllowed(self) -> bool",
         ["return %s" % str(self.teamKillAllowed)], ["@property"],
         [TEAM_KILL_ALLOWED_COMMENT])
     collide = CodeBlock(
         "def _collidePlayers(self, player1: Unit, player2: Unit, tile_id: TileIdentifier,"
         +
         "frontal: bool = False, entity: Optional[Entity] = None) -> None",
         [
             "# FIXME if needed",
             "return super()._collidePlayers(player1, player2, tile_id, frontal=frontal,"
             "entity=entity)"
         ],
         comment_lines=COLLIDE_COMMENTS)
     update_state = ""
     goal_reached = ""
     if self.gameType == PUZZLE_GAME:
         init = CodeBlock(
             "def __init__(self, board: Board, ending_unit: Unit)", [
                 "super().__init__(board)",
                 "self._endingUnit = ending_unit  # type: Unit)"
             ],
             comment_lines=[
                 "Args:",
                 "    ending_unit: The unit that will serve as opponent until the "
                 "goal of the game is reached"
             ])
         goal_reached = CodeBlock(
             "def goalReached(self) -> bool", [
                 "# TODO Implement it",
                 "raise NotImplementedError('Lack implementation for this game')"
             ],
             comment_lines=[
                 "Returns: True if the goal of the game has been reached, "
                 "False otherwise"
             ])
         if_goal_reached = CodeBlock("if self.goalReached()",
                                     ["self._endingUnit.setNbLives(0)"])
         update_state = CodeBlock(
             "def updateGameState(self, unit: Unit, tile_id: TileIdentifier, "
             "move_descriptor: MoveDescriptor)", [
                 "ret_val = super().updateGameState(unit, tile_id, move_descriptor)",
                 if_goal_reached, "return ret_val"
             ],
             comment_lines=[
                 "This method is called every time a unit reaches a new tile"
             ])
     core_class = CodeBlock(
         "class " + to_camel_case(self.gameName, True) + "Core(Core)", [
             init, suicide_property, team_kill_property, collide,
             goal_reached, update_state
         ],
         comment_lines=[],
         class_level=True)
     code = imports + core_class.__str__()
     write_file(
         code, join(self.rulesDir,
                    to_file_name(self.gameName) + "core.py"))
Пример #6
0
    def makeMain(self):
        camel_case = to_camel_case(self.gameName, True)
        imports = "from tkinter import Tk\nfrom tkinter.ttk import Frame, Label, Button\nimport pygame\n" \
                  "from pytgf.menu import AISelectorFrameBuilder, ButtonFrameBuilder, GUI\n\n" \
                  "from .builder import create_game\nfrom .%s.player import %sPlayer\n\n\n" \
                  % ("controllers", camel_case)
        global_vars = "selection_frame = None  # type: Frame\nmain_frame = None\n\n\n"

        get_selection_frame = CodeBlock("def get_selection_frame() -> Frame",
                                        ["return selection_frame"])

        build_main_frame = CodeBlock(
            "def build_main_frame(window: Tk, gui: GUI) -> Frame", [
                "global main_frame",
                "builder = ButtonFrameBuilder(\"%s\", window)" % self.gameName,
                "builder.setTitleColor(\"#FF0000\")",
                "builder.addButton((\"Play\", lambda: gui.goToFrame(get_selection_frame())))",
                "builder.addButton((\"Quit\", gui.quit))",
                "main_frame = builder.create()", "return main_frame"
            ],
            comment_lines=["Build the GUI of the game"])

        build_selection_frame = CodeBlock(
            "def build_selection_frame(window: Tk, gui: GUI) -> Frame", [
                "global selection_frame",
                "builder = AISelectorFrameBuilder(\"Player selection\", window, "
                + "%sPlayer," % camel_case,
                "lambda: launch_game(gui, builder.getSelection()), gui.goToPreviousFrame, "
                "max_teams=%s, min_teams=%s, players_description={1: ''})" %
                (str(self.maxTeams), str(self.minTeams)),
                "selection_frame = builder.create()", "return selection_frame"
            ])

        end_popup = CodeBlock('def end_popup(string_result)', [
            "popup = Tk()", "popup.title('Game finished')",
            "label = Label(popup, text=string_result)",
            "label.grid(row=0, column=0, columnspan=4)",
            "button1 = Button(text=\"Play again\", command=lambda: relaunch_gui(popup), width=15)",
            "button1.grid(row=1, column=1)",
            "button2 = Button(text=\"Quit\", command=popup.destroy, width=15)",
            "button2.grid(row=1, column=2)"
        ])

        if_results = CodeBlock("if result is None", ["return"])
        elif_results = CodeBlock("elif len(result) == 0",
                                 ["string_result = \"DRAW\""])
        else_results = CodeBlock("else", [
            'winning_players_strings = ["Player " + str(player.playerNumber) '
            'for player in result]',
            'string_result = "WON: " + str(winning_players_strings)'
        ])

        launch_game = CodeBlock(
            "def launch_game(gui: GUI, player_info: tuple)", [
                "gui.quit()", "pygame.init()", "",
                "main_loop = create_game(player_info)", "",
                "result = main_loop.run()", if_results, elif_results,
                else_results, "end_popup(string_result)"
            ])

        relaunch_gui = CodeBlock(
            "def relaunch_gui(window)",
            ["pygame.quit()", "window.destroy()", "launch_gui()"])

        launch_gui = CodeBlock("def launch_gui()", [
            "window = Tk()",
            "gui = GUI(\"%s\", window)" % self.gameName,
            "gui.addFrame(build_main_frame(window, gui))",
            "gui.addFrame(build_selection_frame(window, gui))",
            "gui.mainloop()"
        ])

        main = CodeBlock("if __name__ == \"__main__\"", ["launch_gui()"],
                         class_level=True)

        code = imports + global_vars + get_selection_frame.__str__() + "\n\n" + build_main_frame.__str__() + "\n\n" + \
            build_selection_frame.__str__() + "\n\n" + end_popup.__str__() + "\n\n" + launch_game.__str__() + "\n\n" \
               + relaunch_gui.__str__() + "\n\n" + launch_gui.__str__() + "\n\n" + main.__str__()

        write_file(code, join(self.gameDir, "main.py"))
Пример #7
0
    def makeBuilder(self):
        camel_case = to_camel_case(self.gameName, True)
        file_name = to_file_name(self.gameName)
        main_loop_module, main_loop_class = ("turnbased", "TurnBasedMainLoop") \
            if self.turnBased else ("realtime", "RealTimeMainLoop")
        imports = "from typing import Tuple, Dict, Type, Optional\n\n" \
                  "from pytgf.board import Builder\nfrom pytgf.controls.controllers import Bot, Human\n" \
                  "from pytgf.game." + main_loop_module + " import " + main_loop_class + "\n\n" \
                  "from .controllers.wrapper import " + camel_case + "BotControllerWrapper, " \
                  + camel_case + "HumanControllerWrapper\n" \
                  "from .rules." + file_name + "core" + " import " + camel_case + "Core\n" + \
                  "from .rules." + file_name + "api" + " import " + camel_case + "API\n"

        for unit in self.units:
            unit_file_name = to_file_name(unit)
            unit_camel_case = to_camel_case(unit, True)
            imports += "from .%s.%s import %s\n" % ("units", unit_file_name,
                                                    unit_camel_case)
        imports += "\n\n"

        if_bot = CodeBlock("if issubclass(player_class, Bot)", [
            "wrapper = %sBotControllerWrapper(player_class(player_number))" %
            camel_case
        ])
        if_human = CodeBlock("elif issubclass(player_class, Human)", [
            "wrapper = %sHumanControllerWrapper(player_class(player_number))" %
            camel_case
        ])
        else_ = CodeBlock("else", [
            "raise TypeError(\"The type of the player (\'%s\') must either be a Bot or a "
            "Human subclass.\" % (str(player_class)))"
        ])
        add_controller = CodeBlock(
            "def add_controller(main_loop: %s, player_class, "
            "player_number: int, player_team: int, speed: int,"
            "graphics: bool)" % main_loop_class, [
                if_bot, if_human, else_,
                "main_loop.addUnit(# TODO instantiate the wanted unit",
                "        wrapper, start_position, initial_action, team=player_team)"
            ])

        controllers_loop = CodeBlock(
            "for player_number, player_class in player_classes.items()", [
                "add_controller(main_loop, player_class, player_number, "
                "player_teams[player_number], int(speed), graphics)"
            ])

        create_game = CodeBlock(
            "def create_game(player_info: Tuple[Dict[int, Type], Dict[int, int]], width: int=%s, "
            "height: int=%s, rows: int=%s, columns: int=%s, speed: int=1, "
            "graphics: bool=True)" % (str(self.width), str(
                self.height), str(self.rows), str(self.columns)),
            [
                "builder = Builder(width, height, rows, columns)",
                "builder.setBordersColor((0, 125, 125))",
                "builder.setBackgroundColor((25, 25, 25))",
                "builder.setTilesVisible(False)", "board = builder.create()",
                "",
                "game = %sCore(board)" % camel_case,
                "main_loop = %s(%sAPI(game))" % (main_loop_class, camel_case),
                "player_classes = player_info[0]",
                "player_teams = player_info[1]", "", controllers_loop
            ])

        code = imports + add_controller.__str__(
        ) + "\n\n" + create_game.__str__()
        write_file(code, join(self.gameDir, "builder.py"))