package chess

import (
	"fmt"
	"math/rand"
	"strings"
	"testing"
)

func (c *ChessJPZ) TestPrint() {
	for row := 0; row < c.Height; row++ {
		for col := 0; col < c.Width; col++ {
			idx := (c.Height-1-row)*c.Width + col
			piece := c.Buf[idx]
			if IsEmpty(piece) {
				fmt.Printf("|. %2d|   ", idx) // 打印空格表示没有棋子
			} else {
				fmt.Printf("|%s%2d|   ", piece, idx)
			}
		}
		fmt.Println()
	}
}

func (c *ChessJPZ) TestPrintType() {
	fmt.Println("[]Piece{")
	for row := 0; row < c.Height; row++ {
		for col := 0; col < c.Width; col++ {
			idx := (c.Height-1-row)*c.Width + col
			piece := c.Buf[idx]
			if IsEmpty(piece) {
				fmt.Printf("\"\"") // 打印空格表示没有棋子
			} else {
				fmt.Printf("%s", piece)
			}
			if col < c.Width-1 {
				fmt.Print(",")
			}
		}
		fmt.Println()
	}
	fmt.Println("}")
}

func (c *ChessJPZ) TestSet(buf []Piece, bufString []string, cambodianMove []bool) {
	var buf2 []Piece
	if len(buf) > 0 {
		buf2 = make([]Piece, len(buf))
		for x := 0; x < c.Width; x++ {
			for y := 0; y < c.Height; y++ {
				buf2[(c.Height-1-y)*c.Width+x] = buf[y*c.Width+x]
			}
		}
	} else {
		buf2 = make([]Piece, len(bufString))
		for x := 0; x < c.Width; x++ {
			for y := 0; y < c.Height; y++ {
				buf2[(c.Height-1-y)*c.Width+x] = Piece(bufString[y*c.Width+x])
			}
		}
	}

	c.Buf = buf2
	if len(cambodianMove) == 4 {
		for k, v := range cambodianMove {
			c.CambodianMove[k] = v
		}
	}
}

func Print() {
	c := &ChessJPZ{}
	c.Init()
	c.TestPrint()
	c.TestPrintType()
}

func RandChess() {
	// 生成随机数据
	b := make([]Piece, len(pieceJPZ))
	copy(b, pieceJPZ)

	// 随机删除棋子
	for k, v := range b {
		if IsEmpty(v) || IsK(v) {
			continue
		}
		if rand.Intn(2) == 1 {
			b[k] = ""
		}
	}
	// 随机移动棋子
	rand.Shuffle(len(b), func(i, j int) {
		b[i], b[j] = b[j], b[i]
	})
	fmt.Println("[]Piece{")
	for row := 0; row < 8; row++ {
		for col := 0; col < 8; col++ {
			idx := (8-1-row)*8 + col
			piece := b[idx]
			if IsEmpty(piece) {
				fmt.Printf("\"\"") // 打印空格表示没有棋子
			} else {
				fmt.Printf("%s", piece)
			}
			if col < 7 {
				fmt.Print(",")
			}
		}
		fmt.Println()
	}
	fmt.Println("}")
}

func TestNoTest(t *testing.T) {
	//Print()
	RandChess()
}

func TestChessJPZ_GetIndexes(t *testing.T) {
	//	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,
	data := map[Piece][]int{
		WR: {0, 7},
		WN: {1, 6},
		WS: {2, 5},
		WM: {4},
		WK: {3},
		WP: {16, 17, 18, 19, 20, 21, 22, 23},
		BR: {56, 63},
		BN: {57, 62},
		BS: {58, 61},
		BM: {59},
		BK: {60},
		BP: {40, 41, 42, 43, 44, 45, 46, 47},
	}

	c := new(ChessJPZ)
	c.Init()
	//c.TestPrint()

	for k, target := range data {
		result := c.GetIndexes(k)
		if len(result) != len(target) {
			t.Fatalf("%s: target:%v, result:%v\n", k, target, result)
		}
		for _, r := range result {
			has := false
			for _, i := range target {
				if i == r {
					has = true
					break
				}
			}
			if !has {
				t.Fatalf("%s: target:%v, result:%v\n", k, target, result)
			}
		}
	}
}

