Skip to main content

Lochfolk Prinzessin Simulator, which simulates Genius Invokation TCG

Project description

Lochfolk Prinzessin Simulator (LPSim): 水皇模拟器,一个七圣召唤模拟器


Coverage Status PyPI version Ruff

English README

该仓库为水皇模拟器的后端,用来模拟七圣召唤对局,使用Python 3.10编写,使用Pydantic和FastAPI。项目另有一个前端仓库,包含可以与该后端交互的前端页面。

该项目使用AGPL-3.0协议。如果您有任何基于此项目的二次开发和分发,请遵守该协议。

声明

本项目仅供学习交流使用,前端界面仅用于展示对局状态和方便代码调试。请在下载后24小时内删除与本项目相关的所有内容。所有相关代码基于AGPLv3协议开源。项目与米哈游公司无关,所有游戏素材版权归米哈游公司所有。本项目及其代码仓库中不包含米哈游具有版权的图像素材,或是任何与米哈游产品相关的非公开信息。

项目进度

:sparkles: 4.5版本角色和卡牌,以及平衡性调整已实现。 :sparkles:

特性

  • 已实现所有截止当前版本的角色和卡牌,包括其历史版本。
  • 支持在同一套卡组中使用不同版本的角色和卡牌。
  • 支持作为一个小型服务器与客户端交互。
  • 提供了一个前端用来与服务器交互。
  • 可以从任意状态加载并继续运行,保持结果不变。
  • 100%代码覆盖率。

使用方法

该项目需要Python 3.10或更新版本。

使用pip安装

使用pip install lpsim安装最新的发布版本。你可以在PyPI找到最新的发布版本,在CHANGELOG.md找到更新日志。

使用pip install lpsim -i https://test.pypi.org/simple/安装最新的开发版本。当新的提交被推送到master分支并通过所有测试时,新的版本将会被发布到Test PyPI。当新的版本tag被推送到master分支时,新的版本将会被发布到PyPI。

使用源码安装

克隆该仓库并使用pip install .安装。

HTTP服务器

对局服务器

使用FastAPI提供一个HTTP对局服务器,用来与客户端交互。使用以下命令运行服务器:

from lpsim.network import HTTPServer
server = HTTPServer()
server.run()

它将在localhost:8000上开启一个FastAPI服务器,并接受本地连接。在初始化HTTPServer时,你可以设置卡组和对局配置来创建一个带有指定规则的对局。

