コード例 #1
0
    def perform(self, character: "CharacterModel",
                input_: input_model) -> Description:
        character_doc = self._character_lib.get_document(character.id)
        resource, resource_extraction_description, cost_per_unit = self._get_resource_and_cost(
            character_doc, input_)

        if input_.quantity is None:
            unit_name = self._kernel.translation.get(resource.unit)

            return Description(
                title=f"Récupérer du {resource.name}",
                items=[
                    Part(
                        is_form=True,
                        form_values_in_query=True,
                        form_action=get_character_action_url(
                            character_id=character.id,
                            action_type=ActionType.COLLECT_RESOURCE,
                            action_description_id=self._description.id,
                            query_params=self.input_model_serializer.dump(
                                input_),
                        ),
                        items=[
                            Part(
                                label=
                                f"Quantité (coût: {cost_per_unit} par {unit_name}) ?",
                                type_=Type.NUMBER,
                                name="quantity",
                            )
                        ],
                    )
                ],
            )

        self._kernel.resource_lib.add_resource_to(
            character_id=character_doc.id,
            resource_id=input_.resource_id,
            quantity=input_.quantity,
            commit=False,
        )

        cost = self.get_cost(character, input_=input_)
        if cost is None:
            raise RollingError("Cost compute should not be None !")

        self._kernel.character_lib.reduce_action_points(character.id,
                                                        cost,
                                                        commit=False)
        self._kernel.server_db_session.commit()

        return Description(
            title=
            f"{input_.quantity} {self._kernel.translation.get(resource.unit)} récupéré",
            footer_links=[
                Part(is_link=True,
                     go_back_zone=True,
                     label="Retourner à l'écran de déplacements")
            ],
        )
コード例 #2
0
ファイル: hunt.py プロジェクト: coolkat64/rolling
    def get_properties_from_config(cls, game_config: "GameConfig", action_config_raw: dict) -> dict:
        for produce in action_config_raw["produce"]:
            if "resource" not in produce and "stuff" not in produce:
                raise RollingError(
                    "Misconfiguration for action SearchFoodAction (production "
                    "must contain stuff or resource key"
                )

        properties = fill_base_action_properties(cls, game_config, {}, action_config_raw)
        properties.update({"produce": action_config_raw["produce"]})
        return properties
コード例 #3
0
ファイル: craft.py プロジェクト: coolkat64/rolling
    def get_properties_from_config(cls, game_config: "GameConfig", action_config_raw: dict) -> dict:
        for consume in action_config_raw["consume"]:
            if "resource" not in consume and "stuff" not in consume:
                raise RollingError(f"Action config is not correct: {action_config_raw}")

        properties = fill_base_action_properties(cls, game_config, {}, action_config_raw)
        properties["produce_stuff_id"] = action_config_raw["produce_stuff_id"]
        properties["consume"] = action_config_raw["consume"]
        properties["craft_ap"] = action_config_raw["craft_ap"]
        properties["default_description"] = action_config_raw.get("default_description", "")
        properties["link_group_name"] = action_config_raw.get("link_group_name", None)
        return properties
コード例 #4
0
ファイル: meta.py プロジェクト: coolkat64/rolling
    def get_spawn_coordinates(self, world_map_source: "WorldMapSource") -> typing.Tuple[int, int]:
        available_coordinates: typing.List[typing.Tuple[int, int]] = []

        for row_i, rows in enumerate(self._kernel.world_map_source.geography.rows):
            for col_i, world_tile_type in enumerate(rows):
                if world_tile_type in self._world_tile_types:
                    available_coordinates.append((row_i, col_i))

        if not available_coordinates:
            raise RollingError("No matching world tile for find spawn coordinate")

        return random.choice(available_coordinates)