func TestChessJPZ_GetMovePositions(t *testing.T) {
	type Test struct {
		Buf     []Piece
		WMMoved bool
		BMMoved bool
		WKMoved bool
		BKMoved bool

		Index int

		Moves []*PositionPiece
	}

	// 测试数据
	data := []Test{
		{
			Buf:     pieceJPZ,
			WMMoved: true,
			BMMoved: true,
			WKMoved: true,
			BKMoved: true,
			Index:   0,
			Moves: []*PositionPiece{
				{Index: 8, P: ""},
			},
		},
		{
			Buf:     pieceJPZ,
			WMMoved: true,
			BMMoved: true,
			WKMoved: true,
			BKMoved: true,
			Index:   1,
			Moves: []*PositionPiece{
				{Index: 11, P: ""},
			},
		},
		{
			Buf:     pieceJPZ,
			WMMoved: true,
			BMMoved: true,
			WKMoved: true,
			BKMoved: true,
			Index:   2,
			Moves:   []*PositionPiece{{Index: 9}, {Index: 11}, {Index: 10}},
		},
		{
			Buf:     pieceJPZ,
			WMMoved: true,
			BMMoved: true,
			WKMoved: true,
			BKMoved: true,
			Index:   3,
			Moves:   []*PositionPiece{{Index: 10}, {Index: 11}, {Index: 12}, {Index: 9}, {Index: 13}},
		},
		{
			Buf:     pieceJPZ,
			WMMoved: true,
			BMMoved: true,
			WKMoved: true,
			BKMoved: true,
			Index:   4,
			Moves:   []*PositionPiece{{Index: 11}, {Index: 13}},
		},
		{
			Buf:     pieceJPZ,
			WMMoved: true,
			BMMoved: true,
			WKMoved: true,
			BKMoved: true,
			Index:   5,
			Moves:   []*PositionPiece{{Index: 12}, {Index: 14}, {Index: 13}},
		},
		{
			Buf:     pieceJPZ,
			WMMoved: true,
			BMMoved: true,
			WKMoved: true,
			BKMoved: true,
			Index:   6,
			Moves:   []*PositionPiece{{Index: 12}},
		},
		{
			Buf:     pieceJPZ,
			WMMoved: true,
			BMMoved: true,
			WKMoved: true,
			BKMoved: true,
			Index:   7,
			Moves:   []*PositionPiece{{Index: 15}},
		},
		{
			Buf:     pieceJPZ,
			WMMoved: true,
			BMMoved: true,
			WKMoved: true,
			BKMoved: true,
			Index:   16,
			Moves:   []*PositionPiece{{Index: 24}},
		},
		{
			Buf:     pieceJPZ,
			WMMoved: true,
			BMMoved: true,
			WKMoved: true,
			BKMoved: true,
			Index:   17,
			Moves:   []*PositionPiece{{Index: 25}},
		},
		{
			Buf:     pieceJPZ,
			WMMoved: true,
			BMMoved: true,
			WKMoved: true,
			BKMoved: true,
			Index:   40,
			Moves:   []*PositionPiece{{Index: 32}},
		},
		{
			Buf:     pieceJPZ,
			WMMoved: true,
			BMMoved: true,
			WKMoved: true,
			BKMoved: true,
			Index:   41,
			Moves:   []*PositionPiece{{Index: 33}},
		},
		{
			Buf:     pieceJPZ,
			WMMoved: true,
			BMMoved: true,
			WKMoved: true,
			BKMoved: true,
			Index:   56,
			Moves:   []*PositionPiece{{Index: 48}},
		},
		{
			Buf:     pieceJPZ,
			WMMoved: true,
			BMMoved: true,
			WKMoved: true,
			BKMoved: true,
			Index:   57,
			Moves:   []*PositionPiece{{Index: 51}},
		},
		{
			Buf:     pieceJPZ,
			WMMoved: true,
			BMMoved: true,
			WKMoved: true,
			BKMoved: true,
			Index:   58,
			Moves:   []*PositionPiece{{Index: 49}, {Index: 50}, {Index: 51}},
		},
		{
			Buf:     pieceJPZ,
			WMMoved: true,
			BMMoved: true,
			WKMoved: true,
			BKMoved: true,
			Index:   59,
			Moves:   []*PositionPiece{{Index: 50}, {Index: 52}},
		},
		{
			Buf:     pieceJPZ,
			WMMoved: true,
			BMMoved: true,
			WKMoved: true,
			BKMoved: true,
			Index:   60,
			Moves:   []*PositionPiece{{Index: 51}, {Index: 52}, {Index: 53}, {Index: 50}, {Index: 54}},
		},
		{
			Buf:     pieceJPZ,
			WMMoved: true,
			BMMoved: true,
			WKMoved: true,
			BKMoved: true,
			Index:   61,
			Moves:   []*PositionPiece{{Index: 52}, {Index: 54}, {Index: 53}},
		},
		{
			Buf:     pieceJPZ,
			WMMoved: true,
			BMMoved: true,
			WKMoved: true,
			BKMoved: true,
			Index:   62,
			Moves:   []*PositionPiece{{Index: 52}},
		},
		{
			Buf:     pieceJPZ,
			WMMoved: true,
			BMMoved: true,
			WKMoved: true,
			BKMoved: true,
			Index:   63,
			Moves:   []*PositionPiece{{Index: 55}},
		},
		{
			Buf:     pieceJPZ,
			WMMoved: true,
			BMMoved: true,
			WKMoved: true,
			BKMoved: false,
			Index:   60,
			Moves:   []*PositionPiece{{Index: 51}, {Index: 52}, {Index: 53}},
		},
		{
			Buf:     pieceJPZ,
			WMMoved: true,
			BMMoved: true,
			BKMoved: true,
			WKMoved: false,
			Index:   3,
			Moves:   []*PositionPiece{{Index: 10}, {Index: 11}, {Index: 12}},
		},
		{
			Buf: []Piece{
				BR, BN, BS, BM, BK, BS, BN, BR,
				"", "", "", "", "", "", "", "",
				BP, BP, BP, BP, BP, BP, BP, BP,
				"", "", "", "", "", "", "", "",
				"", "", "", "", "", "", "", "",
				WP, WP, WP, WP, "", WP, WP, WP,
				"", "", "", "", "", "", "", "",
				WR, WN, WS, WK, WM, WS, WN, WR,
			},
			BMMoved: true,
			WKMoved: true,
			BKMoved: true,
			WMMoved: false,
			Index:   4,
			Moves:   []*PositionPiece{{Index: 11}, {Index: 13}},
		},
		{
			Buf: []Piece{
				BR, BN, BS, BM, BK, BS, BN, BR,
				"", "", "", "", "", "", "", "",
				BP, BP, BP, BP, BP, BP, BP, BP,
				"", "", "", "", "", "", "", "",
				"", "", "", "", "", "", "", "",
				WP, WP, WP, WP, "", WP, WP, WP,
				"", "", "", "", "", "", "", "",
				WR, WN, WS, WK, WM, WS, WN, WR,
			},
			WMMoved: true,
			Index:   4,
			Moves:   []*PositionPiece{{Index: 11}, {Index: 13}, {Index: 20}},
		},
		{
			Buf: []Piece{
				BR, BN, BS, BM, BK, BS, BN, BR,
				"", "", "", "", "", "", "", "",
				BP, BP, BP, "", BP, BP, BP, BP,
				"", "", "", "", "", "", "", "",
				"", "", "", "", "", "", "", "",
				WP, WP, WP, WP, "", WP, WP, WP,
				"", "", "", "", "", "", "", "",
				WR, WN, WS, WK, WM, WS, WN, WR,
			},
			WMMoved: true,
			WKMoved: true,
			BKMoved: true,
			BMMoved: false,
			Index:   59,
			Moves:   []*PositionPiece{{Index: 50}, {Index: 52}},
		},
		{
			Buf: []Piece{
				BR, BN, BS, BM, BK, BS, BN, BR,
				"", "", "", "", "", "", "", "",
				BP, BP, BP, "", BP, BP, BP, BP,
				"", "", "", "", "", "", "", "",
				"", "", "", "", "", "", "", "",
				WP, WP, WP, WP, "", WP, WP, WP,
				"", "", "", "", "", "", "", "",
				WR, WN, WS, WK, WM, WS, WN, WR,
			},
			BMMoved: true,
			Index:   59,
			Moves:   []*PositionPiece{{Index: 50}, {Index: 52}, {Index: 43}},
		},
	}

	f := func(name string, moves []*PositionPiece) {
		b := strings.Builder{}
		for _, s := range moves {
			b.WriteString(fmt.Sprintf("%+v,", *s))
		}
		fmt.Println(name, b.String())
	}

	c := new(ChessJPZ)
	c.Init()
	//c.TestPrint()
	for _, v := range data {
		c.TestSet(v.Buf, nil, []bool{v.WKMoved, v.WMMoved, v.BMMoved, v.BKMoved})
		moves := c.GetMovePositions(v.Index)
		if len(v.Moves) != len(moves) {
			c.TestPrint()
			fmt.Printf("Index:%v\n", v.Index)
			f("Target Moves:", v.Moves)
			f("Result Moves:", moves)
			t.Fail()
		}
		for _, m := range moves {
			has := false
			for _, v := range v.Moves {
				if v.Index == m.Index && v.P == m.P {
					has = true
					break
				}
			}
			if !has {
				c.TestPrint()
				fmt.Printf("Index:%v\n", v.Index)
				f("Target Moves:", v.Moves)
				f("Result Moves:", moves)
				t.Fail()
			}
		}
	}
}

