Several small improvements + integrate options + first working draft of Cwda
[vchess.git] / client / src / variants / Shinobi.js
index 8afe6fc..e993188 100644 (file)
@@ -12,8 +12,8 @@ export class ShinobiRules extends ChessRules {
   static get NINJA() {
     return 'j';
   }
-  static get SAMURAI() {
-    return 's';
+  static get DRAGON() {
+    return 'd';
   }
   static get MONK() {
     return 'm';
@@ -33,7 +33,7 @@ export class ShinobiRules extends ChessRules {
   static get PIECES() {
     return (
       ChessRules.PIECES
-      .concat([V.CAPTAIN, V.NINJA, V.SAMURAI, V.MONK, V.HORSE, V.LANCE])
+      .concat([V.CAPTAIN, V.NINJA, V.DRAGON, V.MONK, V.HORSE, V.LANCE])
     );
   }
 
@@ -60,7 +60,7 @@ export class ShinobiRules extends ChessRules {
     if (!ChessRules.IsGoodFen(fen)) return false;
     const fenParsed = V.ParseFen(fen);
     // 5) Check reserve
-    if (!fenParsed.reserve || !fenParsed.reserve.match(/^[0-9]{5,5}$/))
+    if (!fenParsed.reserve || !fenParsed.reserve.match(/^[0-2]{5,5}$/))
       return false;
     return true;
   }
@@ -73,13 +73,15 @@ export class ShinobiRules extends ChessRules {
     );
   }
 
-  // In hand initially: ninja, samurai + 2 x monk, horse, lance.
-  static GenRandInitFen(randomness) {
-    const baseFen = ChessRules.GenRandInitFen(Math.min(randomness, 1));
-    return (
-      baseFen.substr(0, 35) + "3CK3 " +
-      "w 0 " + baseFen.substr(48, 2) + " - 11222"
-    );
+  // In hand initially: ninja, dragon, 2 x (monk, horse), lance, pawn.
+  static GenRandInitFen(options) {
+    const baseFen = ChessRules.GenRandInitFen(options);
+    const position = baseFen.substr(0, 43)
+      .replace('Q', 'C')
+      .replace(/B/g, '1')
+      .replace(/R/g, 'L')
+      .replace(/N/g, 'H');
+    return position + " w 0 " + baseFen.substr(48, 2) + " - 11211";
   }
 
   getFen() {
@@ -102,7 +104,7 @@ export class ShinobiRules extends ChessRules {
     this.reserve = {
       w: {
         [V.NINJA]: reserve[0],
-        [V.SAMURAI]: reserve[1],
+        [V.DRAGON]: reserve[1],
         [V.MONK]: reserve[2],
         [V.HORSE]: reserve[3],
         [V.LANCE]: reserve[4]
@@ -121,7 +123,7 @@ export class ShinobiRules extends ChessRules {
   }
 
   static get RESERVE_PIECES() {
-    return [V.NINJA, V.SAMURAI, V.MONK, V.HORSE, V.LANCE];
+    return [V.NINJA, V.DRAGON, V.MONK, V.HORSE, V.LANCE];
   }
 
   getReserveMoves([x, y]) {
@@ -176,7 +178,7 @@ export class ShinobiRules extends ChessRules {
       case V.KING: return this.getPotentialKingMoves(sq);
       case V.CAPTAIN: return this.getPotentialCaptainMoves(sq);
       case V.NINJA: return this.getPotentialNinjaMoves(sq);
-      case V.SAMURAI: return this.getPotentialSamuraiMoves(sq);
+      case V.DRAGON: return this.getPotentialDragonMoves(sq);
     }
     let moves = [];
     switch (piece) {
@@ -194,7 +196,7 @@ export class ShinobiRules extends ChessRules {
         moves = this.getPotentialLanceMoves(sq);
         break;
     }
-    const promotionZone = (this.turn == 'w' ? [0, 1, 2] : [5, 6, 7]);
+    const promotionZone = (this.turn == 'w' ? [0, 1] : [7, 6]);
     const promotedForm = V.MapUnpromoted[piece];
     moves.forEach(m => {
       if (promotionZone.includes(m.end.x)) m.appear[0].p = promotedForm;
@@ -206,37 +208,34 @@ export class ShinobiRules extends ChessRules {
     if (this.getColor(x, y) == 'b') return super.getPotentialKingMoves([x, y]);
     // Clan doesn't castle:
     return super.getSlideNJumpMoves(
-      [x, y],
-      V.steps[V.ROOK].concat(V.steps[V.BISHOP]),
-      "oneStep"
-    );
+      [x, y], V.steps[V.ROOK].concat(V.steps[V.BISHOP]), 1);
   }
 
   getPotentialCaptainMoves(sq) {
     const steps = V.steps[V.ROOK].concat(V.steps[V.BISHOP]);
-    return super.getSlideNJumpMoves(sq, steps, "oneStep");
+    return super.getSlideNJumpMoves(sq, steps, 1);
   }
 
   getPotentialNinjaMoves(sq) {
     return (
       super.getSlideNJumpMoves(sq, V.steps[V.BISHOP])
-      .concat(super.getSlideNJumpMoves(sq, V.steps[V.KNIGHT], "oneStep"))
+      .concat(super.getSlideNJumpMoves(sq, V.steps[V.KNIGHT], 1))
     );
   }
 
-  getPotentialSamuraiMoves(sq) {
+  getPotentialDragonMoves(sq) {
     return (
       super.getSlideNJumpMoves(sq, V.steps[V.ROOK])
-      .concat(super.getSlideNJumpMoves(sq, V.steps[V.KNIGHT], "oneStep"))
+      .concat(super.getSlideNJumpMoves(sq, V.steps[V.BISHOP], 1))
     );
   }
 
   getPotentialMonkMoves(sq) {
-    return super.getSlideNJumpMoves(sq, V.steps[V.BISHOP], "oneStep");
+    return super.getSlideNJumpMoves(sq, V.steps[V.BISHOP], 1);
   }
 
   getPotentialHorseMoves(sq) {
-    return super.getSlideNJumpMoves(sq, [ [-2, 1], [-2, -1] ], "oneStep");
+    return super.getSlideNJumpMoves(sq, [ [-2, 1], [-2, -1] ], 1);
   }
 
   getPotentialLanceMoves(sq) {
@@ -249,9 +248,10 @@ export class ShinobiRules extends ChessRules {
     // Attacked by white:
     return (
       super.isAttackedByKing(sq, 'w') ||
+      super.isAttackedByPawn(sq, 'w') ||
       this.isAttackedByCaptain(sq, 'w') ||
       this.isAttackedByNinja(sq, 'w') ||
-      this.isAttackedBySamurai(sq, 'w') ||
+      this.isAttackedByDragon(sq, 'w') ||
       this.isAttackedByMonk(sq, 'w') ||
       this.isAttackedByHorse(sq, 'w') ||
       this.isAttackedByLance(sq, 'w') ||
@@ -264,7 +264,7 @@ export class ShinobiRules extends ChessRules {
   isAttackedByCaptain(sq, color) {
     const steps = V.steps[V.BISHOP].concat(V.steps[V.ROOK]);
     return (
-      super.isAttackedBySlideNJump(sq, color, V.CAPTAIN, steps, "oneStep")
+      super.isAttackedBySlideNJump(sq, color, V.CAPTAIN, steps, 1)
     );
   }
 
@@ -272,29 +272,29 @@ export class ShinobiRules extends ChessRules {
     return (
       super.isAttackedBySlideNJump(sq, color, V.NINJA, V.steps[V.BISHOP]) ||
       super.isAttackedBySlideNJump(
-        sq, color, V.NINJA, V.steps[V.KNIGHT], "oneStep")
+        sq, color, V.NINJA, V.steps[V.KNIGHT], 1)
     );
   }
 
-  isAttackedBySamurai(sq, color) {
+  isAttackedByDragon(sq, color) {
     return (
-      super.isAttackedBySlideNJump(sq, color, V.SAMURAI, V.steps[V.ROOK]) ||
+      super.isAttackedBySlideNJump(sq, color, V.DRAGON, V.steps[V.ROOK]) ||
       super.isAttackedBySlideNJump(
-        sq, color, V.SAMURAI, V.steps[V.KNIGHT], "oneStep")
+        sq, color, V.DRAGON, V.steps[V.BISHOP], 1)
     );
   }
 
   isAttackedByMonk(sq, color) {
     return (
       super.isAttackedBySlideNJump(
-        sq, color, V.MONK, V.steps[V.BISHOP], "oneStep")
+        sq, color, V.MONK, V.steps[V.BISHOP], 1)
     );
   }
 
   isAttackedByHorse(sq, color) {
     return (
       super.isAttackedBySlideNJump(
-        sq, color, V.HORSE, [ [2, 1], [2, -1] ], "oneStep")
+        sq, color, V.HORSE, [ [2, 1], [2, -1] ], 1)
     );
   }
 
@@ -384,7 +384,7 @@ export class ShinobiRules extends ChessRules {
         {
           c: 4,
           j: 7,
-          s: 8,
+          d: 6,
           m: 2,
           h: 2,
           l: 2
@@ -405,7 +405,12 @@ export class ShinobiRules extends ChessRules {
   }
 
   getNotation(move) {
-    if (move.vanish.length > 0) return super.getNotation(move);
+    if (move.vanish.length > 0) {
+      let notation = super.getNotation(move);
+      if (move.vanish[0].p != V.PAWN && move.appear[0].p != move.vanish[0].p)
+        notation += "=" + move.appear[0].p.toUpperCase();
+      return notation;
+    }
     // Drop:
     const piece =
       move.appear[0].p != V.PAWN ? move.appear[0].p.toUpperCase() : "";