Esempio n. 1
0
/* CompleteTour(when_visited, NextMoveNum, AtR, AtC)
 * 	attempts to complete the partial tour in when_visited.
 *
 * Inputs:
 *	when_visited	holds the partial tour
 *	AtMoveNumber	one more than the number of squares already visited
 *	AtR, AtC	the next position to try in the partial tour
 *
 * Returns:	1 if the partial tour can be completed to a full tour.
 *		0 if no complete tour starts with this partial tour.
 *
 * Outputs:
 *	when_visited holds complete tour if 1 is returned, but
 *	is restored to the partial tour from before call, if 0 returned.
 */
bool
CompleteTour(PartialTour when_visited, 
	int AtMoveNumber, 	int AtR, int AtC)
{
    /* Try adding the new move to the partial tour.
     * If tour is still not complete, try all possible directions for
     * continuing the tour.
     * If no direction results in complete tour, retract the move
     * and return 0 for failure.
     */
    
    /* The pair (RowChange[i], ColChange[i]) is one of the eight possible
     * directions for the knight to move.
     * A knight at (r,c) can move to (r+RowChange[i], c+ColChange[i]),
     * if that destination is on the board and not already used.
     */
    static const int RowChange[8] = { 2,  1, -1, -2, -2, -1,  1,  2};
    static const int ColChange[8] = { 1,  2,  2,  1, -1, -2, -2, -1};

    int direction; /* loop counter for the 8 directions a knight can move */
    
    if (! OnBoard(AtR,AtC) || when_visited[AtR][AtC]!=NotVisited)
    	return 0;	/* can't visit this square, so no legal tour */
    
    /* visit the square */
    when_visited[AtR][AtC] = AtMoveNumber;
    if (AtMoveNumber >= NumSquares)
    	return 1;	/* partial tour is already complete */
    
    /* Try adding a move and completing the new partial tour. */
    for (direction=0; direction<8; direction++)
    {   if (CompleteTour(when_visited,AtMoveNumber+1, 
		AtR+RowChange[direction], AtC+ColChange[direction]))
	    return 1;	/* tour completed successfully */
    }
    
    /* None of the eight directions led to a complete tour with this
     *	    	move added, so backtrack. 
     */ 
    when_visited[AtR][AtC] = NotVisited;
    return 0;
}
Esempio n. 2
0
/* Gets all moves of a certain king or knight */
void getDiscMoves(Board *brd, MoveList *list, int square) {

    int piece, toSquare, dir, j;

    piece = brd->piecesBySquare[square];

    for(j = 0; j < numOfDirections[piece]; j++) {
        dir = directionsOfPieces[piece][j];
        toSquare = square + dir;

        if(OnBoard(toSquare)) {

            if(brd->piecesBySquare[toSquare] != noPiece) {
                if( pieceCol[brd->piecesBySquare[toSquare]] == (brd->side ^ 1)) {
                    addMove(brd, square, toSquare, brd->piecesBySquare[toSquare], noPiece , 0, list);
                }
                continue;
            }
            addMove(brd, square, toSquare, noPiece, noPiece , 0, list);
        }
    }
}
Esempio n. 3
0
/* main
 *	looks for a knight's tour, and prints the tour if it finds one,
 *	as described in the abstract at the beginning of the file.
 *
 *	The main procedure has no inputs, outputs, or return values.
 *	All parameters are set by compile-time constants.
 *	The only side effect is the printing of the solution,
 *	or a message saying that no tour exists.
 */
