summaryrefslogtreecommitdiff
path: root/src/ics.c
diff options
context:
space:
mode:
authorScott Gasch <[email protected]>2016-06-01 18:58:58 -0700
committerScott Gasch <[email protected]>2016-06-01 18:58:58 -0700
commit3fd43cd5fcb22bb65bf2a92a25d95d801b11c9e0 (patch)
tree9b6443235d16ba17f094a1a1c7ae53d2bcb9267b /src/ics.c
Initial checkin for typhoon chess engine.
Diffstat (limited to 'src/ics.c')
-rwxr-xr-xsrc/ics.c272
1 files changed, 272 insertions, 0 deletions
diff --git a/src/ics.c b/src/ics.c
new file mode 100755
index 0000000..5a8d2cd
--- /dev/null
+++ b/src/ics.c
@@ -0,0 +1,272 @@
+/**
+
+Copyright (c) Scott Gasch
+
+Module Name:
+
+ ics.c
+
+Abstract:
+
+ Routines to convert internal move structs into ICS (d2d4 style)
+ move strings and vice versa.
+
+ See also san.c.
+
+Author:
+
+ Scott Gasch ([email protected]) 16 May 2004
+
+Revision History:
+
+ $Id: ics.c 345 2007-12-02 22:56:42Z scott $
+
+**/
+
+#include "chess.h"
+
+
+CHAR *
+MoveToIcs(MOVE mv)
+/**
+
+Routine description:
+
+ Convert a MOVE into an ICS ("d2d4" style) string. Note: not
+ thread safe.
+
+Parameters:
+
+ MOVE mv : the move to convert
+
+Return value:
+
+ CHAR *
+
+**/
+{
+ static char szTextMove[10];
+ char *p = szTextMove;
+
+ if (0 == mv.uMove)
+ {
+ return(NULL);
+ }
+ memset(szTextMove, 0, sizeof(szTextMove));
+
+ ASSERT(IS_ON_BOARD(mv.cFrom));
+ ASSERT(IS_ON_BOARD(mv.cTo));
+ *p++ = FILE(mv.cFrom) + 'a';
+ *p++ = RANK(mv.cFrom) + '0';
+ *p++ = FILE(mv.cTo) + 'a';
+ *p++ = RANK(mv.cTo) + '0';
+
+ if (mv.pPromoted)
+ {
+ if (IS_QUEEN(mv.pPromoted))
+ {
+ *p++ = 'Q';
+ }
+ else if (IS_ROOK(mv.pPromoted))
+ {
+ *p++ = 'R';
+ }
+ else if (IS_BISHOP(mv.pPromoted))
+ {
+ *p++ = 'B';
+ }
+ else if (IS_KNIGHT(mv.pPromoted))
+ {
+ *p++ = 'N';
+ }
+ else
+ {
+ ASSERT(FALSE);
+ return(NULL);
+ }
+ }
+ *p = 0;
+ return(szTextMove);
+}
+
+
+MOVE
+ParseMoveIcs(CHAR *szInput, POSITION *pos)
+/**
+
+Routine description:
+
+ Parse a move in ICS format (i.e. "d2d4") and create a MOVE struct.
+
+Parameters:
+
+ CHAR *szInput,
+ POSITION *pos
+
+Return value:
+
+ MOVE
+
+**/
+{
+ MOVE mv;
+ COOR cFrom, cTo;
+ PIECE pMoved, pCaptured, pProm;
+ CHAR *szMoveText = StripMove(szInput);
+ static CHAR *szPieces = "nbrq";
+ CHAR *p;
+
+ mv.uMove = 0;
+ if (InCheck(pos, pos->uToMove))
+ {
+ mv.bvFlags |= MOVE_FLAG_ESCAPING_CHECK;
+ }
+
+ cFrom = FILE_RANK_TO_COOR((tolower(szMoveText[0]) - 'a'),
+ (tolower(szMoveText[1]) - '0'));
+ cTo = FILE_RANK_TO_COOR((tolower(szMoveText[2]) - 'a'),
+ (tolower(szMoveText[3]) - '0'));
+
+ //
+ // check for castling moves in o-o style notation.
+ //
+ if ((!STRCMPI(szMoveText, "OO")) ||
+ (!STRCMPI(szMoveText, "00")) ||
+ (((E1 == cFrom) && (G1 == cTo)) &&
+ (pos->rgSquare[E1].pPiece == WHITE_KING)) ||
+ (((E8 == cFrom) && (G8 == cTo)) &&
+ (pos->rgSquare[E8].pPiece == BLACK_KING)))
+ {
+ if (pos->uToMove == WHITE)
+ {
+ if (pos->bvCastleInfo & CASTLE_WHITE_SHORT)
+ {
+ ASSERT(pos->rgSquare[E1].pPiece == WHITE_KING);
+ mv.uMove =
+ MAKE_MOVE(E1, G1, WHITE_KING, 0, 0, MOVE_FLAG_SPECIAL);
+ }
+ }
+ else // black to move
+ {
+ if (pos->bvCastleInfo & CASTLE_BLACK_SHORT)
+ {
+ ASSERT(pos->rgSquare[E8].pPiece == BLACK_KING);
+ mv.uMove =
+ MAKE_MOVE(E8, G8, BLACK_KING, 0, 0, MOVE_FLAG_SPECIAL);
+ }
+ }
+ goto done;
+ }
+ else if ((!STRCMPI(szMoveText, "OOO")) ||
+ (!STRCMPI(szMoveText, "000")) ||
+ (((E1 == cFrom) && (C1 == cTo)) &&
+ (pos->rgSquare[E1].pPiece == WHITE_KING)) ||
+ (((E8 == cFrom) && (C8 == cTo)) &&
+ (pos->rgSquare[E8].pPiece == BLACK_KING)))
+ {
+ if (pos->uToMove == WHITE)
+ {
+ if (pos->bvCastleInfo & CASTLE_WHITE_LONG)
+ {
+ ASSERT(pos->rgSquare[E1].pPiece == WHITE_KING);
+ mv.uMove =
+ MAKE_MOVE(E1, C1, WHITE_KING, 0, 0, MOVE_FLAG_SPECIAL);
+ }
+ }
+ else // black to move
+ {
+ if (pos->bvCastleInfo & CASTLE_BLACK_LONG)
+ {
+ ASSERT(pos->rgSquare[E8].pPiece == BLACK_KING);
+ mv.uMove =
+ MAKE_MOVE(E8, C8, BLACK_KING, 0, 0, MOVE_FLAG_SPECIAL);
+ }
+ }
+ goto done;
+ }
+
+ if ((!IS_ON_BOARD(cFrom)) ||
+ (!IS_ON_BOARD(cTo)))
+ {
+ goto illegal;
+ }
+
+ pMoved = pos->rgSquare[cFrom].pPiece;
+ if ((IS_EMPTY(pMoved)) || (GET_COLOR(pMoved) != pos->uToMove))
+ {
+ goto illegal;
+ }
+
+ pCaptured = pos->rgSquare[cTo].pPiece;
+ if ((pCaptured != 0) && (GET_COLOR(pCaptured) == pos->uToMove))
+ {
+ goto illegal;
+ }
+
+ mv.cFrom = cFrom;
+ mv.cTo = cTo;
+ mv.pMoved = pMoved;
+ mv.pCaptured = pCaptured;
+
+ if (IS_PAWN(pMoved))
+ {
+ //
+ // Promotion
+ //
+ if ((szMoveText[4] != 0) && (szMoveText[4] != '\n'))
+ {
+ if (IS_PAWN(mv.pMoved))
+ {
+ if (((BLACK == GET_COLOR(mv.pMoved)) && (RANK(cTo) != 1)) ||
+ ((WHITE == GET_COLOR(mv.pMoved)) && (RANK(cTo) != 8)))
+ {
+ goto illegal;
+ }
+ }
+ p = strchr(szPieces, tolower(szMoveText[4]));
+ if (NULL == p)
+ {
+ goto illegal;
+ }
+ pProm = (PIECE)((BYTE *)p - (BYTE *)szPieces);
+ pProm += 2;
+ pProm <<= 1;
+ pProm |= pos->uToMove;
+ mv.pPromoted = pProm;
+ mv.bvFlags = MOVE_FLAG_SPECIAL;
+ }
+
+ //
+ // Handle en passant captures.
+ //
+ if (cTo == pos->cEpSquare)
+ {
+ mv.bvFlags = MOVE_FLAG_SPECIAL;
+ if (WHITE == pos->uToMove)
+ {
+ mv.pCaptured = pos->rgSquare[cTo + 0x10].pPiece;
+ ASSERT(mv.pCaptured == BLACK_PAWN);
+ }
+ else
+ {
+ mv.pCaptured = pos->rgSquare[cTo - 0x10].pPiece;
+ ASSERT(mv.pCaptured == WHITE_PAWN);
+ }
+ }
+
+ //
+ // Handle double jumps.
+ //
+ if (abs(RANK(cTo) - RANK(cFrom)) > 1)
+ {
+ mv.bvFlags = MOVE_FLAG_SPECIAL;
+ }
+ }
+
+ done:
+ return(mv);
+
+ illegal:
+ mv.uMove = 0;
+ return(mv);
+}