game_sync/gamerule/chess/chessjpz.go

1025 lines
22 KiB
Go
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.

package chess
import (
"fmt"
"strconv"
"strings"
)
var pieceJPZ = []Piece{
BR, BN, BS, BM, BK, BS, BN, BR,
"", "", "", "", "", "", "", "",
BP, BP, BP, BP, BP, BP, BP, BP,
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
WP, WP, WP, WP, WP, WP, WP, WP,
"", "", "", "", "", "", "", "",
WR, WN, WS, WK, WM, WS, WN, WR,
}
const (
MoveWK = 0
MoveWM = 1
MoveBM = 2
MoveBK = 3
)
// RecordJPZ 走棋记录
type RecordJPZ struct {
FromTo [2]*PositionPiece
CambodianMove [4]bool
}
// ChessJPZ 棋盘
type ChessJPZ struct {
Variant int
Width int // 宽度
Height int // 高度
Count int // 格子数量
Act bool // 是否该白字走,false白棋
Round int // 回合数
Buf []Piece // 棋子
Castling [4]bool // 王车易位可行性 [KQkq]
EnPassant int // 过路兵位置
CambodianMove [4]bool // 柬埔寨移动可行性(DEdeD白王E白仕d黑仕e黑王)
Records []*RecordJPZ // 走棋记录
Check [2]bool // 将军
Checkmate [2]bool // 将死
}
func (c *ChessJPZ) GetChess() []string {
ret := make([]string, len(c.Buf))
for k, v := range c.Buf {
ret[k] = string(v)
}
return ret
}
func (c *ChessJPZ) GetAct() string {
if c.Act {
return "b"
} else {
return "w"
}
}
func (c *ChessJPZ) GetCastling() []bool {
ret := make([]bool, len(c.Castling))
for k, v := range c.Castling {
ret[k] = v
}
return ret
}
func (c *ChessJPZ) GetEnPassant() int {
return c.EnPassant
}
func (c *ChessJPZ) GetCambodianMove() []bool {
ret := make([]bool, len(c.CambodianMove))
for k, v := range c.CambodianMove {
ret[k] = v
}
return ret
}
func (c *ChessJPZ) GetRound() int {
return c.Round
}
func (c *ChessJPZ) GetPiece(index int) Piece {
return c.Buf[index]
}
func (c *ChessJPZ) GetCheck() []bool {
ret := make([]bool, len(c.Check))
for k, v := range c.Check {
ret[k] = v
}
return ret
}
func (c *ChessJPZ) GetCheckmate() []bool {
ret := make([]bool, len(c.Checkmate))
for k, v := range c.Checkmate {
ret[k] = v
}
return ret
}
func (c *ChessJPZ) NextAct() {
// 判断将军
c.Check[0] = c.IsCheck(true)
c.Check[1] = c.IsCheck(false)
// 判断将死
c.Checkmate[0] = false
c.Checkmate[1] = false
if !c.Act && c.IsCheckmate(true) {
c.Checkmate[0] = true
}
if c.Act && c.IsCheckmate(false) {
c.Checkmate[1] = true
}
// 下一个玩家操作,记录回合数
if !c.Act {
c.Round++
}
c.Act = !c.Act
}
func (c *ChessJPZ) PrintChess() {
f := func(n int) string {
str := fmt.Sprintf(" %d", n+1)
if c.IsWhiteMove() && n == 0 || c.IsBlackMove() && n == -1 {
str = strings.Replace(str, " ", "*", 1)
}
return str
}
splitStr := " "
for y := c.Height - 1; y >= 0; y-- {
fmt.Print(f(y))
for x := 0; x < c.Width; x++ {
fmt.Print(splitStr)
idx, _ := XYToIndex(c.Width, c.Height, x, y)
value := c.Buf[idx]
if value == "" {
fmt.Print("--")
} else {
fmt.Print(value)
}
splitStr = " "
}
fmt.Println()
splitStr = " "
}
fmt.Print(" ")
for x := 0; x < c.Width; x++ {
fmt.Print(splitStr)
fmt.Print(fmt.Sprintf(" %d", x+1))
splitStr = " "
}
fmt.Println()
}
func (c *ChessJPZ) GenFenChessBoard() string {
var build strings.Builder
splitStr := ""
emptyCnt := 0
writeEmptyCount := func() {
if emptyCnt > 0 {
countStr := fmt.Sprintf("%d", emptyCnt)
build.WriteString(countStr)
emptyCnt = 0
}
}
for y := c.Height - 1; y >= 0; y-- {
build.WriteString(splitStr)
for x := 0; x < c.Width; x++ {
idx, _ := XYToIndex(c.Width, c.Height, x, y)
value := c.Buf[idx]
if value == "" {
//build.WriteString("")
emptyCnt++
} else {
writeEmptyCount()
t := value[1:]
c := value[:1]
if c == "W" {
build.WriteString(string(t))
} else if c == "B" {
build.WriteString(strings.ToLower(string(t)))
}
}
}
writeEmptyCount()
splitStr = "/"
}
return build.String()
}
func (c *ChessJPZ) GenFenCastling() string {
return "-" // 客户端需要支持王车易位走位后才可使用
//var build strings.Builder
//if this.castling[0] {
// build.WriteString("K")
//}
//if this.castling[1] {
// build.WriteString("Q")
//}
//if this.castling[2] {
// build.WriteString("k")
//}
//if this.castling[3] {
// build.WriteString("q")
//}
//str := build.String()
//if len(str) == 0 {
// return "-"
//}
//return build.String()
}
func (c *ChessJPZ) GenFenCambodianMove() string {
var build strings.Builder
if c.CambodianMove[MoveWK] {
build.WriteString("D")
}
if c.CambodianMove[MoveWM] {
build.WriteString("E")
}
if c.CambodianMove[MoveBM] {
build.WriteString("d")
}
if c.CambodianMove[MoveBK] {
build.WriteString("e")
}
str := build.String()
if len(str) == 0 {
return "-"
}
return build.String()
}
func (c *ChessJPZ) GenFenEnPassant() string {
return "-"
}
func (c *ChessJPZ) GenHalfRoundCount() string {
return "0"
}
func (c *ChessJPZ) GenRoundCount() string {
return fmt.Sprintf("%d", c.Round)
}
func (c *ChessJPZ) GenFen() string {
var build strings.Builder
build.WriteString("fen ")
build.WriteString(c.GenFenChessBoard())
build.WriteString(" ")
build.WriteString(c.GetAct())
build.WriteString(" ")
build.WriteString(c.GenFenCambodianMove())
build.WriteString(" ")
build.WriteString(c.GenFenEnPassant())
build.WriteString(" ")
build.WriteString(c.GenHalfRoundCount())
build.WriteString(" ")
build.WriteString(c.GenRoundCount())
return build.String()
}
func (c *ChessJPZ) UciTwoPosToIdxList(str string) []int64 {
result := []int64{-1, -1}
result[0] = c.UciOnePosToIdx(str[0:2])
result[1] = c.UciOnePosToIdx(str[2:4]) // 这里出现过g5f6m这样的返回暂时不清楚这个m表示的意义是兵进行吃子造成的
return result
}
func (c *ChessJPZ) UciOnePosToIdx(str string) int64 {
x := int(strings.ToLower(str[:1])[0] - 'a')
y, _ := strconv.Atoi(str[1:])
y--
idx := y*c.Width + x
//fmt.Println("UciOnePosToIdx", str, x, y, idx)
return int64(idx)
}
func (c *ChessJPZ) GetChessNum(piece Piece) int {
n := 0
for _, v := range c.Buf {
if piece == v {
n++
}
}
return n
}
func (c *ChessJPZ) GetWhiteNum() int {
n := 0
for _, v := range c.Buf {
if IsWhite(v) {
n++
}
}
return n
}
func (c *ChessJPZ) GetBlackNum() int {
n := 0
for _, v := range c.Buf {
if IsBlack(v) {
n++
}
}
return n
}
func (c *ChessJPZ) Has(piece Piece) bool {
for _, v := range c.Buf {
if v == piece {
return true
}
}
return false
}
func (c *ChessJPZ) GetVariant() int {
return c.Variant
}
func (c *ChessJPZ) SetChess(strings []string) {
for k, v := range strings {
c.Buf[k] = Piece(v)
}
}
func (c *ChessJPZ) Set(bufStr []string, bufPiece []Piece, act string, castling []bool, cambodianMove []bool, enPassant int, round int) {
//var buf2 []Piece
//if len(bufStr) > 0 {
// buf2 = make([]Piece, len(bufStr))
// for x := 0; x < c.Width; x++ {
// for y := 0; y < c.Height; y++ {
// buf2[(c.Height-1-y)*c.Width+x] = Piece(bufStr[y*c.Width+x])
// }
// }
//} else {
// buf2 = make([]Piece, len(bufPiece))
// for x := 0; x < c.Width; x++ {
// for y := 0; y < c.Height; y++ {
// buf2[(c.Height-1-y)*c.Width+x] = bufPiece[y*c.Width+x]
// }
// }
//}
if len(bufStr) > 0 {
for k, v := range bufStr {
c.Buf[k] = Piece(v)
}
}
if len(bufPiece) > 0 {
for k, v := range bufPiece {
c.Buf[k] = v
}
}
if act == "w" {
c.Act = false
} else if act == "b" {
c.Act = true
}
if len(castling) == 4 {
for k, v := range castling {
c.Castling[k] = v
}
}
if len(cambodianMove) == 4 {
for k, v := range cambodianMove {
c.CambodianMove[k] = v
}
}
c.EnPassant = enPassant
c.Round = round
}
func (c *ChessJPZ) Init() {
c.Variant = ChessVarCambodian
c.Width = 8
c.Height = 8
c.Count = c.Width * c.Height
c.Act = false
c.Round = 1
if c.Buf == nil || len(c.Buf) != c.Count {
c.Buf = make([]Piece, c.Count)
}
for x := 0; x < c.Width; x++ {
for y := 0; y < c.Height; y++ {
c.Buf[(c.Height-1-y)*c.Width+x] = pieceJPZ[y*c.Width+x]
}
}
c.Castling = [4]bool{true, true, true, true}
c.EnPassant = -1
c.CambodianMove = [4]bool{true, true, true, true}
c.Records = c.Records[:0]
c.Check = [2]bool{false, false}
c.Checkmate = [2]bool{false, false}
}
// GetWidth 获取棋盘的宽度
func (c *ChessJPZ) GetWidth() int {
return c.Width
}
// GetHeight 获取棋盘的高度
func (c *ChessJPZ) GetHeight() int {
return c.Height
}
// MoveR 获取某个位置的车能走的下一步位置
func (c *ChessJPZ) MoveR(x, y int) []*PositionPiece {
// 坐标转换成索引
index, err := XYToIndex(c.Width, c.Height, x, y)
if err != nil {
return nil
}
// 判断这个位置是不是车
o := c.Buf[index]
if !IsR(o) {
return nil
}
var validMoves []*PositionPiece
// 遍历四个方向
for _, dir := range StraightDirections {
dx, dy := dir.X, dir.Y
newX, newY := x+dx, y+dy
// 检查新位置是否在棋盘范围内
for newX >= 0 && newX < c.Width && newY >= 0 && newY < c.Height {
// 获取新位置的索引
index, err := XYToIndex(c.Width, c.Height, newX, newY)
if err != nil {
break
}
// 获取新位置的棋子
piece := c.Buf[index]
if IsEmpty(piece) {
// 记录位置
validMoves = append(validMoves, &PositionPiece{Index: index})
} else {
if IsWhite(piece) != IsWhite(o) {
validMoves = append(validMoves, &PositionPiece{Index: index, P: piece})
}
break
}
// 新位置是空的,继续向前走
newX += dx
newY += dy
}
}
return validMoves
}
// MoveN 获取某个位置的马能走的下一步位置
func (c *ChessJPZ) MoveN(x, y int) []*PositionPiece {
// 坐标转换成索引
index, err := XYToIndex(c.Width, c.Height, x, y)
if err != nil {
return nil
}
// 判断这个位置是不是马
o := c.Buf[index]
if !IsN(o) {
return nil
}
var validMoves []*PositionPiece
for _, dir := range KnightDirections {
dx, dy := dir.X, dir.Y
newX, newY := x+dx, y+dy
// 检查新位置是否在棋盘范围内
if newX >= 0 && newX < c.Width && newY >= 0 && newY < c.Height {
// 获取新位置的索引
index, err := XYToIndex(c.Width, c.Height, newX, newY)
if err == nil {
// 获取新位置的棋子
piece := c.Buf[index]
if IsEmpty(piece) || (IsWhite(piece) != IsWhite(o)) {
validMoves = append(validMoves, &PositionPiece{Index: index, P: piece})
}
}
}
}
return validMoves
}
// MoveS 获取某个位置的象能走的下一步位置
func (c *ChessJPZ) MoveS(x, y int) []*PositionPiece {
// 坐标转换成索引
index, err := XYToIndex(c.Width, c.Height, x, y)
if err != nil {
return nil
}
// 判断这个位置是不是象
o := c.Buf[index]
if !IsS(o) {
return nil
}
var validMoves []*PositionPiece
directions := QueenDirections
if IsWhite(o) {
directions = append(directions, Position{Y: 1})
} else {
directions = append(directions, Position{Y: -1})
}
// 遍历象的移动方向
for _, dir := range directions {
dx, dy := dir.X, dir.Y
newX, newY := x+dx, y+dy
// 检查新位置是否在棋盘范围内
if newX >= 0 && newX < c.Width && newY >= 0 && newY < c.Height {
// 获取新位置的索引
index, err := XYToIndex(c.Width, c.Height, newX, newY)
if err == nil {
// 获取新位置的棋子
piece := c.Buf[index]
if IsEmpty(piece) || (IsWhite(piece) != IsWhite(o)) {
validMoves = append(validMoves, &PositionPiece{Index: index, P: piece})
}
}
}
}
return validMoves
}
// MoveM 获取某个位置的士能走的下一步位置
func (c *ChessJPZ) MoveM(x, y int) []*PositionPiece {
// 坐标转换成索引
index, err := XYToIndex(c.Width, c.Height, x, y)
if err != nil {
return nil
}
// 判断这个位置是不是士
o := c.Buf[index]
if !IsM(o) {
return nil
}
var validMoves []*PositionPiece
for _, dir := range QueenDirections {
dx, dy := dir.X, dir.Y
newX, newY := x+dx, y+dy
// 检查新位置是否在棋盘范围内
if newX >= 0 && newX < c.Width && newY >= 0 && newY < c.Height {
// 获取新位置的索引
index, err := XYToIndex(c.Width, c.Height, newX, newY)
if err == nil {
// 获取新位置的棋子
piece := c.Buf[index]
if IsEmpty(piece) || (IsWhite(piece) != IsWhite(o)) {
validMoves = append(validMoves, &PositionPiece{Index: index, P: piece})
}
}
}
}
if IsWhite(o) && c.CambodianMove[MoveWM] && index == 4 {
index, err = XYToIndex(c.Width, c.Height, x, y+2)
if err == nil && IsEmpty(c.Buf[index]) {
validMoves = append(validMoves, &PositionPiece{Index: index})
}
}
if IsBlack(o) && c.CambodianMove[MoveBM] && index == 59 {
index, err = XYToIndex(c.Width, c.Height, x, y-2)
if err == nil && IsEmpty(c.Buf[index]) {
validMoves = append(validMoves, &PositionPiece{Index: index})
}
}
return validMoves
}
// MoveK 获取某个位置的王能走的下一步位置
func (c *ChessJPZ) MoveK(x, y int) []*PositionPiece {
// 坐标转换成索引
i, err := XYToIndex(c.Width, c.Height, x, y)
if err != nil {
return nil
}
// 判断这个位置是不是王
o := c.Buf[i]
if !IsK(o) {
return nil
}
var validMoves []*PositionPiece
for _, dir := range KingDirections {
dx, dy := dir.X, dir.Y
newX, newY := x+dx, y+dy
// 检查新位置是否在棋盘范围内
if newX >= 0 && newX < c.Width && newY >= 0 && newY < c.Height {
// 获取新位置的索引
index, err := XYToIndex(c.Width, c.Height, newX, newY)
if err == nil {
// 获取新位置的棋子
piece := c.Buf[index]
if IsEmpty(piece) || (IsWhite(piece) != IsWhite(o)) {
validMoves = append(validMoves, &PositionPiece{Index: index, P: piece})
}
}
}
}
// 没有移动过,不能被将军,不能有棋子
if IsWhite(o) && c.CambodianMove[MoveWK] {
if !c.IsCheck(false) {
//index, err := XYToIndex(c.Width, c.Height, x-1, y+2)
//if err == nil && IsEmpty(c.Buf[index]) {
// validMoves = append(validMoves, &PositionPiece{Index: index})
//}
//index, err = XYToIndex(c.Width, c.Height, x+1, y+2)
//if err == nil && IsEmpty(c.Buf[index]) {
// validMoves = append(validMoves, &PositionPiece{Index: index})
//}
index, err := XYToIndex(c.Width, c.Height, x-2, y+1)
if err == nil && IsEmpty(c.Buf[index]) {
validMoves = append(validMoves, &PositionPiece{Index: index})
}
index, err = XYToIndex(c.Width, c.Height, x+2, y+1)
if err == nil && IsEmpty(c.Buf[index]) {
validMoves = append(validMoves, &PositionPiece{Index: index})
}
}
}
// 没有移动过,不能被将军,不能有棋子
if IsBlack(o) && c.CambodianMove[MoveBK] {
// 不能被将军,不能有棋子
if !c.IsCheck(true) {
//index, err := XYToIndex(c.Width, c.Height, x-1, y-2)
//if err == nil && IsEmpty(c.Buf[index]) {
// validMoves = append(validMoves, &PositionPiece{Index: index})
//}
//index, err = XYToIndex(c.Width, c.Height, x+1, y-2)
//if err == nil && IsEmpty(c.Buf[index]) {
// validMoves = append(validMoves, &PositionPiece{Index: index})
//}
index, err := XYToIndex(c.Width, c.Height, x-2, y-1)
if err == nil && IsEmpty(c.Buf[index]) {
validMoves = append(validMoves, &PositionPiece{Index: index})
}
index, err = XYToIndex(c.Width, c.Height, x+2, y-1)
if err == nil && IsEmpty(c.Buf[index]) {
validMoves = append(validMoves, &PositionPiece{Index: index})
}
}
}
// 移动之后不能被将军
var moves []*PositionPiece
for _, v := range validMoves {
c.Move(i, v.Index)
if IsWhite(o) {
if !c.IsCheck(false) {
moves = append(moves, v)
}
} else {
if !c.IsCheck(true) {
moves = append(moves, v)
}
}
c.MoveBack()
}
return moves
}
// MoveP 获取某个位置的兵能走的下一步位置
func (c *ChessJPZ) MoveP(x, y int) []*PositionPiece {
// 坐标转换成索引
index, err := XYToIndex(c.Width, c.Height, x, y)
if err != nil {
return nil
}
// 判断这个位置是不是兵
o := c.Buf[index]
if !IsP(o) {
return nil
}
var validMoves []*PositionPiece
newY := y
isWhite := IsWhite(o)
if isWhite {
newY++
} else {
newY--
}
// 前进一格
index, err = XYToIndex(c.Width, c.Height, x, newY)
if err == nil && IsEmpty(c.Buf[index]) {
validMoves = append(validMoves, &PositionPiece{Index: index})
}
// 斜吃
index, err = XYToIndex(c.Width, c.Height, x-1, newY)
if err == nil && !IsEmpty(c.Buf[index]) && IsWhite(c.Buf[index]) != isWhite {
validMoves = append(validMoves, &PositionPiece{Index: index, P: c.Buf[index]})
}
index, err = XYToIndex(c.Width, c.Height, x+1, newY)
if err == nil && !IsEmpty(c.Buf[index]) && IsWhite(c.Buf[index]) != isWhite {
validMoves = append(validMoves, &PositionPiece{Index: index, P: c.Buf[index]})
}
return validMoves
}
func (c *ChessJPZ) movePositions(index int, flag bool) []*PositionPiece {
x, y, err := IndexToXY(c.Width, c.Height, index)
if err != nil {
return nil
}
o := c.Buf[index]
if IsEmpty(o) {
return nil
}
var moves []*PositionPiece
switch o {
case WR, BR:
moves = c.MoveR(x, y)
case WN, BN:
moves = c.MoveN(x, y)
case WS, BS:
moves = c.MoveS(x, y)
case WM, BM:
moves = c.MoveM(x, y)
case WK, BK:
moves = c.MoveK(x, y)
case WP, BP:
moves = c.MoveP(x, y)
}
// 被将军必须应将,走子后不能被将军
if !flag {
return moves
}
var moves2 []*PositionPiece
for _, v := range moves {
c.Move(index, v.Index)
if IsWhite(o) && c.IsCheck(false) || IsBlack(o) && c.IsCheck(true) {
c.MoveBack()
continue
}
c.MoveBack()
moves2 = append(moves2, v)
}
return moves2
}
// GetMovePositions 获取指定索引位置的棋子能走的位置
func (c *ChessJPZ) GetMovePositions(index int) []*PositionPiece {
return c.movePositions(index, true)
}
func (c *ChessJPZ) IsWhiteMove() bool {
return !c.Act
}
func (c *ChessJPZ) IsBlackMove() bool {
return c.Act
}
// GetIndexes 获取指定棋子的位置
func (c *ChessJPZ) GetIndexes(p Piece) []int {
var positions []int
for k, v := range c.Buf {
if v == p {
positions = append(positions, k)
}
}
return positions
}
// IsCheck 判断将军
func (c *ChessJPZ) IsCheck(isWhite bool) bool {
for k, v := range c.Buf {
if IsEmpty(v) || IsWhite(v) != isWhite {
continue
}
if !IsK(v) {
for _, vv := range c.movePositions(k, false) {
if IsK(vv.P) {
return true
}
}
} else {
// 白王是否吃黑王
x, y, _ := IndexToXY(c.Width, c.Height, k)
for _, dir := range KingDirections {
dx, dy := dir.X, dir.Y
newX, newY := x+dx, y+dy
// 检查新位置是否在棋盘范围内
if newX >= 0 && newX < c.Width && newY >= 0 && newY < c.Height {
// 获取新位置的索引
index, err := XYToIndex(c.Width, c.Height, newX, newY)
if err == nil {
if IsK(c.Buf[index]) {
return true
}
}
}
}
}
}
return false
}
// IsCheckmate 判断将死
func (c *ChessJPZ) IsCheckmate(isWhite bool) bool {
if !c.IsCheck(isWhite) {
return false
}
// 走任何一步,都将军
for k, v := range c.Buf {
if !IsEmpty(v) && IsWhite(v) != isWhite {
for _, vv := range c.movePositions(k, false) {
c.Move(k, vv.Index)
if !c.IsCheck(isWhite) {
c.MoveBack()
return false
}
c.MoveBack()
}
}
}
return true
}
// CanMove 判断是否可以移动
func (c *ChessJPZ) CanMove(fromIndex, toIndex int) bool {
if fromIndex < 0 || fromIndex >= len(c.Buf) || toIndex < 0 || toIndex >= len(c.Buf) {
return false
}
if fromIndex == toIndex {
return false
}
from := c.Buf[fromIndex]
if IsEmpty(from) {
return false
}
// 检查操作权
if c.Act == IsWhite(from) {
return false
}
list := c.GetMovePositions(fromIndex)
for _, v := range list {
if v.Index == toIndex {
return true
}
}
return false
}
// Move 移动棋子
func (c *ChessJPZ) Move(fromIndex, toIndex int) *PositionPiece {
if fromIndex < 0 || fromIndex >= len(c.Buf) || toIndex < 0 || toIndex >= len(c.Buf) {
return nil
}
if fromIndex == toIndex {
return nil
}
from := c.Buf[fromIndex]
if IsEmpty(from) {
return nil
}
fromPiece := &PositionPiece{
Index: fromIndex,
P: c.Buf[fromIndex],
}
to := &PositionPiece{
Index: toIndex,
P: c.Buf[toIndex],
}
c.Records = append(c.Records, &RecordJPZ{
FromTo: [2]*PositionPiece{fromPiece, to},
CambodianMove: c.CambodianMove,
})
// 王,士移动
switch fromPiece.P {
case WK:
if c.CambodianMove[MoveWK] {
c.CambodianMove[MoveWK] = false
}
case BK:
if c.CambodianMove[MoveBK] {
c.CambodianMove[MoveBK] = false
}
case WM:
if c.CambodianMove[MoveWM] && fromIndex == 4 {
c.CambodianMove[MoveWM] = false
}
case BM:
if c.CambodianMove[MoveBM] && fromIndex == 59 {
c.CambodianMove[MoveBM] = false
}
}
// 兵升士
if IsP(fromPiece.P) {
_, y, err := IndexToXY(c.Width, c.Height, toIndex)
if err == nil {
if IsBlack(fromPiece.P) {
if y == 2 {
c.Buf[fromIndex] = BM
}
} else {
if y == 5 {
c.Buf[fromIndex] = WM
}
}
}
}
c.Buf[toIndex] = c.Buf[fromIndex]
c.Buf[fromIndex] = ""
return to
}
// MoveBack 悔棋一步
func (c *ChessJPZ) MoveBack() bool {
if len(c.Records) == 0 {
return false
}
record := c.Records[len(c.Records)-1]
c.Records = c.Records[:len(c.Records)-1]
c.CambodianMove = record.CambodianMove
c.Buf[record.FromTo[0].Index] = record.FromTo[0].P
c.Buf[record.FromTo[1].Index] = record.FromTo[1].P
return true
}
// IsStop 是否无子可走
func (c *ChessJPZ) IsStop(isWhite bool) bool {
for k, v := range c.Buf {
if !IsEmpty(v) && IsWhite(v) == isWhite {
if len(c.GetMovePositions(k)) > 0 {
return false
}
}
}
return true
}
// GetMoveAllPositions 所有可移动棋子及位置
func (c *ChessJPZ) GetMoveAllPositions(isWhite bool) [][2]*PositionPiece {
var positions [][2]*PositionPiece
for k, v := range c.Buf {
if !IsEmpty(v) && IsWhite(v) == isWhite {
for _, p := range c.GetMovePositions(k) {
positions = append(positions, [2]*PositionPiece{{
Index: k,
P: v,
}, p})
}
}
}
return positions
}