int main(void)
{
    int row,col;	/* row and column loop indices */
    PartialTour when_visited;

    /* check that the compile-time constants are all legal */
    assert(NumRows>=1);
    assert(NumCols>=1);
    assert(OnBoard(StartRow,StartCol));
    
    /* clear the when_visited array to get an empty partial tour */
    for (row=0; row<NumRows; row++)
    	for(col=0; col<NumCols; col++)
	    when_visited[row][col]=NotVisited;

    if (CompleteTour(when_visited, 1, StartRow,StartCol))
    {	/* print the solution found */
	for (row=0; row<NumRows; row++)
    	{   for(col=0; col<NumCols; col++)
		printf("+---");
	    printf("+\n");
	    for(col=0; col<NumCols; col++)
	    	printf("|%3d",when_visited[row][col]);
	    printf("|\n");
	}
	for(col=0; col<NumCols; col++)
	    printf("+---");
	printf("+\n");
	return 0;
    }
    
    printf("No knight's tour for %d x %d board, starting at (%d,%d)\n",
    		NumRows, NumCols, StartRow, StartCol);
    printf("Possible positions range from (0,0) to (%d,%d)\n",
		NumRows-1, NumCols-1);
    return 1;
}
Esempio n. 4
0
Move Notation::value(const Board & board, ColorType side, InputFormat format, const string &image) 
{
    int rank = 0;
    int file = 0;

    PieceType piece = Empty;
    PieceType promotion = Empty;
    Square dest = InvalidSquare, start = InvalidSquare;
    int capture = 0;

    stringstream s(image);
    string::const_iterator it = image.begin();
    int i = 0;
    while (it != image.end() && isspace(*it)) {
        it++;
        i++;
    }
    if (it == image.end() || !isalpha(*it)) return NullMove;
    string img(image,i); // string w/o leading spaces
    ASSERT(img.length());
    it = img.begin();
    if (*it == 'O' || *it == '0') {
       // castling, we presume
       return parseCastling(board, side, img);
    } else if (format == WB_IN) {
       if (img.length() < 4) return NullMove;
       Square start = SquareValue(img.substr(0,2));
       if (!OnBoard(start)) return NullMove;
       Square dest = SquareValue(img.substr(2,2));
       if (!OnBoard(dest)) return NullMove;
       PieceType promotion = Empty;
       if (img.length() > 4) {
          promotion = PieceCharValue(toupper(img[4]));
       }
       return CreateMove(board,start,dest,promotion);
    }
    int have_start = 0;
    if (isupper(*it)) {
       piece = PieceCharValue(*it);
       it++;
    }
    else {
       piece = Pawn;
       if ((it+1) != img.end()) {
          char next = *it;
          file = next-'a'+1;
          if (file < 1 || file > 8) return NullMove;
          char next2 = *(it+1);
          if (next2 == 'x' || is_file(next2)) {
             // allow "dc4" as in Informant, instead of dxc4
             it++;
             capture = 1;
          }
          else if (isdigit(next2) && img.length()>2) {
             char next3 = *(it+2);
             if ((next3 == 'x' || next3 == '-') && img.length()>=5) {
                // long algebraic notation
                have_start++;
                start = SquareValue(next,next2);
                if (start == InvalidSquare) return NullMove;
                it+=3; // point to dest
                piece = TypeOfPiece(board[start]);
             }
          }
       }
    }
    if (piece == Empty) {
       return NullMove;
    }
    if (piece != Pawn && !have_start && it != img.end()) {
       char next = *it;
       char next2 = '\0';
       if (it + 1 != img.end()) next2 = *(it+1);
       if (is_file(next) && isdigit(next2) && img.length()>=5) {
          // long algebraic notation, or a SAN move like Qd1d3
          start = SquareValue(next,next2);
          if (IsInvalid(start)) return NullMove;
          it+=2;
          have_start++;
       }
       // also look for disambiguating rank, e.g. '2' in "N2e4".
       else if (isdigit(next)) {
          rank = next - '0';
          if (rank < 1 || rank > 8) return NullMove;
          it++;
       }
       else if (is_file(next) && isalpha(next2)) {
          // disamiguating rank, e.g. "Rfd1"
          file = next - 'a' + 1;
          if (file < 1 || file > 8) return NullMove;
          it++;
       }
    }

    if (it != img.end() && *it == 'x') {
       capture = 1;
       it++;
    }
    if (it != img.end() && (it+1) != img.end()) {
       // remainder of move should be a square identifier, e.g. "g7"
       dest = SquareValue(*it,*(it+1));
       it += 2;
    }
    if (IsInvalid(dest)) {
       return NullMove;
    }
    if (it != img.end() && *it == '=') {
       it++;
       if (it == img.end()) {
          return NullMove;
       } else {
          promotion = PieceCharValue(*it);
          if (piece != Pawn || promotion == Empty)
             return NullMove;
          it++;
       }
    }
    else if (piece == Pawn && it != img.end() && isupper(*it)) {
       // Quite a few "PGN" files have a8Q instead of a8=Q.
       promotion = PieceCharValue(*it);
       if (promotion == Empty || Rank(dest,side) != 8)
          return NullMove;
    } else if (piece == Pawn && Rank(dest,side) == 8) {
       // promotion but no piece specified, treat as error
       return NullMove;
    }

    // Informant does not use "x" for captures.  Assume that if the destination
    // is occupied, this is a capture move.
    if (board[dest] != EmptyPiece) {
       capture = 1;
    }
    // Do a sanity check on capture moves:
    if (capture && !IsEmptyPiece(board[dest]) && PieceColor(board[dest]) == board.sideToMove()) {
       return NullMove;
    }

    // Ok, now we need to figure out where the start square is. For pawn
    // moves this is implicit.

    int dups = 0;

    if (!have_start) {
       if (capture && piece == Pawn && IsEmptyPiece(board[dest]) &&
           Rank(dest,board.sideToMove()) != 8) {
          // en passant capture, special case
          int start_rank = (board.sideToMove() == White) ?
             Rank(dest,White) - 1 :
             Rank(dest,White) + 1;

          start = MakeSquare(file, start_rank, White);
          dups = 1;
       }
       else if (piece == Pawn && board[dest] == EmptyPiece) {
          start = MakeSquare(file,Rank(dest,board.sideToMove())-1,board.sideToMove());
          if (board[start] == EmptyPiece && Rank(dest,board.sideToMove())==4) {
             start = MakeSquare(file,Rank(dest,board.sideToMove())-2,board.sideToMove());
          }
          if (board[start] == EmptyPiece) return NullMove;
          dups = 1;
       }
       else {
          Bitboard attacks = board.calcAttacks(dest,side);
          Square maybe;
          while (attacks.iterate(maybe)) {
             if (TypeOfPiece(board[maybe]) == piece &&
                 PieceColor(board[maybe]) == board.sideToMove()) {
                if (file && File(maybe) != file)
                   continue;
                if (rank && Rank(maybe,White) != rank)
                   continue;
                if (PieceColor(board[maybe]) == board.sideToMove()) {
                   // Possible move to this square.  Make sure it is legal.
                   Board board_copy(board);
                   Move emove = CreateMove(board,maybe,dest,
                                           promotion);
                   board_copy.doMove(emove);
                   if (!board_copy.anyAttacks(
                          board_copy.kingSquare(board_copy.oppositeSide()),
                          board_copy.sideToMove())) {
                      ++dups;
                      start = maybe;
                   }
                }
             }
          }
       }
    }
    if (dups == 1 || have_start) {
       if (start == InvalidSquare || board[start] == EmptyPiece)
          return NullMove;
       else
          return CreateMove(board, start, dest, promotion);
    }
    else                                           // ambiguous move
       return NullMove;
}
Esempio n. 5
0
int BoardIO::readFEN(Board &board, const string &buf)
{
   board.reset();
   for (int i = 0; i < 64; i++)
   {
      board.contents[i] = EmptyPiece;
   }

   char c;
   string::const_iterator bp = buf.begin();
   size_t first = buf.find_first_not_of(" \t");
   if (first != string::npos) {
      bp += first;
   }
   for (int line = 0; line < 8; line++)
   {
      int sqval = 56-line*8;
      while ((c = *bp) != ' ' && c != '/')
      {
         Piece piece;
         if (isdigit(c))
         {
            sqval += (*bp - '0');
            bp++;
         }
         else if (isalnum(c))
         {
            if (!OnBoard(sqval))
            {
	      return 0;
            }
            switch (c)
            {
            case 'p': piece = BlackPawn;
               break;
            case 'n': piece = BlackKnight;
               break;
            case 'b': piece = BlackBishop;
               break;
            case 'r': piece = BlackRook;
               break;
            case 'q': piece = BlackQueen;
               break;
            case 'k': piece = BlackKing;
               break;
            case 'P': piece = WhitePawn;
               break;
            case 'N': piece = WhiteKnight;
               break;
            case 'B': piece = WhiteBishop;
               break;
            case 'R': piece = WhiteRook;
               break;
            case 'Q': piece = WhiteQueen;
               break;
            case 'K': piece = WhiteKing;
               break;
            default:
	      return 0;
            }
            board.contents[sqval] = piece;
            sqval++;
            bp++;
         }
         else // not a letter or a digit
         {
	   return 0;
         }
      }
      if (c=='/') ++bp;  // skip delimiter
   }
   while (bp != buf.end() && isspace(*bp)) bp++;
   if (bp == buf.end()) return 0;
   if (toupper(*bp) == 'W')
      board.side = White;
   else if (toupper(*bp) == 'B')
      board.side = Black;
   else
   {
     return 0;
   }
   bp++;
   while (bp != buf.end() && isspace(*bp)) bp++;
   if (bp == buf.end()) return 0;
   c = *bp;
   if (c == '-')
   {
      // TBD: should try to infer if castling has occurred?
      board.state.castleStatus[White] = 
      board.state.castleStatus[Black] = CantCastleEitherSide;
      bp++;
   }
   else
   {
      int k = 0;
      for (; bp != buf.end() && !isspace(*bp); bp++)
      {
         if (*bp == 'K')
            k += 1;
         else if (*bp == 'Q')
            k += 2;
         else if (*bp == 'k')
            k += 4;
         else if (*bp == 'q')
            k += 8;
         else
         {
	   return 0;
         }
      }
      static const CastleType vals[4] = 
      { CantCastleEitherSide, CanCastleKSide,
         CanCastleQSide, CanCastleEitherSide};
      board.state.castleStatus[White] = vals[k % 4];
      board.state.castleStatus[Black] = vals[k / 4];
   }
   board.setSecondaryVars();
   while (isspace(*bp)) bp++;
   if (bp == buf.end()) return 0;
   c = *bp;
   if (c == '-')
   {
     board.state.enPassantSq = InvalidSquare;
   }
   else if (isalpha(c))
   {
      char sqbuf[2];
      sqbuf[0] = *bp++;
      if (bp == buf.end()) return 0;
      sqbuf[1] = *bp++;
      Square epsq = SquareValue(sqbuf);
      if (epsq == InvalidSquare)
      {
         return 0;
      }
      board.state.enPassantSq = InvalidSquare;
      Square ep_candidate =  
        SquareValue(sqbuf) - (8 * Direction[board.sideToMove()]);
      // only actually set the e.p. square on the board if an en-passant capture
      // is truly possible:
      if (TEST_MASK(Attacks::ep_mask[File(ep_candidate)-1][(int)board.oppositeSide()],
		  board.pawn_bits[board.sideToMove()])) {
         board.state.enPassantSq = ep_candidate;
	 // re-calc hash code since ep has changed
	 board.state.hashCode = BoardHash::hashCode(board);
      }
   }
   else
   {
     return 0;
   }
   board.repList[board.state.moveCount++] = board.hashCode();

   return 1;
}
Esempio n. 6
0
/* This function checks if the current square, sq, is threatened by "side"
       The functions starts from the square, sq, and goes in the direction of all the pieces.
       For instance, it will go into all diagonals and see if a bishop which belongs to "side" is there. */
