Several small improvements + integrate options + first working draft of Cwda
[vchess.git] / client / src / variants / Ordamirror.js
1 import { ChessRules } from "@/base_rules";
2 import { OrdaRules } from "@/variants/Orda";
3 import { ArrayFun } from "@/utils/array";
4 import { randInt } from "@/utils/alea";
5
6 export class OrdamirrorRules extends OrdaRules {
7
8 static get PawnSpecs() {
9 return Object.assign(
10 {},
11 ChessRules.PawnSpecs,
12 { promotions: [V.LANCER, V.ARCHER, V.KHESHIG, V.FALCON] }
13 );
14 }
15
16 static get HasFlags() {
17 return false;
18 }
19
20 static get HasEnpassant() {
21 return false;
22 }
23
24 getPpath(b) {
25 return "Orda/" + b;
26 }
27
28 static GenRandInitFen(options) {
29 if (options.randomness == 0)
30 return "lhafkahl/8/pppppppp/8/8/PPPPPPPP/8/LHAFKAHL w 0 ah -";
31
32 let pieces = { w: new Array(8), b: new Array(8) };
33 // Shuffle pieces on first (and last rank if randomness == 2)
34 for (let c of ["w", "b"]) {
35 if (c == 'b' && options.randomness == 1) {
36 pieces['b'] = pieces['w'];
37 break;
38 }
39
40 let positions = ArrayFun.range(8);
41
42 let randIndex = 2 * randInt(4);
43 const bishop1Pos = positions[randIndex];
44 let randIndex_tmp = 2 * randInt(4) + 1;
45 const bishop2Pos = positions[randIndex_tmp];
46 positions.splice(Math.max(randIndex, randIndex_tmp), 1);
47 positions.splice(Math.min(randIndex, randIndex_tmp), 1);
48
49 randIndex = randInt(6);
50 const knight1Pos = positions[randIndex];
51 positions.splice(randIndex, 1);
52 randIndex = randInt(5);
53 const knight2Pos = positions[randIndex];
54 positions.splice(randIndex, 1);
55
56 randIndex = randInt(4);
57 const queenPos = positions[randIndex];
58 positions.splice(randIndex, 1);
59
60 const rook1Pos = positions[0];
61 const kingPos = positions[1];
62 const rook2Pos = positions[2];
63
64 pieces[c][rook1Pos] = "l";
65 pieces[c][knight1Pos] = "h";
66 pieces[c][bishop1Pos] = "a";
67 pieces[c][queenPos] = "f";
68 pieces[c][kingPos] = "k";
69 pieces[c][bishop2Pos] = "a";
70 pieces[c][knight2Pos] = "h";
71 pieces[c][rook2Pos] = "l";
72 }
73 return (
74 pieces["b"].join("") +
75 "/8/pppppppp/8/8/PPPPPPPP/8/" +
76 pieces["w"].join("").toUpperCase() +
77 " w 0"
78 );
79 }
80
81 static get FALCON() {
82 return 'f';
83 }
84
85 static get PIECES() {
86 return [V.LANCER, V.ARCHER, V.KHESHIG, V.FALCON, V.KING];
87 }
88
89 getPotentialMovesFrom(sq) {
90 switch (this.getPiece(sq[0], sq[1])) {
91 case V.PAWN:
92 return super.getPotentialPawnMoves(sq);
93 case V.LANCER:
94 return super.getPotentialLancerMoves(sq);
95 case V.ARCHER:
96 return super.getPotentialArcherMoves(sq);
97 case V.KHESHIG:
98 return super.getPotentialKheshigMoves(sq);
99 case V.FALCON:
100 return this.getPotentialFalconMoves(sq);
101 case V.KING:
102 return super.getPotentialKingMoves(sq)
103 }
104 return []; //never reached
105 }
106
107 getPotentialFalconMoves(sq) {
108 const onlyMoves = this.getSlideNJumpMoves(
109 sq, V.steps[V.ROOK].concat(V.steps[V.BISHOP]), null, { onlyMove: true });
110 const onlyTakes = this.getSlideNJumpMoves(
111 sq, V.steps[V.KNIGHT], "oneStep", { onlyTake: true });
112 return onlyMoves.concat(onlyTakes);
113 }
114
115 isAttacked(sq, color) {
116 return (
117 super.isAttackedByPawn(sq, color) ||
118 super.isAttackedByLancer(sq, color) ||
119 super.isAttackedByKheshig(sq, color) ||
120 super.isAttackedByArcher(sq, color) ||
121 this.isAttackedByFalcon(sq, color) ||
122 super.isAttackedByKing(sq, color)
123 );
124 }
125
126 isAttackedByFalcon(sq, color) {
127 return this.isAttackedBySlideNJump(
128 sq, color, V.FALCON, V.steps[V.KNIGHT], 1);
129 }
130
131 static get VALUES() {
132 return {
133 p: 1,
134 f: 7,
135 a: 4,
136 h: 7,
137 l: 4,
138 k: 1000
139 };
140 }
141
142 };