Add Sittuyin + Doublemove2. A few fixes. TODO: fix Ambiguous bugs and playing on...
[vchess.git] / client / src / variants / Shatranj.js
CommitLineData
c3a86f01
BA
1import { ChessRules } from "@/base_rules";
2
32f6285e 3export class ShatranjRules extends ChessRules {
c3a86f01
BA
4 static get HasFlags() {
5 return false;
6 }
7
8 static get HasEnpassant() {
9 return false;
10 }
11
32f6285e
BA
12 static get PawnSpecs() {
13 return Object.assign(
14 {},
15 ChessRules.PawnSpecs,
16 {
17 twoSquares: false,
18 promotions: [V.QUEEN]
19 }
20 );
21 }
22
b406466b
BA
23 getPpath(b) {
24 if (b[1] == 'b') return "Shatranj/" + b;
25 return b;
26 }
27
c3a86f01
BA
28 static get ElephantSteps() {
29 return [
30 [-2, -2],
31 [-2, 2],
32 [2, -2],
33 [2, 2]
34 ];
35 }
36
7ba4a5bc 37 static GenRandInitFen(randomness) {
3a2a7b5f
BA
38 // Remove castle flags and en-passant indication
39 return ChessRules.GenRandInitFen(randomness).slice(0, -7);
c3a86f01
BA
40 }
41
c3a86f01
BA
42 getPotentialBishopMoves(sq) {
43 let moves = this.getSlideNJumpMoves(sq, V.ElephantSteps, "oneStep");
44 // Complete with "repositioning moves": like a queen, without capture
45 let repositioningMoves = this.getSlideNJumpMoves(
46 sq,
47 V.steps[V.BISHOP],
48 "oneStep"
49 ).filter(m => m.vanish.length == 1);
50 return moves.concat(repositioningMoves);
51 }
52
53 getPotentialQueenMoves(sq) {
8055eabd
BA
54 // Diagonal capturing moves
55 let captures = this.getSlideNJumpMoves(
c3a86f01
BA
56 sq,
57 V.steps[V.BISHOP],
58 "oneStep"
8055eabd
BA
59 ).filter(m => m.vanish.length == 2);
60 return captures.concat(
61 // Orthogonal non-capturing moves
62 this.getSlideNJumpMoves(
63 sq,
64 V.steps[V.ROOK],
65 "oneStep"
66 ).filter(m => m.vanish.length == 1)
c3a86f01
BA
67 );
68 }
69
68e19a44 70 isAttackedByBishop(sq, color) {
c3a86f01
BA
71 return this.isAttackedBySlideNJump(
72 sq,
68e19a44 73 color,
c3a86f01
BA
74 V.BISHOP,
75 V.ElephantSteps,
76 "oneStep"
77 );
78 }
79
68e19a44 80 isAttackedByQueen(sq, color) {
c3a86f01
BA
81 return this.isAttackedBySlideNJump(
82 sq,
68e19a44 83 color,
c3a86f01
BA
84 V.QUEEN,
85 V.steps[V.BISHOP],
86 "oneStep"
87 );
88 }
89
8055eabd
BA
90 getCurrentScore() {
91 const color = this.turn;
92 const getScoreLost = () => {
93 // Result if I lose:
94 return color == "w" ? "0-1" : "1-0";
95 };
96 if (!this.atLeastOneMove())
97 // No valid move: I lose (this includes checkmate)
98 return getScoreLost();
99 // Win if the opponent has no pieces left (except king),
100 // and cannot bare king on the next move.
101 let piecesLeft = {
102 // No need to remember all pieces' squares:
103 // variable only used if just one remaining piece.
104 "w": {count: 0, square: null},
105 "b": {count: 0, square: null}
106 };
107 outerLoop: for (let i=0; i<V.size.x; i++) {
108 for (let j=0; j<V.size.y; j++) {
109 if (this.board[i][j] != V.EMPTY && this.getPiece(i,j) != V.KING) {
110 const sqCol = this.getColor(i,j);
111 piecesLeft[sqCol].count++;
112 piecesLeft[sqCol].square = [i,j];
113 }
114 }
115 }
116 if (Object.values(piecesLeft).every(v => v.count > 0))
117 return "*";
118 // No pieces left for some side: if both kings are bare, it's a draw
119 if (Object.values(piecesLeft).every(v => v.count == 0))
120 return "1/2";
121 if (piecesLeft[color].count > 0)
122 // He could have drawn, but didn't take my last piece...
123 return color == "w" ? "1-0" : "0-1";
124 const oppCol = V.GetOppCol(color);
125 if (piecesLeft[oppCol].count >= 2)
126 // 2 enemy units or more: I lose
127 return getScoreLost();
128 // I don't have any piece, my opponent have one: can I take it?
68e19a44 129 if (this.isAttacked(piecesLeft[oppCol].square, color))
8055eabd
BA
130 // Yes! But I still need to take it
131 return "*";
132 // No :(
133 return getScoreLost();
134 }
135
c3a86f01
BA
136 static get VALUES() {
137 return {
138 p: 1,
139 r: 5,
140 n: 3,
8055eabd
BA
141 b: 3,
142 q: 3,
c3a86f01
BA
143 k: 1000
144 };
145 }
146};