启动服务器后,打开前端页面,在右上角修改服务器URL(默认为http://localhost:8000),按照页面上的指示设置卡组,并开始对局。

目前异常处理比较混乱,错误可能导致游戏状态变为ERROR,服务器抛出异常,客户端返回空响应,返回404/500,或者前端运行JS失败。请打开前端的控制台,并在前端后后端查看错误信息。

房间服务器

你可以使用房间服务器来提供多个对局。它管理多个HTTP服务器实例,前端可以创建新的房间或加入已有的房间。当一个新的房间被创建时,房间服务器会告诉前端房间名和它运行的端口,然后前端会连接到该端口上的HTTP服务器。当一个房间创建了很长时间并且没有收到POST请求时,它会自动关闭。更多细节请参考lpsim/network/http_room_server.pyhttp_room_serve.py

非交互对局

非交互对局主要用于代码测试和AI训练。你可以按照下述流程进行。

定义卡组

开始对局之前,需要先定义卡组。卡组可以使用文本或JSON格式定义。通常使用Deck.from_str就足够了,它可以定义角色和卡牌,以及控制它们的版本。下面的示例代码中的卡组字符串展示了卡组定义的语法,所有卡牌都使用4.1版本,除了风与自由,它使用4.0版本(因为它在3.7版本之后没有改变,当指定4.0版本时,卡组会自动选择3.7版本)。同时,也支持使用牌组分享码导入牌组。更多细节请参考server/deck.py

开始对局

  1. 初始化一个新的server.Match实例。
  2. 使用set_deck函数为玩家分配卡组。
  3. 如果需要,修改Match.config
  4. 卡组设置完成后,使用Match.start函数开始对局。它会根据配置和卡组初始化对局。如果出现错误(例如卡组不合法),它会返回False和具体错误信息。
  5. 使用Match.step函数推进对局。默认情况下,该函数会持续执行,直到对局结束或者生成需要响应的请求。

为了更方便的响应请求,在agents模块中项目包含了一些简单的代理。这些代理可以响应各种请求。特别的,InteractionAgent可以解析命令行并生成响应,使用命令行交互时较为方便。同时,该代理也是前端和后端交互时使用的代理。

示例代码

from lpsim import Match, Deck
from lpsim.agents import RandomAgent
deck_string = '''
default_version:4.1
character:Fischl
character:Mona
character:Nahida
Gambler's Earrings*2
Wine-Stained Tricorne*2
Vanarana
Timmie*2
Rana*2
Covenant of Rock
Wind and Freedom@4.0
The Bestest Travel Companion!*2
Changing Shifts*2
Toss-Up
Strategize*2
I Haven't Lost Yet!*2
Leave It to Me!
Calx's Arts*2
Adeptus' Temptation*2
Lotus Flower Crisp*2
Mondstadt Hash Brown*2
Tandoori Roast Chicken
'''
deck0 = Deck.from_str(deck_string)
deck1 = Deck.from_str(deck_string)
match = Match()
match.set_deck([deck0, deck1])
match.start()
match.step()

agent_0 = RandomAgent(player_idx = 0)
agent_1 = RandomAgent(player_idx = 1)

while not match.is_game_end():
    if match.need_respond(0):
        match.respond(agent_0.generate_response(match))
    elif match.need_respond(1):
        match.respond(agent_1.generate_response(match))
    match.step()

print(f'winner is {match.winner}')

自定义角色和卡牌

自定义角色和卡牌前,你需要了解actions, event handlers和value modifiers。所有与对局的交互(一个实例需要修改对局中其他实例的状态)都是通过actions完成的,所有的actions都是由events触发的。value modifiers用来修改值,例如骰子消耗和伤害数值/类型。最简单的实现一个新的对象的方法是参考并复制一个已有的卡牌/角色/技能/状态...并修改它。你可以在细节中找到更多信息。

templates/character.py是一个角色的模板。你可以复制它并修改它来实现一个新的角色。你可以定义任何与角色相关的对象,例如技能、天赋、召唤、状态。然后,你需要为这些对象创建描述,描述将会在前端中使用,class registry会拒绝没有描述的对象。最后,使用register_class函数将所有对象以及它们的描述注册到class registry中,就可以在对局中使用它们了。

定义一个新的卡牌相对简单,你可以参考templates/card.py,它定义了一个新的卡牌“大心海”,它消耗2个任意骰子并抽3张牌。作为自定义卡牌的示例,在这个文件里使用了absolute import,因此可以在项目外直接使用。

你可以手动注册新的对象并在对局中使用它们。以“大心海”为例,首先安装lpsim,然后在import lpsim之后输入import templates.card。然后你可以通过a = HTTPServer(); a.run()创建一个HTTP服务器,你会发现修改卡组时一个新的卡牌被添加到了候选卡牌列表中。总代码如下,在项目根目录运行:

import lpsim
import templates.card
a = lpsim.HTTPServer()
a.run()

细节

使用Pydantic保存和加载对局状态,导出的数据可以用来恢复对局到某个状态并继续运行,也可以用来渲染前端的对局状态。

兼容不同版本的角色和卡牌。例如你可以开启一个3.8版本的双岩一斗和3.3版本的双岩剑鬼的对局,或者使用3.3的神宵和3.7的申鹤配合4.3的新行动牌和装备。

通过requestresponse来交互。当request列表不为空时,代理需要响应其中的一个请求。当多个玩家需要响应时(例如在游戏开始时选择角色和卡牌),它们的请求会同时生成。

对局中的所有修改都是通过action来实现的。每个action都会触发一个事件,并且可能会激活后续的action。这些新激活的action会被添加到现有的action列表的顶部,类似于堆栈列表的结构,参考EventFrame类的实现。

对局中所有的对象包含两种触发器:event handlers和value modifiers。事件处理器用来监控事件并产生响应的action列表。值修改器用来修改可变值并在必要时更新内部状态。可修改的值包括初始骰子颜色、伤害和消耗等。

所有的代码都使用pytest进行测试,覆盖率100%(除了防御性代码,它们被标记为# pragma: no cover)。由于完全兼容不同版本,当实现了新的版本时,所有已有测试都应该通过而不需要修改。

贡献

欢迎合作开发项目代码,但是目前没有详细的文档。在贡献代码前,您可以首先阅读CONTRIBUTING.md(英文),它包含了如何安装开发环境和如何运行测试的信息。

如果你想添加新的角色相关的对象(角色、技能、天赋、召唤、状态),请参考server/character/template.py和已经实现的角色。如果你想添加新的卡牌,请参考server/card中已经实现的卡牌。完成代码编写后使用register_class函数注册新的对象到模拟器中即可使用。

你可以通过QQ群945778865联系作者,咨询开发和使用上的问题,进群问题的答案是模拟器的中文名。

开发这个项目花费了大量(本来用来打牌和打模拟宇宙的)时间。如果你觉得这个项目有帮助,您可以通过微信支持作者。

wechat

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lpsim-0.4.5.1.tar.gz (1.1 MB view hashes)

Uploaded Source

Built Distribution

lpsim-0.4.5.1-py3-none-any.whl (559.2 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page