func TestChessJPZ_GetMovePositions2(t *testing.T) {
	testChess := []Piece{
		BR, "", BS, BM, BK, BN, "", "",
		"", "", "", "", "", "", "", WR,
		BP, "", WM, WN, "", WM, "", BP,
		"", "", "", "", "", "", "", "",
		"", "", "", "", "", "", "", "",
		WP, "", BP, "", "", BP, "", WP,
		"", "", "", "", "", "", "", "",
		"", "", WS, WK, WM, "", "", "",
	}

	type Test struct {
		Buf     []Piece
		WMMoved bool
		BMMoved bool
		WKMoved bool
		BKMoved bool
		Index   int
		Moves   []*PositionPiece
	}

	data := []Test{
		{
			Buf: testChess, WMMoved: true, BMMoved: true, WKMoved: true, BKMoved: true,
			Index: 2,
			Moves: []*PositionPiece{{Index: 9}, {Index: 11}, {Index: 10}},
		},
		{
			Buf: testChess, WMMoved: true, BMMoved: true, WKMoved: true, BKMoved: true,
			Index: 3,
			Moves: []*PositionPiece{{Index: 10}, {Index: 13}},
		},
		{
			Buf: testChess, WMMoved: true, BMMoved: true, WKMoved: true, BKMoved: true,
			Index: 4,
			Moves: []*PositionPiece{{Index: 11}, {Index: 13}, {Index: 20}},
		},
		{
			Buf:   testChess,
			Index: 2,
			Moves: []*PositionPiece{{Index: 9}, {Index: 11}, {Index: 10}},
		},
		{
			Buf:   testChess,
			Index: 3,
			Moves: []*PositionPiece{{Index: 10}},
		},
		{
			Buf:   testChess,
			Index: 4,
			Moves: []*PositionPiece{{Index: 11}, {Index: 13}},
		},

		{
			Buf: testChess, WMMoved: true, BMMoved: true, WKMoved: true, BKMoved: true,
			Index: 16,
			Moves: []*PositionPiece{{Index: 24}},
		},
		{
			Buf: testChess, WMMoved: true, BMMoved: true, WKMoved: true, BKMoved: true,
			Index: 18,
			Moves: []*PositionPiece{},
		},
		{
			Buf: testChess, WMMoved: true, BMMoved: true, WKMoved: true, BKMoved: true,
			Index: 21,
			Moves: []*PositionPiece{},
		},
		{
			Buf: testChess, WMMoved: true, BMMoved: true, WKMoved: true, BKMoved: true,
			Index: 23,
			Moves: []*PositionPiece{{Index: 31}},
		},
		{
			Buf:   testChess,
			Index: 16,
			Moves: []*PositionPiece{{Index: 24}},
		},
		{
			Buf:   testChess,
			Index: 18,
			Moves: []*PositionPiece{},
		},
		{
			Buf:   testChess,
			Index: 21,
			Moves: []*PositionPiece{},
		},
		{
			Buf:   testChess,
			Index: 23,
			Moves: []*PositionPiece{{Index: 31}},
		},

		{
			Buf: testChess, WMMoved: true, BMMoved: true, WKMoved: true, BKMoved: true,
			Index: 40,
			Moves: []*PositionPiece{},
		},
		{
			Buf: testChess, WMMoved: true, BMMoved: true, WKMoved: true, BKMoved: true,
			Index: 42,
			Moves: []*PositionPiece{{Index: 33}, {Index: 49}, {Index: 35}, {Index: 51}},
		},
		{
			Buf: testChess, WMMoved: true, BMMoved: true, WKMoved: true, BKMoved: true,
			Index: 43,
			Moves: []*PositionPiece{{Index: 53}, {Index: 37}, {Index: 49}, {Index: 33}, {Index: 60, P: BK}, {Index: 28}, {Index: 58, P: BS}, {Index: 26}},
		},
		{
			Buf: testChess, WMMoved: true, BMMoved: true, WKMoved: true, BKMoved: true,
			Index: 45,
			Moves: []*PositionPiece{{Index: 36}, {Index: 52}, {Index: 38}, {Index: 54}},
		},
		{
			Buf: testChess, WMMoved: true, BMMoved: true, WKMoved: true, BKMoved: true,
			Index: 47,
			Moves: []*PositionPiece{},
		},

		{
			Buf:   testChess,
			Index: 40,
			Moves: []*PositionPiece{},
		},
		{
			Buf:   testChess,
			Index: 42,
			Moves: []*PositionPiece{{Index: 33}, {Index: 49}, {Index: 35}, {Index: 51}},
		},
		{
			Buf:   testChess,
			Index: 43,
			Moves: []*PositionPiece{{Index: 53}, {Index: 37}, {Index: 49}, {Index: 33}, {Index: 60, P: BK}, {Index: 28}, {Index: 58, P: BS}, {Index: 26}},
		},
		{
			Buf:   testChess,
			Index: 45,
			Moves: []*PositionPiece{{Index: 36}, {Index: 52}, {Index: 38}, {Index: 54}},
		},
		{
			Buf:   testChess,
			Index: 47,
			Moves: []*PositionPiece{},
		},

		{
			Buf:   testChess,
			Index: 55,
			Moves: []*PositionPiece{{Index: 47, P: BP}, {Index: 63}, {Index: 54}, {Index: 53}, {Index: 52}, {Index: 51}, {Index: 50}, {Index: 49}, {Index: 48}},
		},

		{
			Buf: testChess, WMMoved: true, BMMoved: true, WKMoved: true, BKMoved: true,
			Index: 56,
			Moves: []*PositionPiece{},
		},
		{
			Buf: testChess, WMMoved: true, BMMoved: true, WKMoved: true, BKMoved: true,
			Index: 58,
			Moves: []*PositionPiece{},
		},
		{
			Buf: testChess, WMMoved: true, BMMoved: true, WKMoved: true, BKMoved: true,
			Index: 59,
			Moves: []*PositionPiece{},
		},
		{
			Buf: testChess, WMMoved: true, BMMoved: true, WKMoved: true, BKMoved: true,
			Index: 60,
			Moves: []*PositionPiece{},
		},
		{
			Buf: testChess, WMMoved: true, BMMoved: true, WKMoved: true, BKMoved: true,
			Index: 61,
			Moves: []*PositionPiece{},
		},
		{
			Buf:   testChess,
			Index: 56,
			Moves: []*PositionPiece{},
		},
		{
			Buf:   testChess,
			Index: 58,
			Moves: []*PositionPiece{},
		},
		{
			Buf:   testChess,
			Index: 59,
			Moves: []*PositionPiece{},
		},
		{
			Buf:   testChess,
			Index: 60,
			Moves: []*PositionPiece{},
		},
		{
			Buf:   testChess,
			Index: 61,
			Moves: []*PositionPiece{},
		},
	}

	f := func(name string, moves []*PositionPiece) {
		b := strings.Builder{}
		for _, s := range moves {
			b.WriteString(fmt.Sprintf("%+v,", *s))
		}
		fmt.Println(name, b.String())
	}

	c := new(ChessJPZ)
	c.Init()
	//c.TestPrint()
	for _, v := range data {
		c.TestSet(v.Buf, nil, []bool{v.WKMoved, v.WMMoved, v.BMMoved, v.BKMoved})
		moves := c.GetMovePositions(v.Index)
		if len(v.Moves) != len(moves) {
			c.TestPrint()
			fmt.Printf("Index:%v\n", v.Index)
			f("Target Moves:", v.Moves)
			f("Result Moves:", moves)
			t.Fatal()
		}
		for _, m := range moves {
			has := false
			for _, v := range v.Moves {
				if v.Index == m.Index && v.P == m.P {
					has = true
					break
				}
			}
			if !has {
				c.TestPrint()
				fmt.Printf("Index:%v\n", v.Index)
				f("Target Moves:", v.Moves)
				f("Result Moves:", moves)
				t.Fatal()
			}
		}
	}

}

