bool apply_move (Game *g, int from, int to, char promote_in) { if (g->result != IN_PROGRESS) return FALSE; Board *board = current_board (g); Board *new_board = NEW_BOARD; char capture = 0; char *move_done = castling (board, castling_type (board, from, to), new_board); if (!move_done) // If move is not a castling { if (!try_move (board, from, to, promote_in, new_board, &move_done, &capture)) { free (new_board); return FALSE; } } // Ok move is legal, update the game update_castling (new_board, from); update_en_passant (new_board, from, to); if (new_board->active_color) new_board->fullmove_number++; new_board->active_color = !new_board->active_color; if (capture || toupper (board->placement[from]) == 'P') new_board->halfmove_clock = 0; else new_board->halfmove_clock++; g->boards[g->current] = new_board; g->moves[g->current] = move_done; g->coord_moves[g->current] = ft_to_coord_move (from, to, promote_in); g->current++; // Test check or checkmate of opponent king if (king_in_check (new_board, new_board->active_color)) { if (king_in_checkmate (new_board, new_board->active_color)) { strcat (move_done, "#"); g->result = !new_board->active_color; } else strcat (move_done, "+"); } // Test insufficient material else if (insufficient_material (new_board)) g->result = DRAW; // Test stalemate else if (stalemate (new_board, new_board->active_color)) g->result = DRAW; return TRUE; }
bool Board::toFEN(char * fen) const { if ( !fen ) return false; char * s = fen; // 1 - write figures for (int y = 7; y >= 0; --y) { int n = 0; for (int x = 0; x < 8; ++x) { Index idx(x, y); const Field & field = getField(idx); if ( !field ) { ++n; continue; } if ( n > 0 ) { *s++ = '0' + n; n = 0; } char c = fromFtype(field.type()); if ( field.color() == Figure::ColorBlack ) c = tolower(c); *s++ = c; } if ( n > 0 ) *s++ = '0' + n; if ( y > 0 ) *s++ = '/'; } // 2 - color to move { *s++ = ' '; if ( Figure::ColorBlack == color_ ) *s++ = 'b'; else *s++ = 'w'; } // 3 - castling possibility { *s++ = ' '; if ( !castling() ) { *s++ = '-'; } else { if ( castling_K() ) { if ( !verifyCastling(Figure::ColorWhite, 0) ) return false; *s++ = 'K'; } if ( castling_Q() ) { if ( !verifyCastling(Figure::ColorWhite, 1) ) return false; *s++ = 'Q'; } if ( castling_k() ) { if ( !verifyCastling(Figure::ColorBlack, 0) ) return false; *s++ = 'k'; } if ( castling_q() ) { if ( !verifyCastling(Figure::ColorBlack, 1) ) return false; *s++ = 'q'; } } } { // 4 - en passant *s++ = ' '; if ( en_passant_ >= 0 ) { Index ep_pos(en_passant_); int x = ep_pos.x(); int y = ep_pos.y(); if ( color_ ) y--; else y++; Index pawn_pos(x, y); const Field & ep_field = getField(pawn_pos); if ( ep_field.color() == color_ || ep_field.type() != Figure::TypePawn ) return false; char cx = 'a' + ep_pos.x(); char cy = '1' + ep_pos.y(); *s++ = cx; *s++ = cy; } else *s++ = '-'; // 5 - fifty move rule { *s++ = ' '; char str[8]; _itoa(fiftyMovesCount_, str, 10); char * sf = str; for ( ; *sf; ++sf, ++s) *s = *sf; } // 6 - moves counter { *s++ = ' '; char str[8]; _itoa(movesCounter_, str, 10); char * sf = str; for ( ; *sf; ++sf, ++s) *s = *sf; } } // terminal *s++ = 0; return true; }
bool Board::validMove(int srcX, int srcY, int destx, int desty) //determines if move is valid { bool collisionLegal = false; bool typeMoveLegal = false; bool sameTeam = true; int idPiece = boardarray[srcX][srcY]; int srcPiece = idPiece; if(srcPiece >= 0 && srcPiece <= 15) //special condition for pawn transformations { if(pieceArray[srcPiece]->getPawnTrans()) { srcPiece = pieceArray[idPiece]->getPieceRule(); } } int destPiece = boardarray[destx][desty]; //neccessary variables int srcPieceColor = 0; int destPieceColor = 0; bool whiteColorsrc = pieceArray[srcPiece]->getWhite(); bool whiteColorDest = false; bool checkMove = true; int colorTurn = 0; if(turn) //sets piece color, true is white colorTurn = 1; else colorTurn = 2; if(whiteColorsrc) srcPieceColor = 1; else srcPieceColor = 2; if(colorTurn == srcPieceColor){ //checks for whose turn it is if(destPiece != -1){ //fixes OutofIndex error whiteColorDest = pieceArray[destPiece]->getWhite(); if(whiteColorDest) destPieceColor = 1; //checks for friendly fire else destPieceColor = 2; } else destPieceColor = 3; if(srcPieceColor == destPieceColor) sameTeam = false; typeMoveLegal = pieceArray[srcPiece]->moveLegal(destx, desty, srcX, srcY, destPiece); collisionLegal = collision(destx, desty, srcX, srcY); if(srcPiece == 31 || srcPiece == 30) //special instance for castling castling(&typeMoveLegal, srcX, srcY, destx, desty, srcPiece); if(typeMoveLegal && collisionLegal && turn) //legal move, white turn, checks if king is in check { if(isCheck(pieceArray[WHITEKING]->getX(), pieceArray[WHITEKING]->getY(), destx, desty, srcX, srcY)) { checkMove = false; } else check = false; } else if(typeMoveLegal && collisionLegal && !turn) //legal move, black turn, checks if king is in check { if(isCheck(pieceArray[BLACKKING]->getX(), pieceArray[BLACKKING]->getY(), destx, desty, srcX, srcY)) { checkMove = false;//sets valid move to false if king is still hypothetically in check, preventing your move from happening } else check = false; } //EN PASSANT if((srcPiece >= 0 && srcPiece <= 15)) //if((srcPiece >= 0 || srcPiece <= 17) && collisionLegal && sameTeam && checkMove) { enPassant(&typeMoveLegal, srcX, srcY, destx, desty, srcPiece, whiteColorsrc, srcPieceColor); } if(srcPiece >= 20 && srcPiece <= 23) collisionLegal = true; if(typeMoveLegal && collisionLegal && sameTeam && checkMove)//everything is true - valid move { if(srcPiece >= 0 && srcPiece <= 15){ //checks if that pawn is moved to other side if(whiteColorsrc && desty == 0){ //for white peices pieceArray[srcPiece]->setTransform(); } if(!whiteColorsrc && desty == 7){ //for black pieces pieceArray[srcPiece]->setTransform(); } } if(idPiece == 30 || idPiece == 31 || (idPiece <= 27 && idPiece >= 24) || (idPiece >= 0 && idPiece <= 15)) pieceArray[srcPiece]->setFirstMoved(); moveCount++; turn = !turn; return true; } } return false; //false if move not valid }