コード例 #5
0
    def get_start_zone_coordinates(
        self, world_row_i: int, world_col_i: int
    ) -> typing.Tuple[int, int]:
        available_coordinates: typing.List[typing.Tuple[int, int]] = []

        for row_i, row in enumerate(self.geography.rows):
            for col_i, map_tile_type in enumerate(row):
                if traversable_properties[map_tile_type].get(TransportType.WALKING.value):
                    available_coordinates.append((row_i, col_i))

        if not available_coordinates:
            raise RollingError(f"No traversable coordinate in zone {world_row_i},{world_col_i}")

        return random.choice(available_coordinates)
コード例 #6
0
ファイル: craft.py プロジェクト: coolkat64/rolling
    def _get_properties_from_config(
        cls, game_config: "GameConfig", action_config_raw: dict
    ) -> dict:
        for require in action_config_raw["require"]:
            if "resource" not in require and "stuff" not in require:
                raise RollingError(
                    "Misconfiguration for action "
                    "CraftStuffWithResourceAction/CraftStuffWithStuffAction (require "
                    "must contain stuff or resource key"
                )

        properties = fill_base_action_properties(cls, game_config, {}, action_config_raw)
        properties.update(
            {"produce": action_config_raw["produce"], "require": action_config_raw["require"]}
        )
        return properties
コード例 #7
0
    def make_deal(
        self,
        offer_id: int,
        character_id: str,
        request_item_id: typing.Optional[int] = None,
        offer_item_id: typing.Optional[int] = None,
    ) -> None:
        offer: OfferDocument = self.get_offer_query(offer_id).one()
        request_items: typing.List[OfferItemDocument] = []
        offer_items: typing.List[OfferItemDocument] = []
        event_texts: typing.List[str] = ["Vous avez obtenu:"]

        if not self.character_can_deal(character_id, offer_id):
            raise RollingError(
                f"Character {character_id} cannot make deal {offer_id}")

        if offer.request_operand == OfferOperand.OR.value:
            if request_item_id:
                request_items.append(
                    next(i for i in offer.request_items
                         if i.id == request_item_id))
        else:
            request_items.extend(offer.request_items)

        if offer.offer_operand == OfferOperand.OR.value:
            if not offer_item_id:
                raise RollingError(
                    f"Offer {offer_id} require an offer_item_id")
            offer_items.append(
                next(i for i in offer.offer_items if i.id == offer_item_id))
        else:
            offer_items.extend(offer.offer_items)

        def _deal_item(item: OfferItemDocument, giver_id: str,
                       receiver_id: str) -> None:
            if item.resource_id:
                self._kernel.resource_lib.reduce_carried_by(
                    character_id=giver_id,
                    resource_id=item.resource_id,
                    quantity=float(item.quantity),
                    commit=False,
                )
                self._kernel.resource_lib.add_resource_to(
                    character_id=receiver_id,
                    resource_id=item.resource_id,
                    quantity=float(item.quantity),
                    commit=False,
                )
            if item.stuff_id:
                for _ in range(int(item.quantity)):
                    stuff = self._kernel.stuff_lib.get_first_carried_stuff(
                        character_id=giver_id, stuff_id=item.stuff_id)
                    self._kernel.stuff_lib.un_use_stuff(
                        stuff.id)  # TODO BS 20200719: test it
                    self._kernel.stuff_lib.set_carried_by(
                        stuff_id=stuff.id,
                        character_id=receiver_id,
                        commit=False)

        for request_item in request_items:
            _deal_item(request_item,
                       giver_id=character_id,
                       receiver_id=offer.character_id)
            event_texts.append(
                f"- {request_item.get_name(self._kernel, quantity=True)}")

        event_texts.append("Vous avez donné:")
        for offer_item in offer_items:
            _deal_item(offer_item,
                       giver_id=offer.character_id,
                       receiver_id=character_id)
            event_texts.append(
                f"- {offer_item.get_name(self._kernel, quantity=True)}")

        self._kernel.character_lib.add_event(
            offer.character_id,
            title=f"Un affaire à été conclu: {offer.title}",
            story_pages=[StoryPageDocument(text="\n".join(event_texts))],
        )
        self._kernel.server_db_session.commit()
