Commit | Line | Data |
---|---|---|
c3a86f01 BA |
1 | import { ChessRules } from "@/base_rules"; |
2 | ||
32f6285e | 3 | export 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 | ||
7ba4a5bc | 46 | static GenRandInitFen(randomness) { |
3a2a7b5f BA |
47 | // Remove castle flags and en-passant indication |
48 | return ChessRules.GenRandInitFen(randomness).slice(0, -7); | |
c3a86f01 BA |
49 | } |
50 | ||
c3a86f01 BA |
51 | getPotentialBishopMoves(sq) { |
52 | let moves = this.getSlideNJumpMoves(sq, V.ElephantSteps, "oneStep"); | |
53 | // Complete with "repositioning moves": like a queen, without capture | |
54 | let repositioningMoves = this.getSlideNJumpMoves( | |
55 | sq, | |
56 | V.steps[V.BISHOP], | |
57 | "oneStep" | |
58 | ).filter(m => m.vanish.length == 1); | |
59 | return moves.concat(repositioningMoves); | |
60 | } | |
61 | ||
62 | getPotentialQueenMoves(sq) { | |
8055eabd BA |
63 | // Diagonal capturing moves |
64 | let captures = this.getSlideNJumpMoves( | |
c3a86f01 BA |
65 | sq, |
66 | V.steps[V.BISHOP], | |
67 | "oneStep" | |
8055eabd BA |
68 | ).filter(m => m.vanish.length == 2); |
69 | return captures.concat( | |
70 | // Orthogonal non-capturing moves | |
71 | this.getSlideNJumpMoves( | |
72 | sq, | |
73 | V.steps[V.ROOK], | |
74 | "oneStep" | |
75 | ).filter(m => m.vanish.length == 1) | |
c3a86f01 BA |
76 | ); |
77 | } | |
78 | ||
68e19a44 | 79 | isAttackedByBishop(sq, color) { |
c3a86f01 BA |
80 | return this.isAttackedBySlideNJump( |
81 | sq, | |
68e19a44 | 82 | color, |
c3a86f01 BA |
83 | V.BISHOP, |
84 | V.ElephantSteps, | |
85 | "oneStep" | |
86 | ); | |
87 | } | |
88 | ||
68e19a44 | 89 | isAttackedByQueen(sq, color) { |
c3a86f01 BA |
90 | return this.isAttackedBySlideNJump( |
91 | sq, | |
68e19a44 | 92 | color, |
c3a86f01 BA |
93 | V.QUEEN, |
94 | V.steps[V.BISHOP], | |
95 | "oneStep" | |
96 | ); | |
97 | } | |
98 | ||
8055eabd BA |
99 | getCurrentScore() { |
100 | const color = this.turn; | |
101 | const getScoreLost = () => { | |
102 | // Result if I lose: | |
103 | return color == "w" ? "0-1" : "1-0"; | |
104 | }; | |
105 | if (!this.atLeastOneMove()) | |
106 | // No valid move: I lose (this includes checkmate) | |
107 | return getScoreLost(); | |
108 | // Win if the opponent has no pieces left (except king), | |
109 | // and cannot bare king on the next move. | |
110 | let piecesLeft = { | |
111 | // No need to remember all pieces' squares: | |
112 | // variable only used if just one remaining piece. | |
113 | "w": {count: 0, square: null}, | |
114 | "b": {count: 0, square: null} | |
115 | }; | |
116 | outerLoop: for (let i=0; i<V.size.x; i++) { | |
117 | for (let j=0; j<V.size.y; j++) { | |
118 | if (this.board[i][j] != V.EMPTY && this.getPiece(i,j) != V.KING) { | |
119 | const sqCol = this.getColor(i,j); | |
120 | piecesLeft[sqCol].count++; | |
121 | piecesLeft[sqCol].square = [i,j]; | |
122 | } | |
123 | } | |
124 | } | |
125 | if (Object.values(piecesLeft).every(v => v.count > 0)) | |
126 | return "*"; | |
127 | // No pieces left for some side: if both kings are bare, it's a draw | |
128 | if (Object.values(piecesLeft).every(v => v.count == 0)) | |
129 | return "1/2"; | |
130 | if (piecesLeft[color].count > 0) | |
131 | // He could have drawn, but didn't take my last piece... | |
132 | return color == "w" ? "1-0" : "0-1"; | |
133 | const oppCol = V.GetOppCol(color); | |
134 | if (piecesLeft[oppCol].count >= 2) | |
135 | // 2 enemy units or more: I lose | |
136 | return getScoreLost(); | |
137 | // I don't have any piece, my opponent have one: can I take it? | |
68e19a44 | 138 | if (this.isAttacked(piecesLeft[oppCol].square, color)) |
8055eabd BA |
139 | // Yes! But I still need to take it |
140 | return "*"; | |
141 | // No :( | |
142 | return getScoreLost(); | |
143 | } | |
144 | ||
c3a86f01 BA |
145 | static get VALUES() { |
146 | return { | |
147 | p: 1, | |
148 | r: 5, | |
149 | n: 3, | |
8055eabd BA |
150 | b: 3, |
151 | q: 3, | |
c3a86f01 BA |
152 | k: 1000 |
153 | }; | |
154 | } | |
7e8a7ea1 | 155 | |
c3a86f01 | 156 | }; |