Add legality testing for Lions, so it ca be played with legality testing on.
Cyan markers are now also used in autonomous highlighting, so that double-
moving is triggered: A new move type FirstLeg instructs the marker callback
to use cyan on Lion contact captures. Igui required a special test, to make
XBoard realize the fial square is empty. Implement Lion-capture rules.
Forbid Pawn promotion to Lion: The Lion is skipped during the promotion
sweep (and it was not in the promotion popp anyway). Chu should not suffer
from this, as the piece used as promoted Kylin is not a real Lion (although
it looks like one). King is not considered a protector in Mighty-Lion Chess
This rule was added to allow trading Lions in the late end-game,
to prevent the game from being too drawish.
BlackKing, BlackMan, BlackKnight, BlackRook }
};
+ChessSquare lionArray[2][BOARD_FILES] = {
+ { WhiteRook, WhiteLion, WhiteBishop, WhiteQueen,
+ WhiteKing, WhiteBishop, WhiteKnight, WhiteRook },
+ { BlackRook, BlackLion, BlackBishop, BlackQueen,
+ BlackKing, BlackBishop, BlackKnight, BlackRook }
+};
+
#if (BOARD_FILES>=10)
ChessSquare ShogiArray[2][BOARD_FILES] = {
case VariantSChess: /* S-Chess, should work */
case VariantGrand: /* should work */
case VariantSpartan: /* should work */
+ case VariantLion: /* should work */
break;
}
}
SendToICS(ics_type == ICS_ICC ? "tag result Game in progress\n" : "commit\n");
}
-static int killX = -1, killY = -1; // [HGM] lion: used for passing e.p. capture square to MakeMove
+int killX = -1, killY = -1; // [HGM] lion: used for passing e.p. capture square to MakeMove
void
CoordsToComputerAlgebraic (int rf, int ff, int rt, int ft, char promoChar, char move[7])
else if(promoSweep == WhiteKing && step > 0) promoSweep = BlackKing;
if(!step) step = -1;
} while(PieceToChar(promoSweep) == '.' || PieceToChar(promoSweep) == '~' || promoSweep == pawn ||
- appData.testLegality && promoSweep == king ||
+ appData.testLegality && (promoSweep == king || promoSweep == WhiteLion || promoSweep == BlackLion) ||
IS_SHOGI(gameInfo.variant) && promoSweep != CHUPROMOTED last && last != CHUPROMOTED promoSweep && last != promoSweep);
if(toX >= 0) {
int victim = boards[currentMove][toY][toX];
pieces = SpartanArray;
SetCharTable(pieceToChar, "PNBRQ................K......lwg.....c...h..k");
break;
+ case VariantLion:
+ pieces = lionArray;
+ SetCharTable(pieceToChar, "PNBRQ................LKpnbrq................lk");
+ break;
case VariantFairy:
pieces = fairyArray;
SetCharTable(pieceToChar, "PNBRQFEACWMOHIJGDVLSUKpnbrqfeacwmohijgdvlsuk");
{
typedef char Markers[BOARD_RANKS][BOARD_FILES];
Markers *m = (Markers *) closure;
- if(rf == fromY && ff == fromX)
+ if(rf == fromY && ff == fromX && (killX < 0 && !(rt == rf && ft == ff) || abs(ft-killX) < 2 && abs(rt-killY) < 2))
(*m)[rt][ft] = 1 + (board[rt][ft] != EmptySquare
|| kind == WhiteCapturesEnPassant
- || kind == BlackCapturesEnPassant);
+ || kind == BlackCapturesEnPassant) + 3*(kind == FirstLeg && killX < 0);
else if(flags & F_MANDATORY_CAPTURE && board[rt][ft] != EmptySquare) (*m)[rt][ft] = 3;
}
MarkTargetSquares(1);
if(x == killX && y == killY) killX = killY = -1; else {
killX = x; killY = y; //remeber this square as intermediate
+ MarkTargetSquares(0);
ReportClick("put", x, y); // and inform engine
ReportClick("lift", x, y);
return;
}
piece = board[toY][toX] = (ChessSquare) fromX;
} else {
+ ChessSquare victim;
int i;
if( killX >= 0 && killY >= 0 ) // [HGM] lion: Lion trampled over something
+ victim = board[killY][killX],
board[killY][killX] = EmptySquare,
board[EP_STATUS] = EP_CAPTURE;
- if( board[toY][toX] != EmptySquare )
+ if( board[toY][toX] != EmptySquare ) {
board[EP_STATUS] = EP_CAPTURE;
+ if( (fromX != toX || fromY != toY) && // not igui!
+ (captured == WhiteLion && board[fromY][fromX] != BlackLion ||
+ captured == BlackLion && board[fromY][fromX] != WhiteLion ) ) { // [HGM] lion: Chu Lion-capture rules
+ board[EP_STATUS] = EP_IRON_LION; // non-Lion x Lion: no counter-strike allowed
+ }
+ }
if( board[fromY][fromX] == WhiteLance || board[fromY][fromX] == BlackLance ) {
if( gameInfo.variant != VariantSuper && gameInfo.variant != VariantShogi )
board[BOARD_HEIGHT-1-k][0] = EmptySquare;
}
}
-
}
/* Updates forwardMostMove */
WhitePromotion, WhiteNonPromotion,
BlackPromotion, BlackNonPromotion,
WhiteCapturesEnPassant, BlackCapturesEnPassant,
- WhiteDrop, BlackDrop,
+ WhiteDrop, BlackDrop, FirstLeg,
NormalMove, AmbiguousMove, IllegalMove, ImpossibleMove,
WhiteWins, BlackWins, GameIsDrawn, GameUnfinished,
GNUChessGame, XBoardGame, MoveNumberOne, Open, Close, Nothing,
VariantSChess,
VariantGrand,
VariantSpartan,
+ VariantLion,
VariantUnknown /* Catchall for other unknown variants */
} VariantClass;
"seirawan",\
"grand",\
"spartan",\
+ "lion",\
"unknown" \
}
{ VariantXiangqi, SAME_ROW,135, NULL, (void*) &Pick, "#BFFFFF", NULL, Button, N_("xiangqi (9x10)")},
{ VariantFairy, 0, 135, NULL, (void*) &Pick, "#BFBFBF", NULL, Button, N_("fairy")},
{ VariantCourier, SAME_ROW,135, NULL, (void*) &Pick, "#BFFFBF", NULL, Button, N_("courier (12x8)")},
-{ VariantNormal, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_(" ")}, // dummy, to have good alignment
+//{ VariantNormal, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, Button, N_(" ")}, // dummy, to have good alignment
+{ VariantLion, 0, 135, NULL, (void*) &Pick, "#BFBFBF", NULL, Button, N_("mighty lion")},
{ VariantChu, SAME_ROW, 135, NULL, (void*) &Pick, "#BFFFBF", NULL, Button, N_("chu shogi (12x12)")},
// optional buttons for engine-defined variants
{ VariantUnknown, 0, 135, NULL, (void*) &Pick, "#FFFFFF", NULL, -1, NULL },
}
break;
+ case WhiteLion:
+ case BlackLion:
+ for(rt = rf - 2; rt <= rf + 2; rt++) for(ft = ff - 2; ft <= ff + 2; ft++) {
+ if (rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) continue;
+ if (!(ff == ft && rf == rt) && SameColor(board[rf][ff], board[rt][ft])) continue;
+ callback(board, flags, (rt-rf)*(rt-rf) + (ff-ft)*(ff-ft) < 3 && board[rt][ft] != EmptySquare ? FirstLeg : NormalMove,
+ rf, ff, rt, ft, closure);
+ }
+ break;
+
case WhiteFalcon: // [HGM] wild: for wildcards, self-capture symbolizes move to anywhere
case BlackFalcon:
case WhiteCobra:
if(rFilter >= 0 && rFilter != rt || fFilter >= 0 && fFilter != ft) return; // [HGM] speed: ignore moves with wrong to-square
+ if (board[EP_STATUS] == EP_IRON_LION && (board[rt][ft] == WhiteLion || board[rt][ft] == BlackLion)) return; //[HGM] lion
+
if (!(flags & F_IGNORE_CHECK) ) {
int check, promo = (gameInfo.variant == VariantSpartan && kind == BlackPromotion);
if(promo) {
cl->check++;
xqCheckers[rf][ff] = xqCheckers[EP_STATUS] & 1; // remember who is checking (if status == 1)
}
+ if( board[EP_STATUS] == EP_ROYAL_LION && (board[rt][ft] == WhiteLion || board[rt][ft] == BlackLion)
+ && (gameInfo.variant != VariantLion || board[rf][ff] != WhiteKing && board[rf][ff] != BlackKing) )
+ cl->check++; // [HGM] lion: forbidden counterstrike against Lion equated to putting yourself in check
}
{
CheckTestClosure cl;
ChessSquare king = flags & F_WHITE_ON_MOVE ? WhiteKing : BlackKing;
- ChessSquare captured = EmptySquare;
+ ChessSquare captured = EmptySquare, ep;
/* Suppress warnings on uninitialized variables */
if(gameInfo.variant == VariantXiangqi)
board[rt][ft] = board[rf][ff];
board[rf][ff] = EmptySquare;
}
+ ep = board[EP_STATUS];
+ if( captured == WhiteLion || captured == BlackLion ) { // [HGM] lion: Chu Lion-capture rules
+ ChessSquare victim = killX < 0 ? EmptySquare : board[killY][killX];
+ if( (board[rt][ft] == WhiteLion || board[rt][ft] == BlackLion) && // capturer is Lion
+ (ff - ft > 1 || ft - ff > 1 || rf - rt > 1 || rt - rf > 1) && // captures from a distance
+ (victim == EmptySquare || victim == WhitePawn || victim == BlackPawn) ) // no or worthless 'bridge'
+ board[EP_STATUS] = EP_ROYAL_LION; // on distant Lion x Lion victim must not be pseudo-legally protected
+ }
}
/* For compatibility with ICS wild 9, we scan the board in the
} else {
board[rt][ft] = captured;
}
+ board[EP_STATUS] = ep;
}
return cl.fking < BOARD_RGHT ? cl.check : 1000; // [HGM] atomic: return 1000 if we have no king
#define F_MANDATORY_CAPTURE 0x200
/* Special epfile values. [HGM] positive values are non-reversible moves! */
-#define EP_NONE (-4) /* [HGM] Tricky! order matters: */
-#define EP_UNKNOWN (-1) /* >= EP_UNKNOWN spils rep-draw */
+#define EP_NONE (-6) /* [HGM] Tricky! order matters: */
+#define EP_UNKNOWN (-1) /* >= EP_UNKNOWN spoils rep-draw */
#define EP_CAPTURE (-2) /* <= EP_NONE is reversible move */
#define EP_PAWN_MOVE (-3)
+#define EP_IRON_LION (-4)
+#define EP_ROYAL_LION (-5)
#define EP_REP_DRAW (-15)
#define EP_RULE_DRAW (-14)
#define EP_INSUF_DRAW (-13)
int rf, int ff, int rt, int ft,
int promoChar, char out[MOVE_LEN]));
-extern int quickFlag;
+extern int quickFlag, killX, killY;