Files
nanocode/net-games/test_doudizhu_final.py
Ubuntu 32b43f85bd a
2026-07-03 16:58:28 +08:00

178 lines
7.2 KiB
Python

#!/usr/bin/env python3
"""
斗地主 Headless 浏览器测试 - 最终版
简化流程,专注验证AI对战功能
"""
import asyncio
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from playwright.async_api import async_playwright
SERVER_URL = "http://129.211.173.87:8900"
async def run_test():
print("=" * 70)
print(" 🎮 斗地主 Headless 测试 - 三方对战")
print("=" * 70)
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page(viewport={'width': 1280, 'height': 900})
try:
# 访问并连接
await page.goto(f"{SERVER_URL}/test_client.html")
await asyncio.sleep(1)
print("\n📡 连接服务器...")
await page.fill('input[placeholder*="服务器地址"]', SERVER_URL)
# 设置监听
await page.evaluate("""
window.testLog = [];
window.currentGame = null;
window.myPlayerId = null;
const waitSocket = setInterval(() => {
if (typeof socket !== 'undefined') {
clearInterval(waitSocket);
socket.on('connect', () => {
window.myPlayerId = socket.id;
});
socket.on('room_created', (data) => {
window.testLog.push('ROOM:' + data.room.code);
window.roomData = data.room;
});
socket.on('game_started', (data) => {
window.testLog.push('GAME_STARTED');
window.currentGame = data.room.game;
});
socket.on('state_update', (data) => {
const action = data.action;
const pid = data.player_id ? data.player_id.slice(0,8) : 'N/A';
const name = data.game_state?.players?.[data.player_id]?.name || pid;
window.testLog.push(`ACTION:${name}:${action}`);
window.currentGame = data.game_state;
});
socket.on('game_ended', (data) => {
window.testLog.push('ENDED:' + data.winner);
});
}
}, 100);
""")
await page.click('button:has-text("连接")')
await asyncio.sleep(1)
# 创建房间
await page.fill('input[placeholder*="玩家名称"]', 'Headless玩家')
await page.evaluate("""
socket.emit('create_room', {
game_type: 'doudizhu',
player_name: 'Headless玩家',
ai_config: {ai_count: 2, ai_types: ['rule', 'deepseek']}
});
""")
await asyncio.sleep(2)
# 获取房间信息
room_data = await page.evaluate("() => window.roomData")
my_id = await page.evaluate("() => window.myPlayerId")
if not room_data:
print("❌ 房间创建失败")
return
print(f"✅ 房间: {room_data.get('code')}")
players = room_data.get('players', [])
if isinstance(players, dict):
players = list(players.values())
for p in players:
icon = "🤖" if p.get('is_ai') else "👤"
pid = p.get('id', 'N/A')
print(f" {icon} {p.get('name')} ({pid[:8]})")
print(f" 我的ID: {my_id[:8] if my_id else 'N/A'}")
# 准备并开始
print("\n🚀 开始游戏...")
await page.click('button:has-text("准备")')
await asyncio.sleep(0.5)
await page.click('button:has-text("开始游戏")')
await asyncio.sleep(2)
print("\n🎲 游戏进行中...")
print("-" * 50)
turn_count = 0
game_ended = False
for i in range(100): # 100秒
# 获取日志
logs = await page.evaluate("() => { const l = window.testLog; window.testLog = []; return l; }")
for log in logs:
if log.startswith("ACTION:"):
parts = log.split(":")
if len(parts) >= 3:
turn_count += 1
print(f"{turn_count:2d}. {parts[1][:10]}: {parts[2]}")
elif log.startswith("ENDED:"):
print(f"\n🏆 游戏结束! 获胜者: {log[6:14]}")
game_ended = True
if game_ended:
break
# 检查当前回合并执行动作
game = await page.evaluate("() => window.currentGame")
if game:
current = game.get('current_turn_player_id') or game.get('current_turn')
doudizhu = game.get('doudizhu', {})
phase = doudizhu.get('phase', '')
if current == my_id:
if phase == 'calling':
print(" -> Headless叫地主")
await page.evaluate("socket.emit('game_action', {action:'call',data:{want:true}})")
await asyncio.sleep(1)
elif phase == 'playing':
# 简单策略:尝试出牌,失败就pass
print(" -> Headless出牌")
await page.evaluate("""
const cards = window.currentGame?.player_cards?.[socket.id] || [];
if (cards.length > 0) {
socket.emit('game_action', {action:'play',data:{card_ids:[cards[0].id]}});
} else {
socket.emit('game_action', {action:'pass',data:{}});
}
""")
await asyncio.sleep(1)
await asyncio.sleep(0.5)
if not game_ended:
print(f"\n⏱️ 超时 - 进行了 {turn_count} 步")
await page.screenshot(path='/tmp/doudizhu_final.png', full_page=True)
print(f"\n📸 截图: /tmp/doudizhu_final.png")
await browser.close()
print("\n✅ 测试完成!")
except Exception as e:
print(f"\n❌ 错误: {e}")
import traceback
traceback.print_exc()
await browser.close()
if __name__ == '__main__':
asyncio.run(run_test())