1ae531d5083fdb312861c265be0607c88a84f8ce
1 import { ChessRules
} from "@/base_rules";
2 import { ArrayFun
} from "@/utils/array";
3 import { randInt
, shuffle
} from "@/utils/alea";
5 export const VariantRules
= class RoyalraceRules
extends ChessRules
{
6 static get HasFlags() {
10 static get HasEnpassant() {
14 static get CanFlip() {
19 return { x: 11, y: 11 };
22 static GenRandInitFen() {
23 let pieces
= { w: new Array(10), b: new Array(10) };
24 // Shuffle pieces on first and second rank
25 for (let c
of ["w", "b"]) {
26 // Reserve 4 and 5 which are pawns positions
27 let positions
= ArrayFun
.range(10).filter(i
=> i
!= 4 && i
!= 5);
29 // Get random squares for bishops
30 let randIndex
= 2 * randInt(4);
31 const bishop1Pos
= positions
[randIndex
];
32 // The second bishop must be on a square of different color
33 let randIndex_tmp
= 2 * randInt(4) + 1;
34 const bishop2Pos
= positions
[randIndex_tmp
];
35 // Remove chosen squares
36 positions
.splice(Math
.max(randIndex
, randIndex_tmp
), 1);
37 positions
.splice(Math
.min(randIndex
, randIndex_tmp
), 1);
39 // Place the king at random on (remaining squares of) first row
41 if (positions
[maxIndex
-1] >= 4)
43 if (positions
[maxIndex
-1] >= 4)
45 randIndex
= randInt(maxIndex
);
46 const kingPos
= positions
[randIndex
];
47 positions
.splice(randIndex
, 1);
49 // Get random squares for knights
50 randIndex
= randInt(5);
51 const knight1Pos
= positions
[randIndex
];
52 positions
.splice(randIndex
, 1);
53 randIndex
= randInt(4);
54 const knight2Pos
= positions
[randIndex
];
55 positions
.splice(randIndex
, 1);
57 // Get random squares for rooks
58 randIndex
= randInt(3);
59 const rook1Pos
= positions
[randIndex
];
60 positions
.splice(randIndex
, 1);
61 randIndex
= randInt(2);
62 const rook2Pos
= positions
[randIndex
];
63 positions
.splice(randIndex
, 1);
65 // Queen position is now determined,
66 // because pawns are not placed at random
67 const queenPos
= positions
[0];
69 // Finally put the shuffled pieces in the board array
70 pieces
[c
][rook1Pos
] = "r";
71 pieces
[c
][knight1Pos
] = "n";
72 pieces
[c
][bishop1Pos
] = "b";
73 pieces
[c
][queenPos
] = "q";
74 pieces
[c
][kingPos
] = "k";
75 pieces
[c
][bishop2Pos
] = "b";
76 pieces
[c
][knight2Pos
] = "n";
77 pieces
[c
][rook2Pos
] = "r";
81 const whiteFen
= pieces
["w"].join("").toUpperCase();
82 const blackFen
= pieces
["b"].join("");
84 "11/11/11/11/11/11/11/11/11/" +
85 whiteFen
.substr(5).split("").reverse().join("") +
87 blackFen
.substr(5).split("").reverse().join("") +
89 whiteFen
.substr(0,5) + "1" + blackFen
.substr(0,5) +
94 getPotentialPawnMoves([x
, y
]) {
95 // Normal moves (as a rook)
97 this.getSlideNJumpMoves([x
, y
], V
.steps
[V
.ROOK
]).filter(m
=> {
98 // Remove captures. Alt: redefine canTake
99 return m
.vanish
.length
== 1;
104 for (let shiftY
of [-1, 1]) {
106 V
.OnBoard(x
+ shiftX
, y
+ shiftY
) &&
107 this.board
[x
+ shiftX
][y
+ shiftY
] != V
.EMPTY
&&
108 this.canTake([x
, y
], [x
+ shiftX
, y
+ shiftY
])
110 moves
.push(this.getBasicMove([x
, y
], [x
+ shiftX
, y
+ shiftY
]));
117 getPotentialKnightMoves(sq
) {
118 // Knight becomes knightrider:
119 return this.getSlideNJumpMoves(sq
, V
.steps
[V
.KNIGHT
]);
122 // What are the king moves from square x,y ?
123 getPotentialKingMoves(sq
) {
124 return this.getSlideNJumpMoves(
126 V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
]),
132 if (moves
.length
== 0) return [];
133 const color
= this.turn
;
134 const oppCol
= V
.GetOppCol(color
);
135 return moves
.filter(m
=> {
137 // Giving check is forbidden as well:
138 const res
= !this.underCheck(color
) && !this.underCheck(oppCol
);
144 isAttackedByPawn([x
, y
], colors
) {
146 if (x
+ pawnShift
< V
.size
.x
) {
147 for (let c
of colors
) {
148 for (let i
of [-1, 1]) {
152 this.getPiece(x
+ pawnShift
, y
+ i
) == V
.PAWN
&&
153 this.getColor(x
+ pawnShift
, y
+ i
) == c
163 isAttackedByKnight(sq
, colors
) {
164 return this.isAttackedBySlideNJump(
174 const color
= V
.GetOppCol(this.turn
);
175 if (this.kingPos
[color
][0] == 0)
176 // The opposing edge is reached!
177 return color
== "w" ? "1-0" : "0-1";
181 static get SEARCH_DEPTH() {
185 static get VALUES() {
198 let evaluation
= super.evalPosition();
199 // Ponder with king position:
200 return evaluation
/5 + this.kingPos
["b"][0] - this.kingPos
["w"][0];
204 // Since pawns are much more mobile, treat them as other pieces:
206 move.vanish
[0].p
.toUpperCase() +
207 (move.vanish
.length
> move.appear
.length
? "x" : "") +
208 V
.CoordsToSquare(move.end
)