Beispiel #1
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"))
Beispiel #2
0
    def __init__(self,
                 game_name: str,
                 game_type: int,
                 unit_names: List[str],
                 turn_based: bool,
                 width: int,
                 height: int,
                 rows: int,
                 columns: int,
                 min_players: int,
                 max_players: int,
                 min_teams: int = 2,
                 max_teams: int = 2,
                 suicide_allowed: bool = True,
                 team_kill_allowed: bool = True):
        self.gameName = game_name
        self.gameDir = to_file_name(game_name)
        os.mkdir(self.gameDir)
        self.gameType = game_type
        self.turnBased = turn_based
        self.suicideAllowed = suicide_allowed
        self.teamKillAllowed = team_kill_allowed
        self.units = unit_names
        self.width = width
        self.height = height
        self.rows = rows
        self.columns = columns
        self.maxPlayers = max_players if game_type != DUEL_GAME else 2
        self.minPlayers = min_players if game_type != DUEL_GAME else 2
        self.minTeams = max(2, min(
            2, min_teams, self.minPlayers)) if game_type != PUZZLE_GAME else 1
        self.maxTeams = max(2, min(
            max_teams, self.maxPlayers)) if game_type != PUZZLE_GAME else 1

        self.rulesDir = join(self.gameDir, "rules")
        self.controllersDir = join(self.gameDir, "controllers")
        self.unitsDir = join(self.gameDir, "units")

        create_module(self.rulesDir)
        self.makeCore()
        self.makeAPI()
        create_module(self.controllersDir)
        self.makePlayer()
        self.makeWrappers()
        create_module(self.unitsDir)
        for unit_name in unit_names:
            self.makeUnit(unit_name, True, False)
        self.makeBuilder()
        self.makeMain()
        os.mkdir(join(self.gameDir, "res"))
        os.mkdir(join(self.gameDir, "res", "AIs"))
Beispiel #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"))
Beispiel #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"))
Beispiel #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"))
Beispiel #6
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"))