Skip to content

Commit

Permalink
feature(nyz): add py3.8 support and get started guide
Browse files Browse the repository at this point in the history
  • Loading branch information
PaParaZz1 authored and yihuai-gao committed Mar 8, 2023
1 parent ca3955d commit 850ee2e
Show file tree
Hide file tree
Showing 19 changed files with 163 additions and 144 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,22 @@ Package name `gisim` stands for both `Genshin Impact` and `Genius Invokation`

希望可以实现类似openai-gym的API,用于训练ai&评估卡组强度

# Get Started

Prerequisites:
* Python >=3.9
* [Poetry 1.1.14+](https://python-poetry.org)

Installation: enter the project directory and execute the following command:
```bash
poetry install
```

Runnable basic demo locally: give the following a try:
```bash
poetry run python3 -u tests/test_framework.py
```


# Roadmap
- [x] Encode the game status into a dictionary
Expand Down
7 changes: 3 additions & 4 deletions gisim/agent.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
"""Player & agent APIs
"""
import enum
from abc import ABC, abstractmethod
from collections import Counter
from typing import OrderedDict
from typing import OrderedDict, List, Dict

from gisim.cards.characters import get_character_card
from gisim.classes.action import (
Expand Down Expand Up @@ -42,8 +41,8 @@ def __init__(self, player_id: PlayerID):

def get_dice_idx_greedy(
self,
dice: list[ElementType],
cost: dict[ElementType, int],
dice: List[ElementType],
cost: Dict[ElementType, int],
char_element: ElementType = ElementType.NONE,
):
# First determine whether the current dice are enough
Expand Down
3 changes: 2 additions & 1 deletion gisim/cards/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from typing import Tuple
from gisim.cards.base import Card
from gisim.cards.characters import *
from gisim.cards.equipments import *
Expand All @@ -22,7 +23,7 @@ def get_card(card_name: str):
return card


def get_equipment(equipment_name: str, target: tuple[PlayerID, CharPos]):
def get_equipment(equipment_name: str, target: Tuple[PlayerID, CharPos]):
equipment_name = equipment_name.replace(" ", "").replace("'", "")
equipment_class = globals()[equipment_name]
equipment: EquipmentEntity = equipment_class(
Expand Down
8 changes: 4 additions & 4 deletions gisim/cards/base.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from queue import PriorityQueue
from typing import TYPE_CHECKING, cast
from typing import TYPE_CHECKING, Dict, cast

from pydantic import BaseModel

Expand All @@ -21,13 +21,13 @@
class Card(BaseModel):
id: int
name: str
costs: dict[ElementType, int]
costs: Dict[ElementType, int]
text: str
card_type: CardType

def use_card(
self,
msg_queue: PriorityQueue[Message],
msg_queue: PriorityQueue, # PriorityQueue[Message]
game_info: "GameInfo",
):
pass
Expand All @@ -42,7 +42,7 @@ class WeaponCard(Card):
weapon_type: WeaponType
card_type: CardType = CardType.WEAPON

def use_card(self, msg_queue: PriorityQueue[Message], game_info: "GameInfo"):
def use_card(self, msg_queue: PriorityQueue, game_info: "GameInfo"):
top_msg = msg_queue.queue[0]
top_msg = cast(UseCardMsg, top_msg)
player_id, entity_type, idx = top_msg.card_target[0]
Expand Down
22 changes: 11 additions & 11 deletions gisim/cards/characters/Cryo/KamisatoAyaka.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""神里绫华"""

from queue import PriorityQueue
from typing import TYPE_CHECKING, cast
from typing import TYPE_CHECKING, Dict, List, cast
from xml.dom.minidom import Element

from gisim.cards.base import TalentCard
Expand Down Expand Up @@ -41,7 +41,7 @@ class KamisatoArtKabuki(GenericSkill):
text: str = """
Deals 2 Physical DMG.
"""
costs: dict[ElementType, int] = {ElementType.CRYO: 1, ElementType.ANY: 2}
costs: Dict[ElementType, int] = {ElementType.CRYO: 1, ElementType.ANY: 2}
type: SkillType = SkillType.NORMAL_ATTACK
damage_element: ElementType = ElementType.NONE
damage_value: int = 2
Expand All @@ -53,7 +53,7 @@ class KamisatoArtHyouka(GenericSkill):
text: str = """
Deals 3 Cryo DMG
"""
costs: dict[ElementType, int] = {ElementType.CRYO: 3}
costs: Dict[ElementType, int] = {ElementType.CRYO: 3}
type: SkillType = SkillType.ELEMENTAL_SKILL
damage_element: ElementType = ElementType.CRYO
damage_value: int = 3
Expand All @@ -65,7 +65,7 @@ class KamisatoArtSoumetsu(GenericSkill):
text: str = """
Deals 4 Cryo DMG, summons 1 Frostflake Seki no To.
"""
costs: dict[ElementType, int] = {ElementType.CRYO: 3, ElementType.POWER: 3}
costs: Dict[ElementType, int] = {ElementType.CRYO: 3, ElementType.POWER: 3}
type: SkillType = SkillType.ELEMENTAL_BURST
damage_element: ElementType = ElementType.CRYO
damage_value: int = 4
Expand All @@ -79,10 +79,10 @@ class KamisatoArtSenho(CharacterSkill):
text: str = """
(Passive) When switched to be the active character, this character gains Cryo Elemental Infusion.
"""
costs: dict[ElementType, int] = {}
costs: Dict[ElementType, int] = {}
type: SkillType = SkillType.PASSIVE_SKILL

def use_skill(self, msg_queue: PriorityQueue[Message], parent: "CharacterEntity"):
def use_skill(self, msg_queue: PriorityQueue, parent: "CharacterEntity"):
top_msg = msg_queue.queue[0]
updated = False
if isinstance(top_msg, ChangeCharacterMsg):
Expand All @@ -105,12 +105,12 @@ class KamisatoAyaka(CharacterCard):
id: int = 1105
name: str = "Kamisato Ayaka"
element_type: ElementType = ElementType.CRYO
nations: list[Nation] = [Nation.Inazuma]
nations: List[Nation] = [Nation.Inazuma]
health_point: int = 10
power: int = 0
max_power: int = 3
weapon_type: WeaponType = WeaponType.SWORD
skills: list[CharacterSkill] = [
skills: List[CharacterSkill] = [
KamisatoArtKabuki(),
KamisatoArtHyouka(),
KamisatoArtSoumetsu(),
Expand All @@ -129,7 +129,7 @@ class KantenSenmyouBlessingCard(TalentCard):
id = 211051
name = "Kanten Senmyou Blessing"
character_name: str = "Kamisato Ayaka"
costs: dict[ElementType, int] = {ElementType.CRYO: 2}
costs: Dict[ElementType, int] = {ElementType.CRYO: 2}
text: str = """
The Cryo Elemental Infusion created by your Kamisato Ayaka, who has this card equipped, allows the character to which it is attached to deal +1 Cryo DMG.
When you switch to Kamisato Ayaka, who has this card equipped: Spend 1 less Elemental Die. (Once per Round)
Expand All @@ -138,7 +138,7 @@ class KantenSenmyouBlessingCard(TalentCard):

def use_card(
self,
msg_queue: PriorityQueue[Message],
msg_queue: PriorityQueue,
game_info: "GameInfo",
):
top_msg = msg_queue.queue[0]
Expand All @@ -157,7 +157,7 @@ def use_card(
class KantenSenmyouBlessing(TalentEntity):
name: str = "Kanten Senmyou Blessing"

def msg_handler(self, msg_queue: PriorityQueue["Message"]) -> bool:
def msg_handler(self, msg_queue: PriorityQueue) -> bool:
top_msg = msg_queue.queue[0]
updated = False
if self._uuid in top_msg.responded_entities:
Expand Down
13 changes: 6 additions & 7 deletions gisim/cards/characters/base.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
"""
Basic character card classes
"""
from abc import abstractmethod
from queue import PriorityQueue
from typing import TYPE_CHECKING, Optional, Type, cast
from typing import TYPE_CHECKING, Optional, Dict, List, cast

from pydantic import BaseModel, Field, validator

Expand All @@ -27,15 +26,15 @@ class CharacterSkill(BaseModel):
id: int
name: str
text: str
costs: dict[ElementType, int]
costs: Dict[ElementType, int]
type: SkillType
resource: Optional[str] = None # 图片链接
accumulate_power: int = 1
"""Default for elemental skills and normal attacks.
Elemental burst will accumulate no power by default."""

# @abstractmethod
def use_skill(self, msg_queue: PriorityQueue[Message], parent: "CharacterEntity"):
def use_skill(self, msg_queue: PriorityQueue, parent: "CharacterEntity"):
"""
Called when the skill is activated, by default, it parses the skill text and
returns a list of messages to be sent to the game
Expand Down Expand Up @@ -68,7 +67,7 @@ class GenericSkill(CharacterSkill):
heal_all_value: int = 0
"""Heal all your alive characters"""

def use_skill(self, msg_queue: PriorityQueue[Message], parent: "CharacterEntity"):
def use_skill(self, msg_queue: PriorityQueue, parent: "CharacterEntity"):
msg = msg_queue.get()
msg = cast(UseSkillMsg, msg)
target_player_id, target_char_pos = msg.skill_targets[0]
Expand Down Expand Up @@ -153,9 +152,9 @@ class CharacterCard(BaseModel):
id: int
name: str
element_type: ElementType
nations: list[Nation] = Field(..., min_items=1, max_items=3) # 所属地区/阵营
nations: List[Nation] = Field(..., min_items=1, max_items=3) # 所属地区/阵营
health_point: int = 10
skills: list[CharacterSkill]
skills: List[CharacterSkill]
resource: Optional[str] = None # 图片链接
power: int = 0
max_power: int
Expand Down
44 changes: 22 additions & 22 deletions gisim/cards/equipments/weapons.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from queue import PriorityQueue
from typing import cast
from typing import cast, Dict

from cards.base import WeaponCard
from cards.characters import get_skill_type
from classes.enums import ElementType, EquipmentType, WeaponType
from classes.equipment import WeaponEntity
from classes.message import AfterUsingSkillMsg, DealDamageMsg, Message
from gisim.cards.base import WeaponCard
from gisim.cards.characters import get_skill_type
from gisim.classes.enums import ElementType, EquipmentType, WeaponType
from gisim.classes.equipment import WeaponEntity
from gisim.classes.message import AfterUsingSkillMsg, DealDamageMsg, Message

from gisim.classes.enums import SkillType
from gisim.classes.message import ChangeDiceMsg
Expand All @@ -15,7 +15,7 @@ class MagicGuideCard(WeaponCard):
id: int = 311101
name: str = "Magic Guide"
text: str = """The character deals +1 DMG.(Only Catalyst Characters can equip this. A character can equip a maximum of 1 Weapon)"""
costs: dict[ElementType, int] = {ElementType.SAME: 2}
costs: Dict[ElementType, int] = {ElementType.SAME: 2}
weapon_type: WeaponType = WeaponType.CATALYST


Expand All @@ -28,7 +28,7 @@ class SacrificialFragmentsCard(WeaponCard):
id: int = 311102
name: str = "Sacrificial Fragments"
text: str = """The character deals +1 DMG.After the character uses an Elemental Skill: Create 1 Elemental Die of the same Elemental Type as this character. (Once per Round)(Only Catalyst Characters can equip this. A character can equip a maximum of 1 Weapon)"""
costs: dict[ElementType, int] = {ElementType.SAME: 3}
costs: Dict[ElementType, int] = {ElementType.SAME: 3}
weapon_type: WeaponType = WeaponType.CATALYST


Expand All @@ -41,7 +41,7 @@ class SkywardAtlasCard(WeaponCard):
id: int = 311103
name: str = "Skyward Atlas"
text: str = """The character deals +1 DMG.Once per Round: This character's Normal Attacks deal +1 additional DMG.(Only Catalyst Characters can equip this. A character can equip a maximum of 1 Weapon)"""
costs: dict[ElementType, int] = {ElementType.SAME: 3}
costs: Dict[ElementType, int] = {ElementType.SAME: 3}
weapon_type: WeaponType = WeaponType.CATALYST


Expand All @@ -54,7 +54,7 @@ class RavenBowCard(WeaponCard):
id: int = 311201
name: str = "Raven Bow"
text: str = """The character deals +1 DMG.(Only Bow Characters can equip this. A character can equip a maximum of 1 Weapon)"""
costs: dict[ElementType, int] = {ElementType.SAME: 2}
costs: Dict[ElementType, int] = {ElementType.SAME: 2}
weapon_type: WeaponType = WeaponType.BOW


Expand All @@ -67,7 +67,7 @@ class SacrificialBowCard(WeaponCard):
id: int = 311202
name: str = "Sacrificial Bow"
text: str = """The character deals +1 DMG.After the character uses an Elemental Skill: Create 1 Elemental Die of the same Elemental Type as this character. (Once per Round)(Only Bow Characters can equip this. A character can equip a maximum of 1 Weapon)"""
costs: dict[ElementType, int] = {ElementType.SAME: 3}
costs: Dict[ElementType, int] = {ElementType.SAME: 3}
weapon_type: WeaponType = WeaponType.BOW


Expand All @@ -80,7 +80,7 @@ class SkywardHarpCard(WeaponCard):
id: int = 311203
name: str = "Skyward Harp"
text: str = """The character deals +1 DMG.Once per Round: This character's Normal Attacks deal +1 additional DMG.(Only Bow Characters can equip this. A character can equip a maximum of 1 Weapon)"""
costs: dict[ElementType, int] = {ElementType.SAME: 3}
costs: Dict[ElementType, int] = {ElementType.SAME: 3}
weapon_type: WeaponType = WeaponType.BOW


Expand All @@ -93,7 +93,7 @@ class WhiteIronGreatswordCard(WeaponCard):
id: int = 311301
name: str = "White Iron Greatsword"
text: str = """The character deals +1 DMG.(Only Claymore Characters can equip this. A character can equip a maximum of 1 Weapon)"""
costs: dict[ElementType, int] = {ElementType.SAME: 2}
costs: Dict[ElementType, int] = {ElementType.SAME: 2}
weapon_type: WeaponType = WeaponType.CLAYMORE


Expand All @@ -106,7 +106,7 @@ class SacrificialGreatswordCard(WeaponCard):
id: int = 311302
name: str = "Sacrificial Greatsword"
text: str = """The character deals +1 DMG.After the character uses an Elemental Skill: Create 1 Elemental Die of the same Elemental Type as this character. (Once per Round)(Only Claymore Characters can equip this. A character can equip a maximum of 1 Weapon)"""
costs: dict[ElementType, int] = {ElementType.SAME: 3}
costs: Dict[ElementType, int] = {ElementType.SAME: 3}
weapon_type: WeaponType = WeaponType.CLAYMORE


Expand All @@ -119,7 +119,7 @@ class WolfsGravestoneCard(WeaponCard):
id: int = 311303
name: str = "Wolf's Gravestone"
text: str = """The character deals +1 DMG.Deal +2 additional DMG if the target's remaining HP is equal to or less than 6.(Only Claymore Characters can equip this. A character can equip a maximum of 1 Weapon)"""
costs: dict[ElementType, int] = {ElementType.SAME: 3}
costs: Dict[ElementType, int] = {ElementType.SAME: 3}
weapon_type: WeaponType = WeaponType.CLAYMORE


Expand All @@ -132,7 +132,7 @@ class WhiteTasselCard(WeaponCard):
id: int = 311401
name: str = "White Tassel"
text: str = """The character deals +1 DMG.(Only Polearm Characters can equip this. A character can equip a maximum of 1 Weapon)"""
costs: dict[ElementType, int] = {ElementType.SAME: 2}
costs: Dict[ElementType, int] = {ElementType.SAME: 2}
weapon_type: WeaponType = WeaponType.POLEARM


Expand All @@ -145,7 +145,7 @@ class LithicSpearCard(WeaponCard):
id: int = 311402
name: str = "Lithic Spear"
text: str = """The character deals +1 DMG.When played: For each party member from Liyue, grant 1 Shield point to the character to which this is attached. (Max 3 points)(Only Polearm Characters can equip this. A character can equip a maximum of 1 Weapon)"""
costs: dict[ElementType, int] = {ElementType.SAME: 3}
costs: Dict[ElementType, int] = {ElementType.SAME: 3}
weapon_type: WeaponType = WeaponType.POLEARM


Expand All @@ -158,7 +158,7 @@ class SkywardSpineCard(WeaponCard):
id: int = 311403
name: str = "Skyward Spine"
text: str = """The character deals +1 DMG.Once per Round: This character's Normal Attacks deal +1 additional DMG.(Only Polearm Characters can equip this. A character can equip a maximum of 1 Weapon)"""
costs: dict[ElementType, int] = {ElementType.SAME: 3}
costs: Dict[ElementType, int] = {ElementType.SAME: 3}
weapon_type: WeaponType = WeaponType.POLEARM


Expand All @@ -171,7 +171,7 @@ class TravelersHandySwordCard(WeaponCard):
id: int = 311501
name: str = "Traveler's Handy Sword"
text: str = """The character deals +1 DMG.(Only Sword Characters can equip this. A character can equip a maximum of 1 Weapon)"""
costs: dict[ElementType, int] = {ElementType.SAME: 2}
costs: Dict[ElementType, int] = {ElementType.SAME: 2}
weapon_type: WeaponType = WeaponType.SWORD


Expand All @@ -184,15 +184,15 @@ class SacrificialSwordCard(WeaponCard):
id: int = 311502
name: str = "Sacrificial Sword"
text: str = """The character deals +1 DMG.After the character uses an Elemental Skill: Create 1 Elemental Die of the same Elemental Type as this character. (Once per Round)(Only Sword Characters can equip this. A character can equip a maximum of 1 Weapon)"""
costs: dict[ElementType, int] = {ElementType.SAME: 3}
costs: Dict[ElementType, int] = {ElementType.SAME: 3}
weapon_type: WeaponType = WeaponType.SWORD


class SacrificialSword(WeaponEntity):
name: str = "Sacrificial Sword"
weapon_type: WeaponType = WeaponType.SWORD

def msg_handler(self, msg_queue: PriorityQueue[Message]):
def msg_handler(self, msg_queue: PriorityQueue):
# Increase 1 dmg by default without any advanced effects
top_msg = msg_queue.queue[0]
updated = False
Expand Down Expand Up @@ -237,7 +237,7 @@ class AquilaFavoniaCard(WeaponCard):
id: int = 311503
name: str = "Aquila Favonia"
text: str = """The character deals +1 DMG.After the opposing character uses a Skill: If the character with this attached is the active character, heal this character for 1 HP. (Max twice per Round)(Only Sword Characters can equip this. A character can equip a maximum of 1 Weapon)"""
costs: dict[ElementType, int] = {ElementType.SAME: 3}
costs: Dict[ElementType, int] = {ElementType.SAME: 3}
weapon_type: WeaponType = WeaponType.SWORD


Expand Down
Loading

0 comments on commit 850ee2e

Please sign in to comment.