Add Fugue variant
[vchess.git] / client / src / variants / Progressive1.js
1 import { ChessRules } from "@/base_rules";
2 import { randInt } from "@/utils/alea";
3
4 export class Progressive1Rules extends ChessRules {
5
6 static get HasEnpassant() {
7 return false;
8 }
9
10 setOtherVariables(fen) {
11 super.setOtherVariables(fen);
12 this.subTurn = 1;
13 }
14
15 filterValid(moves) {
16 if (moves.length == 0) return [];
17 const color = this.turn;
18 return moves.filter(m => {
19 // Not using this.play() (would result ininfinite recursive calls)
20 V.PlayOnBoard(this.board, m);
21 if (m.appear[0].p == V.KING)
22 this.kingPos[color] = [m.appear[0].x, m.appear[0].y];
23 const res = !this.underCheck(color);
24 V.UndoOnBoard(this.board, m);
25 if (m.appear[0].p == V.KING)
26 this.kingPos[color] = [m.vanish[0].x, m.vanish[0].y];
27 return res;
28 });
29 }
30
31 play(move) {
32 if (V.HasFlags) move.flags = JSON.stringify(this.aggregateFlags());
33 const color = this.turn;
34 const oppCol = V.GetOppCol(color);
35 move.turn = [color, this.subTurn];
36 V.PlayOnBoard(this.board, move);
37 if (
38 this.subTurn > this.movesCount ||
39 this.underCheck(oppCol) ||
40 !this.atLeastOneMove()
41 ) {
42 this.turn = oppCol;
43 this.subTurn = 1;
44 this.movesCount++;
45 }
46 else this.subTurn++;
47 this.postPlay(move);
48 }
49
50 postPlay(move) {
51 const c = move.turn[0];
52 const piece = move.vanish[0].p;
53 const firstRank = c == "w" ? V.size.x - 1 : 0;
54
55 if (piece == V.KING && move.appear.length > 0) {
56 this.kingPos[c][0] = move.appear[0].x;
57 this.kingPos[c][1] = move.appear[0].y;
58 this.castleFlags[c] = [V.size.y, V.size.y];
59 return;
60 }
61 const oppCol = V.GetOppCol(c);
62 const oppFirstRank = V.size.x - 1 - firstRank;
63 if (
64 move.start.x == firstRank && //our rook moves?
65 this.castleFlags[c].includes(move.start.y)
66 ) {
67 const flagIdx = (move.start.y == this.castleFlags[c][0] ? 0 : 1);
68 this.castleFlags[c][flagIdx] = V.size.y;
69 }
70 if (
71 move.end.x == oppFirstRank && //we took opponent rook?
72 this.castleFlags[oppCol].includes(move.end.y)
73 ) {
74 const flagIdx = (move.end.y == this.castleFlags[oppCol][0] ? 0 : 1);
75 this.castleFlags[oppCol][flagIdx] = V.size.y;
76 }
77 }
78
79 undo(move) {
80 this.disaggregateFlags(JSON.parse(move.flags));
81 V.UndoOnBoard(this.board, move);
82 if (this.turn != move.turn[0]) this.movesCount--;
83 this.turn = move.turn[0];
84 this.subTurn = move.turn[1];
85 super.postUndo(move);
86 }
87
88 static get VALUES() {
89 return {
90 p: 1,
91 r: 5,
92 n: 3,
93 b: 3,
94 q: 7, //slightly less than in orthodox game
95 k: 1000
96 };
97 }
98
99 // Random moves (too high branching factor otherwise). TODO
100 getComputerMove() {
101 let res = [];
102 const color = this.turn;
103 while (this.turn == color) {
104 const moves = this.getAllValidMoves();
105 const m = moves[randInt(moves.length)];
106 res.push(m);
107 this.play(m);
108 }
109 for (let i=res.length - 1; i>= 0; i--) this.undo(res[i]);
110 return res;
111 }
112
113 };