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