コード例 #8
0
ファイル: generator.py プロジェクト: coolkat64/rolling
    def generate(
        self,
        width: int,
        height: typing.Optional[int] = None,
        north_west_map: typing.Optional[ZoneMapSource] = None,
        north_map: typing.Optional[ZoneMapSource] = None,
        north_est_map: typing.Optional[ZoneMapSource] = None,
        west_map: typing.Optional[ZoneMapSource] = None,
        est_map: typing.Optional[ZoneMapSource] = None,
        south_west_map: typing.Optional[ZoneMapSource] = None,
        south_map: typing.Optional[ZoneMapSource] = None,
        south_est_map: typing.Optional[ZoneMapSource] = None,
    ) -> ZoneMapSource:
        height = height or width

        # Must be odd
        if not width % 2 or not height % 2:
            raise RollingError(
                "Width and height must be odd: given values are {}x{}".format(
                    width, height))

        self._current_raw_source = "::GEO\n"
        part_len = width // 3
        top_void_part = 0, part_len - 1
        bottom_void_part = height - part_len, height - 1
        reduce_counter = part_len
        reduce2_counter = 0

        for row_i in range(height):

            if row_i <= top_void_part[1]:
                left_void_part = 0, part_len - 1 - row_i
                right_void_part = width - part_len + row_i, width - 1
            elif row_i >= bottom_void_part[0]:
                left_void_part = 0, part_len - reduce_counter
                right_void_part = width - reduce2_counter - 1, width - 1
                reduce_counter -= 1
                reduce2_counter += 1
            else:
                left_void_part = -1, -1
                right_void_part = width + 1, width + 1

            for col_i in range(width):
                # Fill with empty
                # TODO BS 2018-12-28: Idea can be fill other map tiles
                if col_i <= left_void_part[1] or col_i >= right_void_part[0]:
                    self._current_raw_source += " "  # FIXME fom type
                else:
                    is_border = False
                    distance_from_border = 0
                    border = None

                    # TODO BS 2019-03-07: give info about border

                    self._current_raw_source += self._filler.get_char(
                        self,
                        is_border=is_border,
                        distance_from_border=distance_from_border,
                        border=border,
                    )

            self._current_raw_source += "\n"

        return ZoneMapSource(self._kernel, self._current_raw_source)