func TestChessJPZ_GetMoveAllPositions(t *testing.T) {
	type Test struct {
		Buf                    []Piece
		WMMoved                bool
		BMMoved                bool
		WKMoved                bool
		BKMoved                bool
		WhiteMoves, BlackMoves [][2]*PositionPiece
	}

	data := []Test{
		{
			Buf: []Piece{
				"", "", "", "", BS, "", "", "",
				"", "", BM, "", "", "", BS, "",
				"", "", "", "", WK, "", "", "",
				"", "", BN, "", "", "", "", BR,
				"", WM, "", WR, WN, BP, "", "",
				"", "", BK, "", "", BP, "", WP,
				"", WR, "", "", "", "", "", "",
				WM, "", "", "", "", "", "", "",
			},
			WhiteMoves: [][2]*PositionPiece{{{Index: 25, P: WM}, {Index: 34, P: BN}}, {{Index: 28, P: WN}, {Index: 34, P: BN}}},
			BlackMoves: [][2]*PositionPiece{{{Index: 18, P: BK}, {Index: 27, P: WR}}},
		},
	}

	f := func(name string, moves [][2]*PositionPiece) {
		b := strings.Builder{}
		for _, s := range moves {
			b.WriteString(fmt.Sprintf("%+v,", *s[0]))
			b.WriteString(fmt.Sprintf("%+v,", *s[1]))
		}
		fmt.Println(name, b.String())
	}

	c := new(ChessJPZ)
	c.Init()
	//c.TestPrint()
	for _, v := range data {
		c.TestSet(v.Buf, nil, []bool{v.WKMoved, v.WMMoved, v.BMMoved, v.BKMoved})
		moves := c.GetMoveAllPositions(true)
		if len(v.WhiteMoves) != len(moves) {
			c.TestPrint()
			f("Target WhiteMoves:", v.WhiteMoves)
			f("Result WhiteMoves:", moves)
			t.Fatal()
		}
		for _, m := range moves {
			has := false
			for _, v := range v.WhiteMoves {
				if v[0].Index == m[0].Index && v[0].P == m[0].P && v[1].Index == m[1].Index && v[1].P == m[1].P {
					has = true
					break
				}
			}
			if !has {
				c.TestPrint()
				f("Target WhiteMoves:", v.WhiteMoves)
				f("Result WhiteMoves:", moves)
				t.Fatal()
			}
		}

		moves = c.GetMoveAllPositions(false)
		if len(v.BlackMoves) != len(moves) {
			c.TestPrint()
			f("Target BlackMoves:", v.BlackMoves)
			f("Result BlackMoves:", moves)
			t.Fatal()
		}
		for _, m := range moves {
			has := false
			for _, v := range v.BlackMoves {
				if v[0].Index == m[0].Index && v[0].P == m[0].P && v[1].Index == m[1].Index && v[1].P == m[1].P {
					has = true
					break
				}
			}
			if !has {
				c.TestPrint()
				f("Target BlackMoves:", v.BlackMoves)
				f("Result BlackMoves:", moves)
				t.Fatal()
			}
		}
	}

}

