Files
WPSBot/games/casino.py
2025-10-31 11:16:38 +08:00

410 lines
15 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""赌场游戏模块"""
import logging
import random
from games.base import BaseGame
from utils.parser import CommandParser
from core.database import get_db
logger = logging.getLogger(__name__)
class CasinoGame(BaseGame):
"""赌场游戏"""
def __init__(self):
"""初始化游戏"""
super().__init__()
self.db = get_db()
async def handle(self, command: str, chat_id: int, user_id: int) -> str:
"""处理赌场指令
Args:
command: 完整指令
chat_id: 会话ID
user_id: 用户ID
Returns:
回复消息
"""
try:
# 提取参数
_, args = CommandParser.extract_command_args(command)
args = args.strip().lower()
# 没有参数,显示帮助
if not args:
return self.get_help()
# 解析第一个参数为游戏类型
parts = args.split(maxsplit=1)
game_type = parts[0]
sub_args = parts[1] if len(parts) > 1 else ""
# 根据游戏类型分发
if game_type == '大小':
return await self._handle_bigsmall(sub_args, chat_id, user_id)
elif game_type in ['help', '帮助']:
return self.get_help()
else:
return f"❌ 暂不支持的游戏类型: {game_type}\n\n支持的类型:大小"
except Exception as e:
logger.error(f"处理赌场指令错误: {e}", exc_info=True)
return f"❌ 处理指令出错: {str(e)}"
async def _handle_bigsmall(self, args: str, chat_id: int, user_id: int) -> str:
"""处理大小游戏
Args:
args: 子命令和参数
chat_id: 会话ID
user_id: 用户ID
Returns:
回复消息
"""
if not args:
return self._get_bigsmall_help()
# 解析子命令
parts = args.split(maxsplit=1)
action = parts[0].lower()
sub_args = parts[1] if len(parts) > 1 else ""
if action in ['open', '开启', '开始']:
return await self._open_bigsmall(sub_args, chat_id, user_id)
elif action in ['bet', '下注', '']:
return await self._bet_bigsmall(sub_args, chat_id, user_id)
elif action in ['status', '状态', '查看']:
return await self._status_bigsmall(chat_id)
elif action in ['settle', '结算', '开奖']:
return await self._settle_bigsmall(sub_args, chat_id, user_id)
elif action in ['cancel', '放弃', '关闭']:
return await self._cancel_bigsmall(chat_id, user_id)
elif action in ['help', '帮助']:
return self._get_bigsmall_help()
else:
return f"❌ 未知命令: {action}\n\n{self._get_bigsmall_help()}"
async def _open_bigsmall(self, args: str, chat_id: int, user_id: int) -> str:
"""庄家开启大小游戏
Args:
args: 参数字符串 "<最小下注> <最大下注> <赔率>"
chat_id: 会话ID
user_id: 用户ID
Returns:
回复消息
"""
try:
# 解析参数
parts = args.split()
if len(parts) != 3:
return "❌ 参数格式错误!\n\n正确格式:`.赌场 大小 open <最小下注> <最大下注> <赔率>`\n\n示例:`.赌场 大小 open 10 100 2.0`"
try:
min_bet = int(parts[0])
max_bet = int(parts[1])
multiplier = float(parts[2])
except ValueError:
return "❌ 参数必须是数字!"
# 参数验证
if min_bet <= 0 or max_bet <= 0:
return "❌ 下注金额必须大于0"
if min_bet > max_bet:
return "❌ 最小下注不能大于最大下注!"
if multiplier <= 0:
return "❌ 赔率必须大于0"
if max_bet > 10000:
return "❌ 最大下注不能超过10000分"
# 检查是否已有活跃游戏
existing = self.db.get_active_casino_session(chat_id, '大小')
if existing:
return "⚠️ 当前已有进行中的大小游戏,请先结算后再开启新游戏。"
# 创建游戏会话
session_id = self.db.create_casino_session(
chat_id=chat_id,
game_type='大小',
banker_id=user_id,
min_bet=min_bet,
max_bet=max_bet,
multiplier=multiplier,
house_fee=0.05 # 固定5%抽水
)
banker_display_name = self.db.get_user_display_name(user_id)
text = f"## 🎰 大小游戏已开启\n\n"
text += f"**庄家**{banker_display_name}\n\n"
text += f"**最小下注**{min_bet}\n\n"
text += f"**最大下注**{max_bet}\n\n"
text += f"**赔率**{multiplier}\n\n"
text += f"**抽水率**5%\n\n"
text += "---\n\n"
text += "💡 提示:玩家可以使用 `.赌场 大小 bet <大/小> <金额>` 进行下注"
return text
except Exception as e:
logger.error(f"开启游戏失败: {e}", exc_info=True)
return f"❌ 开启游戏失败: {str(e)}"
async def _bet_bigsmall(self, args: str, chat_id: int, user_id: int) -> str:
"""玩家下注
Args:
args: 参数字符串 "<大/小> <下注金额>"
chat_id: 会话ID
user_id: 用户ID
Returns:
回复消息
"""
try:
# 解析参数
parts = args.split()
if len(parts) != 2:
return "❌ 参数格式错误!\n\n正确格式:`.赌场 大小 bet <大/小> <下注金额>`\n\n示例:`.赌场 大小 bet 大 50`"
bet_type = parts[0]
try:
amount = int(parts[1])
except ValueError:
return "❌ 下注金额必须是数字!"
# 验证下注类型
if bet_type not in ['', '']:
return f"❌ 下注类型错误!只支持'''',您输入的是:{bet_type}"
# 检查是否有活跃的会话
session = self.db.get_active_casino_session(chat_id, '大小')
if not session:
return "❌ 当前没有进行中的游戏,请等待庄家开启游戏。"
# 验证下注金额
if amount < session['min_bet']:
return f"❌ 下注金额太小!最小下注:{session['min_bet']}"
if amount > session['max_bet']:
return f"❌ 下注金额太大!最大下注:{session['max_bet']}"
# 检查用户积分
user_points = self.db.get_user_points(user_id)
if user_points['points'] < amount:
return f"❌ 积分不足!需要 {amount} 分,当前可用 {user_points['points']}"
# 扣除积分
if not self.db.consume_points(user_id, amount, 'casino_bet', f"大小游戏下注{bet_type}"):
return "❌ 扣除积分失败!"
# 记录下注
bet_id = self.db.create_casino_bet(
chat_id=chat_id,
game_type='大小',
user_id=user_id,
bet_type=bet_type,
amount=amount,
multiplier=session['multiplier']
)
# 获取更新后的积分
updated_points = self.db.get_user_points(user_id)
text = f"## 🎲 下注成功\n\n"
text += f"**下注类型**{bet_type}\n\n"
text += f"**下注金额**{amount}\n\n"
text += f"**赔率**{session['multiplier']}\n\n"
text += f"**剩余积分**{updated_points['points']}\n\n"
text += "---\n\n"
text += "💡 等待庄家结算结果..."
return text
except Exception as e:
logger.error(f"下注失败: {e}", exc_info=True)
return f"❌ 下注失败: {str(e)}"
async def _status_bigsmall(self, chat_id: int) -> str:
"""查看当前游戏状态
Args:
chat_id: 会话ID
Returns:
状态消息
"""
session = self.db.get_active_casino_session(chat_id, '大小')
if not session:
return "❌ 当前没有进行中的大小游戏"
# 获取所有待结算下注
bets = self.db.get_pending_bets(chat_id, '大小')
# 统计下注情况
bet_big = sum(b['amount'] for b in bets if b['bet_type'] == '')
bet_small = sum(b['amount'] for b in bets if b['bet_type'] == '')
banker_display_name = self.db.get_user_display_name(session['banker_id'])
text = f"## 🎰 大小游戏状态\n\n"
text += f"**庄家**{banker_display_name}\n\n"
text += f"**最小下注**{session['min_bet']}\n\n"
text += f"**最大下注**{session['max_bet']}\n\n"
text += f"**赔率**{session['multiplier']}\n\n"
text += "---\n\n"
text += f"**当前下注统计**\n"
text += f"- 压大:{bet_big} 分({len([b for b in bets if b['bet_type'] == ''])}注)\n"
text += f"- 压小:{bet_small} 分({len([b for b in bets if b['bet_type'] == ''])}注)\n"
text += f"- 总下注:{len(bets)}\n\n"
text += "---\n\n"
text += "💡 庄家可以使用 `.赌场 大小 settle` 结算"
return text
async def _settle_bigsmall(self, args: str, chat_id: int, user_id: int) -> str:
"""庄家结算游戏(系统随机生成结果)
Args:
args: 无参数
chat_id: 会话ID
user_id: 用户ID
Returns:
结算结果消息
"""
try:
# 不需要参数,系统自动随机生成结果
# 使用系统随机数决定大小50%概率)
result = '' if random.random() > 0.5 else ''
# 结算
settlement = self.db.settle_casino_bets(chat_id, '大小', result, user_id)
# 构建结算报告
text = f"## 🎰 大小游戏结算\n\n"
text += f"**结算结果**:🎲 {result}\n\n"
text += "---\n\n"
text += f"**赢家**{len(settlement['winners'])}\n"
text += f"**输家**{len(settlement['losers'])}\n\n"
# 显示赢家详情
if settlement['winners']:
text += "**赢家明细**\n"
for winner in settlement['winners']:
winner_display_name = self.db.get_user_display_name(winner['user_id'])
text += f"- {winner_display_name}: 下注{winner['amount']}分,赢得{winner['win_amount']}\n"
text += "\n"
# 显示输家详情
if settlement['losers']:
text += "**输家明细**\n"
for loser in settlement['losers']:
loser_display_name = self.db.get_user_display_name(loser['user_id'])
text += f"- {loser_display_name}: 下注{loser['amount']}\n"
text += "\n"
text += "---\n\n"
text += "✅ 游戏已结束,欢迎再次游戏!"
return text
except ValueError as e:
return f"{str(e)}"
except Exception as e:
logger.error(f"结算失败: {e}", exc_info=True)
return f"❌ 结算失败: {str(e)}"
async def _cancel_bigsmall(self, chat_id: int, user_id: int) -> str:
"""庄家放弃本轮游戏
Args:
chat_id: 会话ID
user_id: 用户ID
Returns:
放弃结果消息
"""
try:
# 检查是否有活跃的会话
session = self.db.get_active_casino_session(chat_id, '大小')
if not session:
return "❌ 当前没有进行中的游戏"
# 验证是否为庄家
if session['banker_id'] != user_id:
return "❌ 只有庄家可以放弃游戏"
# 获取所有待结算下注
bets = self.db.get_pending_bets(chat_id, '大小')
# 返还所有下注的积分
return_amount = 0
for bet in bets:
# 返还积分
self.db.add_points(bet['user_id'], bet['amount'], 'casino_cancel',
"庄家放弃游戏,返还下注")
return_amount += bet['amount']
# 关闭会话(不结算,返还积分)
self.db.close_casino_session(chat_id, '大小')
# 标记下注为已取消
cursor = self.db.conn.cursor()
cursor.execute("""
UPDATE casino_bets
SET status = 'cancelled'
WHERE chat_id = ? AND game_type = ? AND status = 'pending'
""", (chat_id, '大小'))
# 构建报告
banker_display_name = self.db.get_user_display_name(user_id)
text = f"## 🎰 游戏已放弃\n\n"
text += f"**庄家**{banker_display_name}\n\n"
text += f"**总返还积分**{return_amount}\n\n"
text += f"**返还人数**{len(bets)}\n\n"
text += "---\n\n"
text += "✅ 所有下注已返还,游戏已关闭"
return text
except Exception as e:
logger.error(f"放弃游戏失败: {e}", exc_info=True)
return f"❌ 放弃游戏失败: {str(e)}"
def _get_bigsmall_help(self) -> str:
"""获取大小游戏帮助信息"""
return """## 🎰 大小游戏帮助
### 庄家命令
- `.赌场 大小 open <最小> <最大> <赔率>` - 开启游戏
- 示例:`.赌场 大小 open 10 100 2.0`
- `.赌场 大小 settle` - 结算游戏(系统随机生成结果)
- `.赌场 大小 cancel` - 放弃游戏(返还所有下注)
### 玩家命令
- `.赌场 大小 bet <大/小> <金额>` - 下注
- 示例:`.赌场 大小 bet 大 50`
- 示例:`.赌场 大小 bet 小 30`
### 通用命令
- `.赌场 大小 status` - 查看当前状态
### 游戏规则
- 玩家下注后积分立即扣除
- 结算后根据结果发放奖励
- 庄家放弃游戏时,所有下注全额返还
- 系统抽水5%
- 赔率由庄家设置
"""
def get_help(self) -> str:
"""获取帮助信息"""
return self._get_bigsmall_help()