258 lines
9.9 KiB
Go
258 lines
9.9 KiB
Go
package routers
|
||||
|
|
|
|||
|
|
import (
|
|||
|
|
"context"
|
|||
|
|
"sync"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
var _ = sync.Mutex{}
|
|||
|
|
var _ = context.Background
|
|||
|
|
|
|||
|
|
// 棋子类型(同侧内的功能种类,与 chessId 的 %16 分段一一对应)。
|
|||
|
|
type ChessKind int32
|
|||
|
|
|
|||
|
|
const (
|
|||
|
|
ChessKind_King ChessKind = 0
|
|||
|
|
ChessKind_Advisor ChessKind = 1
|
|||
|
|
ChessKind_Elephant ChessKind = 2
|
|||
|
|
ChessKind_Horse ChessKind = 3
|
|||
|
|
ChessKind_Rook ChessKind = 4
|
|||
|
|
ChessKind_Cannon ChessKind = 5
|
|||
|
|
ChessKind_Pawn ChessKind = 6
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// 一步棋(坐标即线上坐标,可直接写进 ChineseChessMove)。
|
|||
|
|
type ChessMove struct {
|
|||
|
|
FromId int32 `json:"fromId"`
|
|||
|
|
FromX int32 `json:"fromX"`
|
|||
|
|
FromY int32 `json:"fromY"`
|
|||
|
|
ToX int32 `json:"toX"`
|
|||
|
|
ToY int32 `json:"toY"`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//
|
|||
|
|
// 9×10 的象棋盘 + 完整走法生成 + 将军/绝杀判定 + 一个 2 层极小极大 AI。
|
|||
|
|
// 非线程安全;一个 zone 一份,由 handler 持有在 session 里。
|
|||
|
|
//
|
|||
|
|
type ChineseChessBoard struct {
|
|||
|
|
At []int32 `json:"_at"`
|
|||
|
|
Pos []int32 `json:"_pos"`
|
|||
|
|
Rng any `json:"_rng"`
|
|||
|
|
// 轮到红方?(服务端镜像状态,仅用于日志/AI 选择)
|
|||
|
|
RedToMove bool `json:"redToMove"`
|
|||
|
|
// 本局已走过的着数(写进 ChineseChessMove.MoveIndex)。
|
|||
|
|
MoveCount int32 `json:"moveCount"`
|
|||
|
|
Dirs []any `json:"dirs"`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const (
|
|||
|
|
ChineseChessBoard_MinX int32 = 3
|
|||
|
|
ChineseChessBoard_MaxX int32 = 11
|
|||
|
|
ChineseChessBoard_MinY int32 = 3
|
|||
|
|
ChineseChessBoard_MaxY int32 = 12
|
|||
|
|
ChineseChessBoard_Empty int32 = -1
|
|||
|
|
ChineseChessBoard_Stride int32 = 16
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// ─────────────────────────────────────────────────────────────────────────────────
|
|||
|
|
// 基础
|
|||
|
|
// ─────────────────────────────────────────────────────────────────────────────────
|
|||
|
|
func ChineseChessBoard_IsRedId(ctx context.Context, id int32) bool {
|
|||
|
|
// Router implementation for ChineseChessBoard_IsRedId
|
|||
|
|
return true
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func ChineseChessBoard_InBoard(ctx context.Context, x int32, y int32) bool {
|
|||
|
|
// Router implementation for ChineseChessBoard_InBoard
|
|||
|
|
return true
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func ChineseChessBoard_KindOf(ctx context.Context, id int32) any {
|
|||
|
|
// Router implementation for ChineseChessBoard_KindOf
|
|||
|
|
var zero any; return zero
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 红方九宫 x∈[6,8] y∈[3,5];黑方 x∈[6,8] y∈[10,12]。
|
|||
|
|
func ChineseChessBoard_InPalace(ctx context.Context, red bool, x int32, y int32) bool {
|
|||
|
|
// Router implementation for ChineseChessBoard_InPalace
|
|||
|
|
return true
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 是否还在本方半场(相/象不可过河)。红 y∈[3,7],黑 y∈[8,12]。
|
|||
|
|
func ChineseChessBoard_InOwnHalf(ctx context.Context, red bool, y int32) bool {
|
|||
|
|
// Router implementation for ChineseChessBoard_InOwnHalf
|
|||
|
|
return true
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 兵/卒是否已过河。红过河 = y≥8;黑过河 = y≤7。
|
|||
|
|
func ChineseChessBoard_PawnCrossedRiver(ctx context.Context, red bool, y int32) bool {
|
|||
|
|
// Router implementation for ChineseChessBoard_PawnCrossedRiver
|
|||
|
|
return true
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func ChineseChessBoard_At(ctx context.Context, x int32, y int32) int32 {
|
|||
|
|
// Router implementation for ChineseChessBoard_At
|
|||
|
|
return 0
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func ChineseChessBoard_Put(ctx context.Context, x int32, y int32, id int32) any {
|
|||
|
|
// Router implementation for ChineseChessBoard_Put
|
|||
|
|
var zero any; return zero
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func ChineseChessBoard_ClearAt(ctx context.Context, x int32, y int32) any {
|
|||
|
|
// Router implementation for ChineseChessBoard_ClearAt
|
|||
|
|
var zero any; return zero
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 清空盘面(残局 / 自定义局面 / 回放重置用)。
|
|||
|
|
func ChineseChessBoard_Clear(ctx context.Context, ) any {
|
|||
|
|
// Router implementation for ChineseChessBoard_Clear
|
|||
|
|
var zero any; return zero
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 直接把一枚子摆在某个点(残局 / 回放 / 摆位校验用)。
|
|||
|
|
func ChineseChessBoard_Place(ctx context.Context, x int32, y int32, id int32) any {
|
|||
|
|
// Router implementation for ChineseChessBoard_Place
|
|||
|
|
var zero any; return zero
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func ChineseChessBoard_Init(ctx context.Context, ) any {
|
|||
|
|
// Router implementation for ChineseChessBoard_Init
|
|||
|
|
var zero any; return zero
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func ChineseChessBoard_TryLocate(ctx context.Context, id int32, x int32, y int32) bool {
|
|||
|
|
// Router implementation for ChineseChessBoard_TryLocate
|
|||
|
|
return true
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func ChineseChessBoard_IsAlive(ctx context.Context, id int32) bool {
|
|||
|
|
// Router implementation for ChineseChessBoard_IsAlive
|
|||
|
|
return true
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func ChineseChessBoard_KingId(ctx context.Context, red bool) int32 {
|
|||
|
|
// Router implementation for ChineseChessBoard_KingId
|
|||
|
|
return 0
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 把 32 子的位置吐成一行(日志/断言用)。
|
|||
|
|
func ChineseChessBoard_Dump(ctx context.Context, ) string {
|
|||
|
|
// Router implementation for ChineseChessBoard_Dump
|
|||
|
|
return ""
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 紧凑盘面串(棋盘 9×10,空格用 '.'),日志里一眼能看出错位。
|
|||
|
|
func ChineseChessBoard_Render(ctx context.Context, ) string {
|
|||
|
|
// Router implementation for ChineseChessBoard_Render
|
|||
|
|
return ""
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func ChineseChessBoard_Glyph(ctx context.Context, id int32) rune {
|
|||
|
|
// Router implementation for ChineseChessBoard_Glyph
|
|||
|
|
return 0
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ─────────────────────────────────────────────────────────────────────────────────
|
|||
|
|
// 走法生成
|
|||
|
|
// ─────────────────────────────────────────────────────────────────────────────────
|
|||
|
|
//
|
|||
|
|
// 伪合法走法(几何 + 不吃己子 + 蹩腿/塞眼/炮架),**不**过滤「自将」。
|
|||
|
|
// ★ 王永远不会被「吃」——所以这里不把对方王的格子当落点;王的「输」由
|
|||
|
|
// 「无合法着法」(绝杀/困毙)表达。飞将的将军判定另见 IsInCheck。
|
|||
|
|
//
|
|||
|
|
func ChineseChessBoard_PseudoTargets(ctx context.Context, id int32) []any {
|
|||
|
|
// Router implementation for ChineseChessBoard_PseudoTargets
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//
|
|||
|
|
// 攻击集:与可落点唯一的差别是**包含对方王的格子**(用于将军判定)。
|
|||
|
|
// 把这两者分开是必须的 —— 混在一起会让「绝杀」永远判不出来(对方王总能"吃"回来)。
|
|||
|
|
//
|
|||
|
|
func ChineseChessBoard_Targets(ctx context.Context, id int32, forAttack bool) []any {
|
|||
|
|
// Router implementation for ChineseChessBoard_Targets
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//
|
|||
|
|
// 某一方是否被将军。
|
|||
|
|
// ① 常规:敌方任何一枚子的**攻击集**覆盖我方王的格子;
|
|||
|
|
// ② 飞将:双方王同列且中间无子 —— 这一条必须显式写,
|
|||
|
|
// 因为「王」的攻击集里不含对方王(王不吃王)。
|
|||
|
|
//
|
|||
|
|
func ChineseChessBoard_IsInCheck(ctx context.Context, red bool) bool {
|
|||
|
|
// Router implementation for ChineseChessBoard_IsInCheck
|
|||
|
|
return true
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 走一步(不改回合、不校验合法性),返回被吃子的 id(无 = -1)。
|
|||
|
|
func ChineseChessBoard_ApplyMove(ctx context.Context, id int32, tx int32, ty int32) int32 {
|
|||
|
|
// Router implementation for ChineseChessBoard_ApplyMove
|
|||
|
|
return 0
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 撤销 ApplyMove。参数就是刚才那一步的原样。
|
|||
|
|
func ChineseChessBoard_UndoMove(ctx context.Context, id int32, fx int32, fy int32, tx int32, ty int32, captured int32) any {
|
|||
|
|
// Router implementation for ChineseChessBoard_UndoMove
|
|||
|
|
var zero any; return zero
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 该子走这一步之后,自己是否被将军(= 送将 / 自将)。
|
|||
|
|
func ChineseChessBoard_LeavesOwnKingInCheck(ctx context.Context, id int32, tx int32, ty int32) bool {
|
|||
|
|
// Router implementation for ChineseChessBoard_LeavesOwnKingInCheck
|
|||
|
|
return true
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 某一方所有**合法**着法(已过滤自将)。
|
|||
|
|
func ChineseChessBoard_LegalMoves(ctx context.Context, red bool) []any {
|
|||
|
|
// Router implementation for ChineseChessBoard_LegalMoves
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func ChineseChessBoard_HasAnyLegalMove(ctx context.Context, red bool) bool {
|
|||
|
|
// Router implementation for ChineseChessBoard_HasAnyLegalMove
|
|||
|
|
return true
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ─────────────────────────────────────────────────────────────────────────────────
|
|||
|
|
// 评估 + AI
|
|||
|
|
// ─────────────────────────────────────────────────────────────────────────────────
|
|||
|
|
// 子力价值:与客户端 ChineseChessEnum.lua 的打分表同量级
|
|||
|
|
// (帅10000 / 仕100 / 相100 / 马400 / 车900 / 炮450 / 兵100)
|
|||
|
|
func ChineseChessBoard_ValueOf(ctx context.Context, id int32) int32 {
|
|||
|
|
// Router implementation for ChineseChessBoard_ValueOf
|
|||
|
|
return 0
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 从黑方视角的静态子力差(正 = 黑优)。
|
|||
|
|
func ChineseChessBoard_EvalBlack(ctx context.Context, ) int32 {
|
|||
|
|
// Router implementation for ChineseChessBoard_EvalBlack
|
|||
|
|
return 0
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 从某一方视角的静态分(正 = 该方占优)。
|
|||
|
|
func ChineseChessBoard_EvalFor(ctx context.Context, red bool) int32 {
|
|||
|
|
// Router implementation for ChineseChessBoard_EvalFor
|
|||
|
|
return 0
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 黑方挑一步棋(= PickMove 的便捷壳,离线自测用)。
|
|||
|
|
func ChineseChessBoard_PickBlackMove(ctx context.Context, difficulty byte) any {
|
|||
|
|
// Router implementation for ChineseChessBoard_PickBlackMove
|
|||
|
|
var zero any; return zero
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//
|
|||
|
|
// 给某一方挑一步棋。difficulty = 0..4
|
|||
|
|
// (UX.Game.ChineseChessAIDifficulty: Beginner 0 / Easy 1 / Medium 2 / Hard 3 / Expert 4)。
|
|||
|
|
// Beginner/Easy 会有一小部分随机着,避免一开局就把玩家掐死。
|
|||
|
|
// ★ R183:原来只有 PickBlackMove。加了「玩家可以选择执黑」这条路之后,
|
|||
|
|
// 服务端还得替 AI 走**红方**(红先手,玩家执黑时开局是 AI 的),所以改成按颜色取。
|
|||
|
|
//
|
|||
|
|
func ChineseChessBoard_PickMove(ctx context.Context, red bool, difficulty byte) any {
|
|||
|
|
// Router implementation for ChineseChessBoard_PickMove
|
|||
|
|
var zero any; return zero
|
|||
|
|
}
|
|||
|
|
|