This commit is contained in:
File diff suppressed because it is too large
Load Diff
+45
@@ -0,0 +1,45 @@
|
||||
"""Generated reviewed adapter for coin-taffy."""
|
||||
|
||||
from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
|
||||
|
||||
PROFILE = 'coin-taffy'
|
||||
AUTHOR = 'jwebot'
|
||||
DESCRIPTION = 'Taffy金币'
|
||||
HELP_ENTRIES = ('/Taffy金币',)
|
||||
COMMANDS = ('/Taffy金币', '/taffycoins')
|
||||
|
||||
|
||||
def _handler(context: SingleGroupContext, command: str):
|
||||
def handle(event: Event, arguments: str) -> ExtensionResult:
|
||||
response = context.services.call(
|
||||
PROFILE,
|
||||
operation="execute",
|
||||
payload={
|
||||
"command": command,
|
||||
"arguments": arguments,
|
||||
"event": event.to_mapping(),
|
||||
},
|
||||
)
|
||||
texts = response.get("texts")
|
||||
if isinstance(texts, list) and texts and all(
|
||||
isinstance(item, str) and item.strip() for item in texts
|
||||
):
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.multi_text(texts),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
text = response.get("text")
|
||||
if not isinstance(text, str) or not text.strip():
|
||||
raise ValueError("local service returned invalid text")
|
||||
return ExtensionResult(
|
||||
reply=ReplyPlan.text(text),
|
||||
metadata={"local_extension": PROFILE, "author": AUTHOR},
|
||||
)
|
||||
|
||||
return handle
|
||||
|
||||
|
||||
def plugin(context: SingleGroupContext) -> None:
|
||||
for command in COMMANDS:
|
||||
context.commands.register(command, _handler(context, command))
|
||||
+1
-1
@@ -5,7 +5,7 @@ from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
|
||||
PROFILE = 'context-summary'
|
||||
AUTHOR = 'official'
|
||||
DESCRIPTION = '提取当前群最近100、200或300条本地文字的上下文'
|
||||
DESCRIPTION = '上下文总结'
|
||||
HELP_ENTRIES = ('/上下文 [100|200|300];/context [100|200|300]',)
|
||||
COMMANDS = ('/上下文', '/context')
|
||||
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext
|
||||
PROFILE = 'single-player-games'
|
||||
AUTHOR = 'jwebot'
|
||||
DESCRIPTION = '金币游戏'
|
||||
HELP_ENTRIES = ('/金币 /wallet;/游戏记录 /gamehistory', '/抽奖 [金额];/draw', '/彩票 开始|报名|状态|开奖|取消;/lottery', '/21点 开始 [1~500];/blackjack start', '/21点 要牌|停牌|状态|结束;/blackjack', '/游戏帮助;/games')
|
||||
HELP_ENTRIES = ('/金币 /wallet;/游戏记录 /gamehistory', '/抽奖 [金额];/draw', '/彩票 开始|报名|状态|开奖|取消;/lottery', '/21点 单人开始|要牌|停牌|状态;多人启动|加入|开始|放200', '/游戏帮助;/games')
|
||||
COMMANDS = ('/金币', '/wallet', '/抽奖', '/draw', '/彩票', '/买彩票', '/lottery', '/21点', '/二十一点', '/blackjack', '/游戏记录', '/个人记录', '/gamehistory', '/游戏帮助', '/games')
|
||||
|
||||
|
||||
|
||||
@@ -46,6 +46,8 @@ LOCAL_COMMAND_ALIASES = {
|
||||
"金币排行榜": "coin_ranking",
|
||||
"大富翁榜": "coin_ranking",
|
||||
"richlist": "coin_ranking",
|
||||
"Taffy金币": "taffy_coins",
|
||||
"taffycoins": "taffy_coins",
|
||||
"转账": "transfer",
|
||||
"transfer": "transfer",
|
||||
"贷款": "loan",
|
||||
@@ -143,7 +145,7 @@ LOCAL_EXTENSIONS = (
|
||||
LocalExtensionDescriptor(
|
||||
extension_id="context-summary",
|
||||
author=OFFICIAL_AUTHOR,
|
||||
description="提取当前群最近100、200或300条本地文字的上下文",
|
||||
description="上下文总结",
|
||||
help_entries=("/上下文 [100|200|300];/context [100|200|300]",),
|
||||
command_kinds=("context_summary",),
|
||||
),
|
||||
@@ -155,8 +157,7 @@ LOCAL_EXTENSIONS = (
|
||||
"/金币 /wallet;/游戏记录 /gamehistory",
|
||||
"/抽奖 [金额];/draw",
|
||||
"/彩票 开始|报名|状态|开奖|取消;/lottery",
|
||||
"/21点 开始 [1~500];/blackjack start",
|
||||
"/21点 要牌|停牌|状态|结束;/blackjack",
|
||||
"/21点 单人开始|要牌|停牌|状态;多人启动|加入|开始|放200",
|
||||
"/游戏帮助;/games",
|
||||
),
|
||||
command_kinds=(
|
||||
@@ -182,6 +183,13 @@ LOCAL_EXTENSIONS = (
|
||||
help_entries=("/大富翁榜",),
|
||||
command_kinds=("coin_ranking",),
|
||||
),
|
||||
LocalExtensionDescriptor(
|
||||
extension_id="coin-taffy",
|
||||
author=JWEBOT_AUTHOR,
|
||||
description="Taffy金币",
|
||||
help_entries=("/Taffy金币",),
|
||||
command_kinds=("taffy_coins",),
|
||||
),
|
||||
LocalExtensionDescriptor(
|
||||
extension_id="coin-loan",
|
||||
author=JWEBOT_AUTHOR,
|
||||
|
||||
@@ -157,6 +157,7 @@ class LocalCommandEngine:
|
||||
if kind in {
|
||||
"wallet",
|
||||
"coin_ranking",
|
||||
"taffy_coins",
|
||||
"transfer",
|
||||
"loan",
|
||||
"repay",
|
||||
|
||||
@@ -16,6 +16,9 @@ MAX_LOTTERY_BET = 500
|
||||
DEFAULT_LOTTERY_BET = 10
|
||||
MIN_BLACKJACK_BET = 1
|
||||
MAX_BLACKJACK_BET = 500
|
||||
MIN_BLACKJACK_TABLE_BET = 1
|
||||
MAX_BLACKJACK_TABLE_BET = 10_000
|
||||
MAX_BLACKJACK_TABLE_PLAYERS = 8
|
||||
MIN_TRANSFER_AMOUNT = 1
|
||||
MAX_TRANSFER_AMOUNT = 100_000
|
||||
MIN_LOAN_AMOUNT = 1
|
||||
@@ -45,6 +48,10 @@ BLACKJACK_COMBINED_ACTION = re.compile(
|
||||
r"^(?:开始|start)(?P<bet>\d{1,3})?"
|
||||
r"(?:要牌|hit|停牌|stand)$"
|
||||
)
|
||||
BLACKJACK_TABLE_BET = re.compile(
|
||||
r"^(?:放|下注|bet)(?P<bet>\d{1,5})$",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
TRANSFER_MARKED = re.compile(
|
||||
r"^(?:给|to)?\s*(?P<target>.+?)\s*"
|
||||
r"(?:金额|金币|coin|coins|:|:)\s*(?P<amount>\d{1,6})$",
|
||||
@@ -161,6 +168,9 @@ class PlayerGames:
|
||||
"看到牌后再单独发送 /21点 要牌|停牌|状态|结束"
|
||||
"(/blackjack hit|stand|status|end);"
|
||||
"每人最多一局,10分钟无操作视为认输,结束不退下注。\n"
|
||||
"多人21点:/21点 多人 启动 创建牌桌;/21点 加入;"
|
||||
"主持人 /21点 多人 开始 后按提示 /21点 放200"
|
||||
"(1~10000);轮到自己 /21点 要牌|停牌。\n"
|
||||
"21点获胜返2倍、平局返下注、自然21点返2.5倍向下取整,庄家软17停牌。"
|
||||
"以上均含本金;虚拟金币不能充值或兑换。"
|
||||
)
|
||||
@@ -177,6 +187,8 @@ class PlayerGames:
|
||||
return self.group_lottery(row, arguments)
|
||||
if kind == "coin_ranking":
|
||||
return self.coin_ranking(row, arguments)
|
||||
if kind == "taffy_coins":
|
||||
return self.taffy_coins(row, arguments)
|
||||
if kind == "transfer":
|
||||
return self.transfer(row, arguments)
|
||||
if kind in {"loan", "repay"}:
|
||||
@@ -188,6 +200,15 @@ class PlayerGames:
|
||||
return "用法:/抽奖 [2~100金币](/draw),默认10金币"
|
||||
bet = int(arguments or 10)
|
||||
elif kind == "blackjack":
|
||||
table_command = self.parse_blackjack_table_command(arguments)
|
||||
if table_command is not None:
|
||||
table_action, table_bet = table_command
|
||||
return self.group_blackjack(
|
||||
row,
|
||||
table_action,
|
||||
table_bet,
|
||||
arguments,
|
||||
)
|
||||
compacted = re.sub(r"\s+", "", arguments.casefold()) or "状态"
|
||||
start = BLACKJACK_START.fullmatch(compacted)
|
||||
if start is not None:
|
||||
@@ -209,6 +230,28 @@ class PlayerGames:
|
||||
"用法:先 /21点 开始 [1~500](金额是本局下注,默认50);"
|
||||
"开局后再单独发送 /21点 要牌|停牌|状态|结束;空格可省略"
|
||||
)
|
||||
group = str(row["group_fingerprint"])
|
||||
if (
|
||||
action in {"hit", "stand", "status"}
|
||||
and self.ledger.has_active_group_blackjack(group)
|
||||
):
|
||||
return self.group_blackjack(row, action, 0, arguments)
|
||||
if (
|
||||
action == "start"
|
||||
and self.ledger.has_active_group_blackjack(group)
|
||||
):
|
||||
return (
|
||||
"当前已有Taffy的21点多人牌桌;"
|
||||
"发送 /21点 状态 查看,或等待本桌结束"
|
||||
)
|
||||
if (
|
||||
action == "end"
|
||||
and self.ledger.has_active_group_blackjack(group)
|
||||
):
|
||||
return (
|
||||
"当前是多人21点牌桌;轮到你时请 /21点 停牌,"
|
||||
"主持人可 /21点 多人 取消"
|
||||
)
|
||||
else:
|
||||
bet = 0
|
||||
if kind == "prize_draw" and not MIN_DRAW_BET <= bet <= MAX_DRAW_BET:
|
||||
@@ -341,6 +384,451 @@ class PlayerGames:
|
||||
)
|
||||
return "\n".join(lines)
|
||||
|
||||
def taffy_coins(self, row: dict[str, Any], arguments: str) -> str:
|
||||
value = arguments.strip()
|
||||
if value and not re.fullmatch(r"\d{1,2}", value):
|
||||
return "用法:/Taffy金币 [人数]"
|
||||
limit = int(value or 8)
|
||||
if not 1 <= limit <= 20:
|
||||
return "Taffy金币人数必须为 1~20"
|
||||
stats = self.ledger.player_taffy_coin_stats(
|
||||
str(row["group_fingerprint"]),
|
||||
limit=limit,
|
||||
)
|
||||
if int(stats["records"]) == 0:
|
||||
return "Taffy金币:当前群暂无已结算游戏记录"
|
||||
net = int(stats["taffy_net"])
|
||||
result = f"Taffy累计赢 {net} 金币" if net >= 0 else f"Taffy累计倒贴 {-net} 金币"
|
||||
lines = [
|
||||
(
|
||||
f"Taffy金币:已结算 {stats['records']} 局;"
|
||||
f"玩家总下注 {stats['stake']},总返还 {stats['payout']};"
|
||||
f"{result}"
|
||||
)
|
||||
]
|
||||
if stats["players"]:
|
||||
lines.append("最大上贡者排行(含负数):")
|
||||
else:
|
||||
lines.append("最大上贡者排行:暂无已结算玩家明细")
|
||||
for index, record in enumerate(stats["players"], start=1):
|
||||
player_net = int(record["taffy_net"])
|
||||
if player_net > 0:
|
||||
verdict = f"上贡 {player_net}"
|
||||
elif player_net < 0:
|
||||
verdict = f"从Taffy赢走 {-player_net}"
|
||||
else:
|
||||
verdict = "打平 0"
|
||||
lines.append(
|
||||
f"{index}. {record['display_name']}:{verdict};"
|
||||
f"下注 {record['stake']},返还 {record['payout']},"
|
||||
f"{record['records']} 局"
|
||||
)
|
||||
return "\n".join(lines)
|
||||
|
||||
@staticmethod
|
||||
def parse_blackjack_table_command(
|
||||
arguments: str,
|
||||
) -> tuple[str, int] | None:
|
||||
compacted = re.sub(r"\s+", "", arguments.casefold())
|
||||
if not compacted:
|
||||
return None
|
||||
if compacted in {"多人", "牌桌", "table", "multiplayer"}:
|
||||
return "help", 0
|
||||
if compacted in {
|
||||
"多人启动",
|
||||
"多人开桌",
|
||||
"多人创建",
|
||||
"牌桌启动",
|
||||
"牌桌开桌",
|
||||
"tablestart",
|
||||
"multiplayerstart",
|
||||
}:
|
||||
return "start", 0
|
||||
if compacted in {"加入", "join"}:
|
||||
return "join", 0
|
||||
if compacted in {
|
||||
"多人开始",
|
||||
"多人发牌",
|
||||
"开始多人",
|
||||
"开桌",
|
||||
"发牌",
|
||||
"tabledeal",
|
||||
"multiplayerdeal",
|
||||
}:
|
||||
return "begin", 0
|
||||
if compacted in {
|
||||
"多人取消",
|
||||
"牌桌取消",
|
||||
"取消牌桌",
|
||||
"tablecancel",
|
||||
"multiplayercancel",
|
||||
}:
|
||||
return "cancel", 0
|
||||
bet = BLACKJACK_TABLE_BET.fullmatch(compacted)
|
||||
if bet is not None:
|
||||
return "bet", int(bet["bet"])
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def blackjack_players_text(players: list[dict[str, Any]]) -> str:
|
||||
names = [str(player["display_name"]) for player in players]
|
||||
return "、".join(names) if names else "暂无"
|
||||
|
||||
@staticmethod
|
||||
def blackjack_hand_text(hand: list[int]) -> str:
|
||||
if not hand:
|
||||
return "未发牌"
|
||||
return (
|
||||
f"{' '.join(card_label(card) for card in hand)}"
|
||||
f"({hand_value(hand)}点)"
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def blackjack_prompt(player: dict[str, Any]) -> str:
|
||||
return (
|
||||
f"请{player['display_name']} 放自己的筹码\n"
|
||||
"输入/21点 放200(1~10000)"
|
||||
)
|
||||
|
||||
def group_blackjack(
|
||||
self,
|
||||
row: dict[str, Any],
|
||||
action: str,
|
||||
amount: int,
|
||||
arguments: str,
|
||||
) -> str:
|
||||
group = str(row["group_fingerprint"])
|
||||
sender = str(row["sender"])
|
||||
event_id = str(row["event_id"])
|
||||
command = f"blackjack-table:{arguments}"
|
||||
if action == "help":
|
||||
return (
|
||||
"多人21点用法:/21点 多人 启动;/21点 加入;"
|
||||
"主持人 /21点 多人 开始;按提示 /21点 放200"
|
||||
"(1~10000);轮到自己 /21点 要牌 或 /21点 停牌"
|
||||
)
|
||||
if action == "start":
|
||||
return self.ledger.start_group_blackjack(
|
||||
group,
|
||||
sender,
|
||||
event_id,
|
||||
command,
|
||||
max_players=MAX_BLACKJACK_TABLE_PLAYERS,
|
||||
render=self.render_blackjack_table_start,
|
||||
)
|
||||
if action == "join":
|
||||
return self.ledger.join_group_blackjack(
|
||||
group,
|
||||
sender,
|
||||
event_id,
|
||||
command,
|
||||
max_players=MAX_BLACKJACK_TABLE_PLAYERS,
|
||||
render=self.render_blackjack_table_join,
|
||||
)
|
||||
if action == "begin":
|
||||
return self.ledger.begin_group_blackjack_betting(
|
||||
group,
|
||||
sender,
|
||||
event_id,
|
||||
command,
|
||||
self.render_blackjack_table_begin,
|
||||
)
|
||||
if action == "cancel":
|
||||
return self.ledger.cancel_group_blackjack(
|
||||
group,
|
||||
sender,
|
||||
event_id,
|
||||
command,
|
||||
self.render_blackjack_table_cancel,
|
||||
)
|
||||
if action == "status":
|
||||
return self.ledger.group_blackjack_status(
|
||||
group,
|
||||
sender,
|
||||
event_id,
|
||||
command,
|
||||
self.render_blackjack_table_status,
|
||||
)
|
||||
if action == "bet":
|
||||
if not MIN_BLACKJACK_TABLE_BET <= amount <= MAX_BLACKJACK_TABLE_BET:
|
||||
return "21点多人牌桌筹码必须为 1~10000 的整数金币"
|
||||
deck = list(range(52))
|
||||
self.rng.shuffle(deck)
|
||||
return self.ledger.place_group_blackjack_bet(
|
||||
group,
|
||||
sender,
|
||||
event_id,
|
||||
command,
|
||||
amount,
|
||||
deck,
|
||||
self.render_blackjack_table_bet,
|
||||
)
|
||||
if action in {"hit", "stand"}:
|
||||
return self.ledger.play_group_blackjack(
|
||||
group,
|
||||
sender,
|
||||
event_id,
|
||||
command,
|
||||
action,
|
||||
self.render_blackjack_table_action,
|
||||
)
|
||||
raise ValueError(f"unsupported blackjack table action: {action}")
|
||||
|
||||
def render_blackjack_table_start(self, data: dict[str, Any]) -> str:
|
||||
status = data["status"]
|
||||
if status == "private_game":
|
||||
return (
|
||||
f"{data['display_name']}:你已有单人21点,"
|
||||
"请先 /21点 停牌 或 /21点 结束"
|
||||
)
|
||||
players = data.get("players", [])
|
||||
prefix = (
|
||||
"当前已有Taffy 的黑杰克Blackjack 21点牌桌"
|
||||
if status == "already_open"
|
||||
else "欢迎来到Taffy 的黑杰克Blackjack 21点牌桌"
|
||||
)
|
||||
return (
|
||||
f"{prefix}\n"
|
||||
"输入/21点 加入 加入当前游戏!"
|
||||
f"目前玩家:{self.blackjack_players_text(players)}\n"
|
||||
"主持人发送 /21点 多人 开始 后,"
|
||||
"Taffy会按顺序喊每个人放筹码"
|
||||
)
|
||||
|
||||
def render_blackjack_table_join(self, data: dict[str, Any]) -> str:
|
||||
status = data["status"]
|
||||
if status == "no_table":
|
||||
return "当前没有21点多人牌桌;发送 /21点 多人 启动"
|
||||
if status == "closed":
|
||||
return "这桌已经停止加入;发送 /21点 状态 查看当前进度"
|
||||
if status == "full":
|
||||
return f"这桌已满,最多 {data['max_players']} 人"
|
||||
if status == "private_game":
|
||||
return (
|
||||
f"{data['display_name']}:你已有单人21点,"
|
||||
"请先 /21点 停牌 或 /21点 结束"
|
||||
)
|
||||
if status == "already_joined":
|
||||
return (
|
||||
f"{data['display_name']} 已经在这桌;"
|
||||
f"目前玩家:{self.blackjack_players_text(data['players'])}"
|
||||
)
|
||||
return (
|
||||
f"{data['display_name']} 已加入Taffy的21点牌桌;"
|
||||
f"目前玩家:{self.blackjack_players_text(data['players'])}"
|
||||
)
|
||||
|
||||
def render_blackjack_table_begin(self, data: dict[str, Any]) -> str:
|
||||
status = data["status"]
|
||||
if status == "no_table":
|
||||
return "当前没有21点多人牌桌;发送 /21点 多人 启动"
|
||||
if status == "not_host":
|
||||
return f"只有本桌主持人 {data['host_display_name']} 可以结束加入"
|
||||
if status == "not_joining":
|
||||
return "这桌已经结束加入;发送 /21点 状态 查看当前进度"
|
||||
if status == "not_enough":
|
||||
return (
|
||||
"至少需要 2 名玩家才能开始多人21点;"
|
||||
f"目前玩家:{self.blackjack_players_text(data['players'])}"
|
||||
)
|
||||
return (
|
||||
"加入结束,Taffy 按顺序收筹码。\n"
|
||||
f"{self.blackjack_prompt(data['prompt_player'])}"
|
||||
)
|
||||
|
||||
def render_blackjack_table_status(self, data: dict[str, Any]) -> str:
|
||||
if data["status"] == "no_table":
|
||||
return "当前没有21点多人牌桌;发送 /21点 多人 启动"
|
||||
state = str(data["state"])
|
||||
table_number = int(data["table_number"])
|
||||
players = data["players"]
|
||||
if state == "joining":
|
||||
return (
|
||||
f"21点牌桌第 {table_number} 桌正在加入;"
|
||||
f"目前玩家:{self.blackjack_players_text(players)}\n"
|
||||
"输入/21点 加入 加入当前游戏;"
|
||||
"主持人 /21点 多人 开始"
|
||||
)
|
||||
if state == "betting":
|
||||
prompt = next(
|
||||
(
|
||||
player for player in players
|
||||
if str(player["person_key"]) == str(data["turn_person_key"])
|
||||
),
|
||||
None,
|
||||
)
|
||||
lines = [f"21点牌桌第 {table_number} 桌正在下注:"]
|
||||
for player in players:
|
||||
bet = int(player["bet"])
|
||||
lines.append(
|
||||
f"{player['display_name']} #{player['player_game_index']}:"
|
||||
f"{bet if bet else '未放'}"
|
||||
)
|
||||
if prompt is not None:
|
||||
lines.append(self.blackjack_prompt(prompt))
|
||||
return "\n".join(lines)
|
||||
if state == "playing":
|
||||
prompt = next(
|
||||
(
|
||||
player for player in players
|
||||
if str(player["person_key"]) == str(data["turn_person_key"])
|
||||
),
|
||||
None,
|
||||
)
|
||||
dealer = data.get("dealer", [])
|
||||
dealer_text = (
|
||||
f"{card_label(dealer[0])} + 暗牌"
|
||||
if dealer
|
||||
else "未发牌"
|
||||
)
|
||||
lines = [
|
||||
f"21点牌桌第 {table_number} 桌正在出牌;Taffy {dealer_text}"
|
||||
]
|
||||
for player in players:
|
||||
lines.append(
|
||||
f"{player['display_name']} #{player['player_game_index']}:"
|
||||
f"{self.blackjack_hand_text(player['hand'])};"
|
||||
f"下注 {player['bet']};{player['state']}"
|
||||
)
|
||||
if prompt is not None:
|
||||
lines.append(
|
||||
f"请{prompt['display_name']} 操作:"
|
||||
"/21点 要牌 或 /21点 停牌"
|
||||
)
|
||||
return "\n".join(lines)
|
||||
return "当前没有进行中的21点多人牌桌"
|
||||
|
||||
def render_blackjack_table_bet(self, data: dict[str, Any]) -> str:
|
||||
status = data["status"]
|
||||
if status == "no_table":
|
||||
return "当前没有21点多人牌桌;发送 /21点 多人 启动"
|
||||
if status == "not_betting":
|
||||
return "现在不是放筹码阶段;发送 /21点 状态 查看当前进度"
|
||||
if status == "not_player":
|
||||
return "你不在当前21点牌桌;下一桌可发送 /21点 加入"
|
||||
if status == "wrong_turn":
|
||||
return self.blackjack_prompt(data["prompt_player"])
|
||||
if status == "insufficient":
|
||||
return (
|
||||
f"{data['display_name']}:金币不足,余额 {data['balance']},"
|
||||
f"本次需要 {data['bet']}"
|
||||
)
|
||||
if status == "bet_accepted":
|
||||
return (
|
||||
f"{data['display_name']} 放下 {data['bet']};"
|
||||
f"金币 {data['balance']}\n"
|
||||
f"{self.blackjack_prompt(data['prompt_player'])}"
|
||||
)
|
||||
if status == "dealt":
|
||||
return self.render_blackjack_table_dealt(data)
|
||||
if status == "settled":
|
||||
return self.render_blackjack_table_settlement(data)
|
||||
raise ValueError(f"unsupported blackjack bet status: {status}")
|
||||
|
||||
def render_blackjack_table_dealt(self, data: dict[str, Any]) -> str:
|
||||
dealer = data.get("dealer", [])
|
||||
dealer_text = (
|
||||
f"{card_label(dealer[0])} + 暗牌"
|
||||
if dealer
|
||||
else "未发牌"
|
||||
)
|
||||
lines = [
|
||||
(
|
||||
f"{data['display_name']} 放下 {data['bet']};"
|
||||
"全部筹码已确认。Taffy 发牌。"
|
||||
),
|
||||
f"Taffy 明牌 {dealer_text}",
|
||||
]
|
||||
for player in data["players"]:
|
||||
lines.append(
|
||||
f"{player['display_name']} #{player['player_game_index']}:"
|
||||
f"{self.blackjack_hand_text(player['hand'])};"
|
||||
f"下注 {player['bet']}"
|
||||
)
|
||||
prompt = data["prompt_player"]
|
||||
lines.append(
|
||||
f"请{prompt['display_name']} 操作:/21点 要牌 或 /21点 停牌"
|
||||
)
|
||||
return "\n".join(lines)
|
||||
|
||||
def render_blackjack_table_action(self, data: dict[str, Any]) -> str:
|
||||
status = data["status"]
|
||||
if status == "no_table":
|
||||
return "当前没有21点多人牌桌;发送 /21点 多人 启动"
|
||||
if status == "not_playing":
|
||||
return "现在不是出牌阶段;发送 /21点 状态 查看当前进度"
|
||||
if status == "not_player":
|
||||
return "你不在当前21点牌桌;下一桌可发送 /21点 加入"
|
||||
if status == "wrong_turn":
|
||||
prompt = data["prompt_player"]
|
||||
return (
|
||||
f"现在轮到 {prompt['display_name']};"
|
||||
"/21点 要牌 或 /21点 停牌"
|
||||
)
|
||||
if status == "not_actionable":
|
||||
return "你这一手已经结束;等待本桌结算"
|
||||
if status == "settled":
|
||||
return self.render_blackjack_table_settlement(data)
|
||||
player = data["player"]
|
||||
lines: list[str] = []
|
||||
if status == "hit":
|
||||
lines.append(
|
||||
f"{player['display_name']} 要牌,拿到 "
|
||||
f"{card_label(data['drawn_card'])};"
|
||||
f"当前 {self.blackjack_hand_text(player['hand'])}"
|
||||
)
|
||||
elif status == "busted":
|
||||
lines.append(
|
||||
f"{player['display_name']} 要牌,拿到 "
|
||||
f"{card_label(data['drawn_card'])};"
|
||||
f"{self.blackjack_hand_text(player['hand'])} 爆牌"
|
||||
)
|
||||
elif status == "stood":
|
||||
lines.append(
|
||||
f"{player['display_name']} 停牌;"
|
||||
f"{self.blackjack_hand_text(player['hand'])}"
|
||||
)
|
||||
else:
|
||||
raise ValueError(f"unsupported blackjack action status: {status}")
|
||||
prompt = data["prompt_player"]
|
||||
lines.append(
|
||||
f"请{prompt['display_name']} 操作:/21点 要牌 或 /21点 停牌"
|
||||
)
|
||||
return "\n".join(lines)
|
||||
|
||||
def render_blackjack_table_settlement(self, data: dict[str, Any]) -> str:
|
||||
dealer = data.get("dealer", [])
|
||||
dealer_text = self.blackjack_hand_text(dealer)
|
||||
lines = [
|
||||
(
|
||||
"Taffy 的黑杰克Blackjack 21点牌桌"
|
||||
f"第 {data['table_number']} 桌结算:"
|
||||
),
|
||||
f"Taffy 庄家 {dealer_text}",
|
||||
"这一桌每个人的变化:",
|
||||
]
|
||||
for player in data["players"]:
|
||||
bet = int(player["bet"])
|
||||
payout = int(player["payout"])
|
||||
lines.append(
|
||||
f"{player['display_name']} #{player['player_game_index']}:"
|
||||
f"{player['outcome']};牌 {self.blackjack_hand_text(player['hand'])};"
|
||||
f"下注 {bet},返还 {payout},净变化 {payout - bet:+d};"
|
||||
f"金币 {player['balance']}"
|
||||
)
|
||||
return "\n".join(lines)
|
||||
|
||||
def render_blackjack_table_cancel(self, data: dict[str, Any]) -> str:
|
||||
status = data["status"]
|
||||
if status == "no_table":
|
||||
return "当前没有21点多人牌桌"
|
||||
if status == "not_host":
|
||||
return f"只有本桌主持人 {data['host_display_name']} 可以取消"
|
||||
return (
|
||||
f"21点牌桌第 {data['table_number']} 桌已取消;"
|
||||
f"{data['refunded']} 人的下注已退回"
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def parse_transfer(
|
||||
arguments: str,
|
||||
|
||||
Reference in New Issue
Block a user