コード例 #9
0
ファイル: affinity.py プロジェクト: coolkat64/rolling
    async def manage(self, request: Request,
                     hapic_data: HapicData) -> Description:
        # TODO BS: only chief (or ability) can display this
        affinity = self._kernel.affinity_lib.get_affinity(
            hapic_data.path.affinity_id)
        relation = self._kernel.affinity_lib.get_character_relation(
            affinity_id=hapic_data.path.affinity_id,
            character_id=hapic_data.path.character_id)

        if hapic_data.query.join_type == affinity_join_str[
                AffinityJoinType.ACCEPT_ALL]:
            request_relations = (self._kernel.server_db_session.query(
                AffinityRelationDocument).filter(
                    AffinityRelationDocument.request == True,
                    AffinityRelationDocument.accepted == False,
                    AffinityRelationDocument.affinity_id == affinity.id,
                ).all())
            if len(request_relations) and not hapic_data.query.confirm:
                return Description(
                    title=affinity.name,
                    items=[
                        Part(
                            text=f'Choisir "{hapic_data.query.join_type}" '
                            f"acceptera automatiquement {len(request_relations)} demande(s) "
                            f"en attente"),
                        Part(
                            label="Confirmer",
                            is_link=True,
                            form_action=
                            f"/affinity/{hapic_data.path.character_id}"
                            f"/manage/{affinity.id}"
                            f"?join_type={urllib.parse.quote(hapic_data.query.join_type)}"
                            f"&confirm=1",
                        ),
                        Part(
                            label="Annuler",
                            is_link=True,
                            form_action=
                            f"/affinity/{hapic_data.path.character_id}"
                            f"/manage/{affinity.id}",
                        ),
                    ],
                )

        # proceed submited data
        if hapic_data.query.join_type is not None:
            join_type = list(affinity_join_str.keys())[list(
                affinity_join_str.values()).index(hapic_data.query.join_type)]

            # TODO BS: code it
            if join_type not in [
                    AffinityJoinType.ACCEPT_ALL,
                    AffinityJoinType.ONE_CHIEF_ACCEPT
            ]:
                raise RollingError(
                    "Cette fonctionnalite n'est pas encore disponible")

            if join_type == AffinityJoinType.ACCEPT_ALL:
                self._kernel.server_db_session.query(
                    AffinityRelationDocument).filter(
                        AffinityRelationDocument.request == True,
                        AffinityRelationDocument.accepted == False,
                        AffinityRelationDocument.affinity_id == affinity.id,
                    ).update({
                        "accepted": True,
                        "request": False
                    })

            affinity.join_type = join_type.value
            self._kernel.server_db_session.add(affinity)
            self._kernel.server_db_session.commit()
            return Description(
                redirect=
                f"/affinity/{hapic_data.path.character_id}/manage/{affinity.id}"
            )

        join_values = [
            affinity_join_str[AffinityJoinType.ACCEPT_ALL],
            affinity_join_str[AffinityJoinType.ONE_CHIEF_ACCEPT],
            affinity_join_str[AffinityJoinType.HALF_STATUS_ACCEPT],
        ]

        request_count = (self._kernel.server_db_session.query(
            AffinityRelationDocument).filter(
                AffinityRelationDocument.affinity_id == affinity.id,
                AffinityRelationDocument.accepted == False,
                AffinityRelationDocument.request == True,
            ).count())
        member_count = (self._kernel.server_db_session.query(
            AffinityRelationDocument).filter(
                AffinityRelationDocument.affinity_id == affinity.id,
                AffinityRelationDocument.accepted == True,
            ).count())
        parts = [
            Part(
                label=
                f"Il y a actuellement {request_count} demande(s) d'adhésion",
                is_link=bool(request_count),
                form_action=
                (f"/affinity/{hapic_data.path.character_id}/manage-requests/{affinity.id}"
                 ),
            ),
            Part(
                label=f"Il y a actuellement {member_count} membre(s)",
                is_link=True,
                form_action=
                (f"/affinity/{hapic_data.path.character_id}/manage-relations/{affinity.id}"
                 ),
            ),
        ]

        return Description(
            title=f"Administration de {affinity.name}",
            items=[
                Part(
                    is_form=True,
                    form_values_in_query=True,
                    submit_label="Enregistrer",
                    form_action=
                    f"/affinity/{hapic_data.path.character_id}/manage/{affinity.id}",
                    items=[
                        Part(
                            label="Mode d'admission des nouveaux membres",
                            choices=join_values,
                            name="join_type",
                            value=affinity_join_str[AffinityJoinType(
                                affinity.join_type)],
                        )
                    ],
                )
            ] + parts,
            footer_links=[
                Part(is_link=True,
                     go_back_zone=True,
                     label="Retourner à l'écran de déplacements"),
                Part(
                    is_link=True,
                    label="Voir les affinités",
                    form_action=f"/affinity/{hapic_data.path.character_id}",
                ),
            ],
            can_be_back_url=True,
        )
コード例 #10
0
ファイル: character.py プロジェクト: coolkat64/rolling
    def display_object(self) -> "DisplayObject":
        if self._display_object is None:
            raise RollingError(
                "You are trying to use property which is not set")

        return self._display_object
コード例 #11
0
ファイル: world.py プロジェクト: coolkat64/rolling
 def get_zone_properties(self, zone_type: ZoneMapTileType) -> ZoneProperties:
     for zone_properties in self.world.zones_properties:
         if zone_properties.zone_type == zone_type:
             return zone_properties
     raise RollingError(f"No zone properties for zone {zone_type}")