int isSquareThreat(const Board *brd, const int square, const int side) {

	int piece,index,temp,dir;

	/* pawns */
	if(side == WHITE) {
		if(brd->piecesBySquare[square-11] == wPawn || brd->piecesBySquare[square-9] == wPawn) {
			return TRUE;
		}
	} else {
		if(brd->piecesBySquare[square+11] == bPawn || brd->piecesBySquare[square+9] == bPawn) {
			return TRUE;
		}
	}

	/* knights */
	for(index = 0; index < 8; ++index) {
		piece = brd->piecesBySquare[square + directionsOfPieces[3][index]];
		if( (side == WHITE && piece == wKnight) || (side == BLACK && piece == bKnight) ) {
			return TRUE;
		}
	}

	/* rooks, queens */
	for(index = 0; index < 4; ++index) {
		dir = directionsOfPieces[2][index];
		temp = square + dir;
		piece = brd->piecesBySquare[temp];
		while(OnBoard(temp)) {
			if(piece != noPiece) {
				if( (((piece == wQueen) || (piece == wRook)) && side == WHITE) ||
                                (((piece == bQueen) || (piece == bRook)) && side == BLACK) ) return TRUE;
                break;
			}
			temp += dir;
			piece = brd->piecesBySquare[temp];
		}
	}

	/* bishops, queens */
	for(index = 0; index < 4; ++index) {
		dir = directionsOfPieces[4][index];
		temp = square + dir;
		piece = brd->piecesBySquare[temp];
		while(OnBoard(temp)) {
			if(piece != noPiece) {
				if( (((piece == wQueen) || (piece == wBishop)) && side == WHITE) ||
                                (((piece == bQueen) || (piece == bBishop)) && side == BLACK) ) return TRUE;
                break;

			}
			temp += dir;
			piece = brd->piecesBySquare[temp];
		}
	}

	/* kings */
	for(index = 0; index < 8; ++index) {
		piece = brd->piecesBySquare[square + directionsOfPieces[6][index]];
		if( (piece == wKing && side == WHITE) ||
                               (piece == bKing && side == BLACK) )
					return TRUE;
    }

	return FALSE;

}
Esempio n. 7
0
/* Gets all of a specified pawn's moves */
void getPawnMoves(Board *brd, MoveList *list, int square) {

    if(pieceCol[brd->piecesBySquare[square]] == WHITE) {

        if(brd->piecesBySquare[square + 10] == noPiece) {
            if(rows[square + 10] == R8) {
               addMove(brd, square, square + 10, noPiece, wQueen, 0, list);
               addMove(brd, square, square + 10, noPiece, wRook, 0, list);
               addMove(brd, square, square + 10, noPiece, wBishop, 0, list);
               addMove(brd, square, square + 10, noPiece, wKnight, 0, list);
            } else {
               addMove(brd, square, square + 10, noPiece, noPiece, 0, list);
            }
        }

        if( (OnBoard(square + 9)) && pieceCol[brd->piecesBySquare[square + 9]] == BLACK) {
            if(rows[square + 9] == R8) {
               addMove(brd, square, square + 9, brd->piecesBySquare[square + 9], wQueen, 0, list);
               addMove(brd, square, square + 9, brd->piecesBySquare[square + 9], wRook, 0, list);
               addMove(brd, square, square + 9, brd->piecesBySquare[square + 9], wBishop, 0, list);
               addMove(brd, square, square + 9, brd->piecesBySquare[square + 9], wKnight, 0, list);
            } else {
               addMove(brd, square, square + 9, brd->piecesBySquare[square + 9], noPiece, 0, list);
            }
        }

        if( (OnBoard(square + 11)) && pieceCol[brd->piecesBySquare[square + 11]] == BLACK) {
            if(rows[square + 11] == R8) {
               addMove(brd, square, square + 11, brd->piecesBySquare[square + 11], wQueen, 0, list);
               addMove(brd, square, square + 11, brd->piecesBySquare[square + 11], wRook, 0, list);
               addMove(brd, square, square + 11, brd->piecesBySquare[square + 11], wBishop, 0, list);
               addMove(brd, square, square + 11, brd->piecesBySquare[square + 11], wKnight, 0, list);
            } else {
               addMove(brd, square, square + 11, brd->piecesBySquare[square + 11], noPiece, 0, list);
            }
        }

    } else { /* same, but for black */

        if(brd->piecesBySquare[square - 10] == noPiece) {
            if(rows[square - 10] == R8) {
                addMove(brd, square, square - 10, noPiece, wQueen, 0,  list);
                addMove(brd, square, square - 10, noPiece, wRook, 0, list);
                addMove(brd, square, square - 10, noPiece, wBishop, 0, list);
                addMove(brd, square, square - 10, noPiece, wKnight, 0, list);
            } else {
                addMove(brd, square, square - 10, noPiece, noPiece, 0, list);
            }
        }

        if( (OnBoard(square - 9)) && pieceCol[brd->piecesBySquare[square - 9]] == WHITE) {
            if(rows[square - 9] == R8) {
                addMove(brd, square, square - 9, brd->piecesBySquare[square - 9], wQueen, 0, list);
                addMove(brd, square, square - 9, brd->piecesBySquare[square - 9], wRook, 0, list);
                addMove(brd, square, square - 9, brd->piecesBySquare[square - 9], wBishop, 0, list);
                addMove(brd, square, square - 9, brd->piecesBySquare[square - 9], wKnight, 0, list);
            } else {
                addMove(brd, square, square - 9, brd->piecesBySquare[square - 9], noPiece, 0, list);
            }
        }

        if( (OnBoard(square - 11)) && pieceCol[brd->piecesBySquare[square - 11]] == WHITE) {
            if(rows[square - 11] == R8) {
                addMove(brd, square, square - 11, brd->piecesBySquare[square - 11], wQueen, 0, list);
                addMove(brd, square, square - 11, brd->piecesBySquare[square - 11], wRook, 0, list);
                addMove(brd, square, square - 11, brd->piecesBySquare[square - 11], wBishop, 0, list);
                addMove(brd, square, square - 11, brd->piecesBySquare[square - 11], wKnight, 0, list);
            } else {
                addMove(brd, square, square - 11, brd->piecesBySquare[square - 11], noPiece, 0, list);
            }
        }

    }

}