func TestChessJPZ_IsCheck(t *testing.T) {
	type Test struct {
		Buf       []Piece
		WMMoved   bool
		BMMoved   bool
		WKMoved   bool
		BKMoved   bool
		Check     [2]bool
		Checkmate [2]bool
		Stop      [2]bool
	}

	data := []Test{
		{
			Buf: []Piece{
				BR, "", BS, BM, BK, BN, "", "",
				"", "", "", "", "", "", "", WR,
				BP, "", WM, WN, "", WM, "", BP,
				"", "", "", "", "", "", "", "",
				"", "", "", "", "", "", "", "",
				WP, "", BP, "", "", BP, "", WP,
				"", "", "", "", "", "", "", "",
				"", "", WS, WK, WM, "", "", "",
			},
			WMMoved:   true,
			BMMoved:   true,
			WKMoved:   true,
			BKMoved:   true,
			Check:     [2]bool{true, false},
			Checkmate: [2]bool{true, false},
			Stop:      [2]bool{false, true},
		},
		{
			Buf: []Piece{
				BR, "", BS, BM, BK, BN, "", "",
				"", "", "", "", "", "", "", WR,
				BP, "", WM, WN, "", WM, "", BP,
				"", "", "", "", "", "", "", "",
				"", "", "", "", "", "", "", "",
				WP, "", BP, "", "", BP, "", WP,
				"", "", "", "", "", "", "", "",
				"", "", WS, WK, WM, "", "", "",
			},
			Check:     [2]bool{true, false},
			Checkmate: [2]bool{true, false},
			Stop:      [2]bool{false, true},
		},
		{
			Buf: []Piece{
				"", "", "", "", BS, "", "", "",
				"", "", BM, "", "", "", BS, "",
				"", "", "", "", WK, "", "", "",
				"", "", BN, "", "", "", "", BR,
				"", WM, "", WR, WN, BP, "", "",
				"", "", BK, "", "", BP, "", WP,
				"", WR, "", "", "", "", "", "",
				WM, "", "", "", "", "", "", "",
			},
			Check:     [2]bool{true, true},
			Checkmate: [2]bool{false, false},
			Stop:      [2]bool{false, false},
		},
		{
			Buf: []Piece{
				"", "", "", "", BS, "", "", "",
				"", "", BM, "", "", "", BS, "",
				"", BK, "", "", WK, "", "", "",
				"", "", BP, "", "", "", "", BR,
				"", "", WP, "", "", "", "", "",
				"", "", "", "", "", "", "", "",
				"", "", "", "", "", "", "", "",
				"", "", "", "", "", "", "", "",
			},
			Check:     [2]bool{false, false},
			Checkmate: [2]bool{false, false},
			Stop:      [2]bool{true, false},
		},
		{
			Buf: []Piece{
				"", "", "", "", WR, "", WR, "",
				"", "", BM, BR, "", BK, "", "",
				"", "", "", "", "", "", "", "",
				"", "", "", "", WN, "", WP, "",
				"", "", "", BP, "", "", "", "",
				"", "", BS, "", WP, "", WS, "",
				"", "", WS, "", WK, "", BM, "",
				"", "", "", "", WM, "", "", "",
			},
			Check:     [2]bool{true, false},
			Checkmate: [2]bool{true, false},
			Stop:      [2]bool{false, true},
		},
	}

	c := new(ChessJPZ)
	c.Init()
	//c.TestPrint()
	for _, v := range data {
		c.TestSet(v.Buf, nil, []bool{v.WKMoved, v.WMMoved, v.BMMoved, v.BKMoved})
		if v.Check[0] != c.IsCheck(true) || v.Check[1] != c.IsCheck(false) {
			c.TestPrint()
			fmt.Println("Target Check:", v.Check)
			fmt.Println("Result Check:", c.IsCheck(true), c.IsCheck(false))
			t.Fatal()
		}
		if v.Checkmate[0] != c.IsCheckmate(true) || v.Checkmate[1] != c.IsCheckmate(false) {
			c.TestPrint()
			fmt.Println("Target Checkmate:", v.Checkmate)
			fmt.Println("Result Checkmate:", c.IsCheckmate(true), c.IsCheckmate(false))
			t.Fatal()
		}
		if v.Stop[0] != c.IsStop(true) || v.Stop[1] != c.IsStop(false) {
			c.TestPrint()
			fmt.Println("Target Stop:", v.Stop)
			fmt.Println("Result Stop:", c.IsStop(true), c.IsStop(false))
			t.Fatal()
		}
	}
}
