/* *Validates a move in a given direction from current position */ int validateMove(BoardNode currentBoard, int moveRow, int moveCol, int currRow, int currCol, int distance) { if(distance > MAXDISTOCHECK) { return 1;} if(checkBounds(currRow+moveRow,currCol+moveCol)) { switch(distance) { case NEIGHDIS: if(getButtonStatus(currentBoard,currRow+moveRow,currCol+moveCol) == ALIVE) { if(validateMove(currentBoard,moveRow,moveCol,currRow+moveRow,currCol+moveCol,++distance)) { return 1; } } break; case MAXDISTOCHECK: if(getButtonStatus(currentBoard,currRow+moveRow,currCol+moveCol) == DEAD) { if(validateMove(currentBoard,moveRow,moveCol,currRow+moveRow,currCol+moveCol,++distance)) { return 1; } } break; default: return 0; } } return 0; }
/* * Calls functions required for generating moves depending on program mode */ int generatePossibleMove(BoardNode currentBoard) { int row, col; for(row = 0; row < MAXROW; row++) { for(col = 0; col < MAXCOL; col++) { if(getButtonStatus(currentBoard,row,col) == ALIVE) { if(validateMove(currentBoard,DONTMV,MVRIGHT,row, col,NEIGHDIS)) { if(getMode() == ZHASH) { generateUniqueBoardHash(currentBoard,DONTMV,MVRIGHT,row,col); //!extended Zobrist Hash } else if(getMode() == BHASH) { generateUniqueBoardBitHash(currentBoard,DONTMV,MVRIGHT,row,col); //! Extended bit Hash } else { generateUniqueBoardWithMove(currentBoard,DONTMV,MVRIGHT,row,col); //!Basic } } if(validateMove(currentBoard,DONTMV,MVLEFT,row, col,NEIGHDIS)) { if(getMode() == ZHASH) { generateUniqueBoardHash(currentBoard,DONTMV,MVLEFT,row,col); //!extended Zobrist Hash } else if(getMode() == BHASH) { generateUniqueBoardBitHash(currentBoard,DONTMV,MVLEFT,row,col); //! Extended bit Hash } else { generateUniqueBoardWithMove(currentBoard,DONTMV,MVLEFT,row,col); //!Basic } } if(validateMove(currentBoard,MVUP,DONTMV,row,col,NEIGHDIS)) { if(getMode() == ZHASH) { generateUniqueBoardHash(currentBoard,MVUP,DONTMV,row,col); //!extended Zobrist Hash } else if(getMode() == BHASH) { generateUniqueBoardBitHash(currentBoard,MVUP,DONTMV,row,col); //! Extended bit Hash } else { generateUniqueBoardWithMove(currentBoard,MVUP,DONTMV,row,col); //!Basic } } if(getMode() == LINEAR) { if(validateMove(currentBoard,MVDOWN,DONTMV,row,col,NEIGHDIS)) { generateUniqueBoardWithMove(currentBoard,MVDOWN,DONTMV,row,col); //!Basic move down } } } } } return 1; }
// verify is there draw or mat void Board::verifyState() { if ( matState() || drawState() ) return; #ifndef NDEBUG Board board0(*this); #endif MovesGenerator mg(*this); bool found = false; for ( ; !found; ) { const Move & m = mg.move(); if ( !m ) break; if ( validateMove(m) ) found = true; } if ( !found ) { setNoMoves(); // update move's state because it is last one if ( halfmovesCounter_ > 0 ) { UndoInfo & undo = undoInfo(halfmovesCounter_-1); undo.state_ = state_; } } }
bool ChessBoard::checkIfCanMoveTo( PieceColor color, int to_x, int to_y ) { std::vector<Piece*> toCheck; if( color == WHITE ) { toCheck = whitePieces; } else { toCheck = blackPieces; } for( std::vector<Piece*>::iterator it = toCheck.begin(); it != toCheck.end(); ++it ) { if( (*it)->inPlay ) { Move m((*it)->x, (*it)->y, to_x, to_y); Piece* piece = getPiece( (*it)->x, (*it)->y ); if( piece->type == QUEEN ) { std::cout << "Checking if queen on: x: " << piece->x << " y: " <<piece->y << ". can move to x: " << to_x << " y: " << to_y << "\n"; } if( validateMove( m ) ){ return true; } } } if( color == WHITE ) std::cout << "white cant move to: "; else std::cout << "black cant move to: "; std::cout << " x: "<< to_x << " y: " << to_y << "\n"; return false; }
/** When a target square is clicked, this event is prompted * (it is attached to every enabled target square button's onClick). * We execute the given move for the selected chess piece and clicked target using the * logic layer and mark them as possible targets on board. */ void onTargetClick(GuiButton* button) { // Each target button caches a game square in its extent, so it can access the logic layer GameSquare* gameSquare = (GameSquare*)button->generalProperties.extent; if (NULL == gameSquare) return; // Avoid null extents GameControl* gameControl = gameSquare->gameControl; int guiStartX = boardRowIndexToGuiRowIndex(gameControl->selectedSquare->x); int guiTargetX = boardRowIndexToGuiRowIndex(gameSquare->x); // Build the move // Make sure to abort clicks on illegal moves Position initPos = { guiStartX, gameControl->selectedSquare->y }; Position nextPos = { guiTargetX, gameSquare->y }; Move* move = createMove(&initPos, &nextPos); if ((g_memError) || (NULL == move)) return; // If a pawn have reached the other edge, we have a promotion move. // Show the promotion dialog and wait for results. // Since this event can only be prompted by a player, we can count on the isBlackPlayerEditable property if (isSquareOnOppositeEdge(gameControl->isBlackPlayerEditable, nextPos.x) && isSquareOccupiedByPawn(gameControl->board, gameControl->isBlackPlayerEditable, initPos.x, initPos.y)) { move->promotion = showPromotionDialog(button->generalProperties.window, gameControl->isBlackPlayerEditable); } // Black king is an error value of showPromotionDialog (this is an invalid promotion). We quit on errors. if (g_guiError || g_memError || (move->promotion == BLACK_K)) { deleteMove(move); return; } // Validate the move is legal bool isValidMove = validateMove(gameControl->board, gameControl->isBlackPlayerEditable, move); if (!isValidMove) { printf("Error: Gui allowed user to interact with illegal move, but logic protected from executing this move.\n"); deleteMove(move); return; } GuiWindow* window = (GuiWindow*)button->generalProperties.window; // Execute the move and update the gui. If the game is over, return. bool isGameOver = executeGuiTurn(window, gameControl, move); if (isGameOver) return; // When playing against the AI, execute the next turn if (g_gameMode == GAME_MODE_PLAYER_VS_AI) executeGuiNextComputerMove(window); }
STATUS CChessGame :: playMoveOnBoard(BOARD_POSITION init, BOARD_POSITION dest, CHESSPIECE_GENERAL newCp, MOVE_CLAIM mClaim = CLAIM_NONE) { STATUS status; CHECK_STATUS cStatus; MOVELIST *mList, *tempList; CZobrist zob; UINT64 currentHash; UINT8 count = 1, currentSeqNum; status = validateMove(init, dest, MVT_GENERAL); if((status & MOVE_PAWN_PROMOTED) && newCp == CHESSPIECE_TYPE(INVALID_CHESSPIECE)) { //pawn promotion should provide new piece also if(playerType[gState.turn] != PT_COMPUTER) { newCp = getNewPieceFromUser(); } else { status = MOVE_ILLEGAL; } } if(status & MOVE_SUCCESS) { (void)makeMove(init, dest, newCp, status); mList = (MOVELIST *)moveList.getTail(); if(mList != NULL) { //status must have got updated after makemove... status = mList->status; cStatus = scan4Check(init, dest, CHECK); if(isEndGame()) { if(cStatus == CHECK) { status |= MOVE_CHECKMATE; //printf("Checkmate\n"); } else { status |= MOVE_STALEMATE; //printf("Stalemate\n"); } } else if(cStatus == CHECK) { status |= MOVE_CHECK; //printf("Itz a check!!\n"); } /* Form the SAN notation for the MOVE */ mList->status = status; //This is needed for SAN (void)updateCANString(mList); (void)updateSANString(mList, TRUE); (void)updateFENString(mList->FEN); //check if 50 move repetition happened if(gState.draw50HalfMoveCount >= 50) { mList->status |= MOVE_DRAW_50MOVE_ACTIVE; } //check for insufficient material draw tempList = (MOVELIST *)moveList.getPrev((DLL_NODE *)mList); if((tempList != NULL && tempList->status & MOVE_DRAW_INSUFFICIENT_PIECES_ACTIVE) || insufficientMatingMaterial(getLastFENString()) == TRUE) { mList->status |= MOVE_DRAW_INSUFFICIENT_PIECES_ACTIVE; } // Update zobrist Hash zob.updateBoardPosition(getLastFENString()); zob.calculateZobristHash(); mList->zobristHash = zob.getZobristHash(); currentHash = mList->zobristHash; currentSeqNum = gState.seqNum; //check if 3 move repetition happened for(tempList = (MOVELIST *)moveList.getPrev((DLL_NODE *)mList); tempList != NULL; tempList = (MOVELIST *)moveList.getPrev((DLL_NODE *)tempList)) { if(tempList->seqNum != currentSeqNum) { break; } if(tempList->zobristHash == currentHash) { //add more detailed check using FEN string if required count++; } if(count == 3) { break; } } if(count == 3) { mList->status |= MOVE_DRAW_3MOVE_ACTIVE; } status = mList->status; } toggleTurn(); } return status; }
bool ChessBoard::makeMove(int from_x, int from_y, int to_x, int to_y ) { Move move( from_x, from_y, to_x, to_y ); /* the code that validates the move, does not check the position after the move this is done in the end of this method */ if( !validateMove( move ) ) return false; //castling if( getPiece( from_x, from_y )->type == KING && std::abs(to_x - from_x) == 2) { Piece* rook; int x, y = from_y; x = (to_x != 2) ? from_x + 1 : from_x - 1; if( to_x != 2 ) { rook = removePiece(to_x+1, to_y); } else { rook = removePiece( to_x - 2, to_y); } setPiece( x, y, rook ); rook->x = x; rook->y = y; } /* adds the piece to be taken if exists, then adds the move to the stack of moves */ Piece* pieceToMove = removePiece( from_x, from_y ); move.pieceTaken = getPiece( to_x, to_y ); //amp if( (pieceToMove->type == PAWN) && (std::abs( to_x - from_x ) == 1 ) && (getPiece( to_x, to_y ) == NULL) ) { move.pieceTaken = removePiece( to_x, from_y ); move.amp = true; } //transform to piece if( pieceToMove->type == PAWN && ( to_y == 0 || to_y == 7) ) { move.trans = true; pieceToMove->type = QUEEN; } if( move.pieceTaken != NULL ) { if( pieceToMove->color == move.pieceTaken->color) { setPiece( from_x, from_y, pieceToMove ); return false; } move.pieceTaken->inPlay = false; } moves.push( move ); /* retrives the piece that is to be moved, and then it moves it. at the end the new position is updaten in the piece-object */ setPiece( to_x, to_y, pieceToMove ); pieceToMove->x = to_x; pieceToMove->y = to_y; PieceColor colorOfMovingPlayer = pieceToMove->color; pieceToMove->nrOfMoves++; /* checks if the king of the player which just moved is in check, if so the move is invalid and it goes back a move */ if( playersKingInCheck( colorOfMovingPlayer ) ) { goBackAMove(); return false; } return true; }