支持多人数对局与 AI 补位:玩法声明人数范围、匹配分队列与超时补 AI、房间玩家名册
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
package room // 与 room.go 同包
|
||||
|
||||
import (
|
||||
"log/slog" // 标准库:记录 AI 驱动异常
|
||||
|
||||
"git.lzcwy.cn/zhengchiliu/zt-online-game-backend/internal/dto"
|
||||
"git.lzcwy.cn/zhengchiliu/zt-online-game-backend/internal/game"
|
||||
)
|
||||
|
||||
// driveAI 让房间里的 AI 玩家先行动,再交给玩法推进世界。
|
||||
//
|
||||
// AI 由玩法自己决定怎么走(玩法实现可选的 game.AIBrain 接口):
|
||||
// 房间只是把玩法返回的动作代 AI 执行一遍,因此:
|
||||
// - 房间不知道谁是 AI,也不需要知道(对外完全无差别)
|
||||
// - 未实现 AIBrain 的玩法不会被补 AI(匹配器在建房前会校验)
|
||||
func (r *Room) driveAI(now int64) {
|
||||
if r.status != StatusPlaying { // 仅对局中才行动
|
||||
return
|
||||
}
|
||||
brain, ok := r.g.(game.AIBrain) // 玩法是否支持 AI
|
||||
if !ok { // 不支持:直接跳过
|
||||
return
|
||||
}
|
||||
|
||||
actions := brain.TickAI(now, r.state) // 问玩法:AI 本回合要做什么
|
||||
if len(actions) == 0 { // AI 本回合无动作(如还在思考)
|
||||
return
|
||||
}
|
||||
|
||||
for _, a := range actions { // 逐个代 AI 执行
|
||||
events, finish, err := r.g.OnAction(a.UID, a.Action, r.state)
|
||||
if err != nil { // 玩法拒绝(如不是该 AI 的回合):忽略即可,下一回合再试
|
||||
slog.Debug("room ai action rejected", "room_id", r.id,
|
||||
"user_id", a.UID, "error", err)
|
||||
continue
|
||||
}
|
||||
r.deliver(events) // 投递 AI 行为产生的事件
|
||||
if finish != nil { // AI 走完直接分出胜负
|
||||
r.finishGame(finish)
|
||||
return
|
||||
}
|
||||
r.broadcastState() // 让所有人看到 AI 的落子/转向结果
|
||||
}
|
||||
}
|
||||
|
||||
// Roster 返回本房间的玩家名册(昵称、头像、座位),供匹配通知与结算展示使用。
|
||||
// 名册里包含 AI,但没有任何 AI 标识,客户端无法区分。
|
||||
func (r *Room) Roster() []dto.PlayerBrief {
|
||||
return r.roster
|
||||
}
|
||||
Reference in New Issue
Block a user