static __inline int eval_b_mobility(int sq, int color) { int dest,r = 0,score = 0; int opcolor = color ^ 1; dest = sq + 17; while(IsEmpty(dest)) { r++; score += sq_ctrl[dest]; score += *(safety[opcolor] + dest); dest += 17; } if(PieceColor(dest) == opcolor) { r++; score += sq_ctrl[dest]; score += *(safety[opcolor] + dest); } dest = sq - 17; while(IsEmpty(dest)) { r++; score += sq_ctrl[dest]; score += *(safety[opcolor] + dest); dest -= 17; } if(PieceColor(dest) == opcolor) { r++; score += sq_ctrl[dest]; score += *(safety[opcolor] + dest); } dest = sq + 15; while(IsEmpty(dest)) { r++; score += sq_ctrl[dest]; score += *(safety[opcolor] + dest); dest += 15; } if(PieceColor(dest) == opcolor) { r++; score += sq_ctrl[dest]; score += *(safety[opcolor] + dest); } dest = sq - 15; while(IsEmpty(dest)) { r++; score += sq_ctrl[dest]; score += *(safety[opcolor] + dest); dest -= 15; } if(PieceColor(dest) == opcolor) { r++; score += sq_ctrl[dest]; score += *(safety[opcolor] + dest); } score += (mobility[BISHOP][r]); return score; }
static __inline int eval_n_mobility(int sq, int color) { int dest,r = 0,score = 0; int opcolor = color ^ 1; dest = sq + 14; if(!IsOutside(dest) && PieceColor(dest) != color) { r++; score += sq_ctrl[dest]; score += *(safety[opcolor] + dest); } dest = sq - 14; if(!IsOutside(dest) && PieceColor(dest) != color) { r++; score += sq_ctrl[dest]; score += *(safety[opcolor] + dest); } dest = sq + 18; if(!IsOutside(dest) && PieceColor(dest) != color) { r++; score += sq_ctrl[dest]; score += *(safety[opcolor] + dest); } dest = sq - 18; if(!IsOutside(dest) && PieceColor(dest) != color) { r++; score += sq_ctrl[dest]; score += *(safety[opcolor] + dest); } dest = sq + 31; if(!IsOutside(dest) && PieceColor(dest) != color) { r++; score += sq_ctrl[dest]; score += *(safety[opcolor] + dest); } dest = sq - 31; if(!IsOutside(dest) && PieceColor(dest) != color) { r++; score += sq_ctrl[dest]; score += *(safety[opcolor] + dest); } dest = sq + 33; if(!IsOutside(dest) && PieceColor(dest) != color) { r++; score += sq_ctrl[dest]; score += *(safety[opcolor] + dest); } dest = sq - 33; if(!IsOutside(dest) && PieceColor(dest) != color) { r++; score += sq_ctrl[dest]; score += *(safety[opcolor] + dest); } score += (mobility[KNIGHT][r]); return score; }
void MovePiece(int cx, int cy, int nx, int ny) { DrawFourTilesAt(nx * 2 + BOARD_OFFSET_X, ny * 2 + BOARD_OFFSET_Y, 29, _pieces[PieceColor(cx, cy)][PieceType(cx, cy)]); EraseFourTilesAt(cx * 2 + BOARD_OFFSET_X, cy * 2 + BOARD_OFFSET_Y, 29); _pieceLayout[ny][nx] = _pieceLayout[cy][cx]; _pieceLayout[cy][cx] = -1; }
void HorizontalMovesFrom(int x, int y, int* moves, int &nextMoveSlot, int* takingMoves, int &nextTMoveSlot) { for(int i = x + 1; i < 8; i++) if(!PieceAt(i, y)) moves[nextMoveSlot++] = y * 8 + i; else if(PieceColor(i, y) != PieceColor(x, y)) { takingMoves[nextTMoveSlot++] = y * 8 + i; break; } else break; for(int i = x - 1; i >= 0; i--) if(!PieceAt(i, y)) moves[nextMoveSlot++] = y * 8 + i; else if(PieceColor(i, y) != PieceColor(x, y)) { takingMoves[nextTMoveSlot++] = y * 8 + i; break; } else break; for(int i = y + 1; i < 8; i++) if(!PieceAt(x, i)) moves[nextMoveSlot++] = i * 8 + x; else if(PieceColor(x, i) != PieceColor(x, y)) { takingMoves[nextTMoveSlot++] = i * 8 + x; break; } else break; for(int i = y - 1; i >= 0; i--) if(!PieceAt(x, i)) moves[nextMoveSlot++] = i * 8 + x; else if(PieceColor(x, i) != PieceColor(x, y)) { takingMoves[nextTMoveSlot++] = i * 8 + x; break; } else break; }
int see( const Board &board, Move move ) { ASSERT(!IsNull(move)); #ifdef ATTACK_TRACE cout << "see "; MoveImage(move,cout); cout << endl; #endif ColorType my_side = PieceColor(board[StartSquare(move)]); ColorType side = my_side; ColorType oside = OppositeColor(side); Square square = DestSquare(move); Square attack_square = StartSquare(move); Piece attacker = board[attack_square]; Piece on_square = (TypeOfMove(move) == EnPassant) ? MakePiece(Pawn,oside) : board[square]; Bitboard opp_attacks(board.calcAttacks(square,oside)); if (opp_attacks.isClear()) { // piece is undefended #ifdef ATTACK_TRACE cout << "undefended, returning " << Gain(move) << endl; #endif return Gain(move); } int score_list[20]; int swap_score = 0; int gain; Bitboard attacks[2]; Square last_attack_sq[2] = {InvalidSquare, InvalidSquare}; attacks[side] = board.calcAttacks(square,side); attacks[oside] = opp_attacks; int count = 0; for (;;) { last_attack_sq[side] = attack_square; attacker = board[attack_square]; #ifdef ATTACK_TRACE cout << " " << PieceImage(TypeOfPiece(attacker)) << " on " << FileImage(attack_square) << RankImage(attack_square) << " takes " << PieceImage(TypeOfPiece(on_square)) << endl; #endif gain = PieceValue(on_square); if (TypeOfPiece(attacker) == Pawn && Rank(square,side) == 8) { if (count == 0) { // initial capture is a promotion (could be under-promotion) gain += (PieceValues[PromoteTo(move)] - PAWN_VALUE); on_square = MakePiece(PromoteTo(move),side); } else { // assume Queen promotion gain += QUEEN_VALUE-PAWN_VALUE; on_square = MakePiece(Queen,side); } } else { on_square = attacker; } if (side == my_side) swap_score += gain; else swap_score -= gain; ASSERT(count < 20); score_list[count++] = swap_score; // remove piece we used from attacks attacks[side].clear(attack_square); // switch sides side = OppositeColor(side); const Square atk = last_attack_sq[side]; if (atk != InvalidSquare && TypeOfPiece(board[atk]) != Knight) { // add in x-ray attacks if any Square xray = board.getDirectionalAttack(atk, -Attacks::directions[atk][square], side); if (xray != InvalidSquare) { attacks[side].set(xray); } } if (attacks[side]) { // get next opponent attacker attack_square = minAttacker(board,attacks[side],side); } else { // no more attackers (including x-rays) break; } } ASSERT(count >= 1); // minimax over the score list for (int i = count-1; i > 0; --i) { if (i % 2 == 0) { score_list[i-1] = max(score_list[i],score_list[i-1]); } else { score_list[i-1] = min(score_list[i],score_list[i-1]); } } #ifdef ATTACK_TRACE cout << "returning " << score_list[0] << endl; #endif return score_list[0]; }
int seeSign( const Board &board, Move move, int threshold ) { ASSERT(!IsNull(move)); #ifdef ATTACK_TRACE cout << "see "; MoveImage(move,cout); cout << endl; #endif ColorType my_side = PieceColor(board[StartSquare(move)]); ColorType side = my_side; ColorType oside = OppositeColor(side); Square square = DestSquare(move); Square attack_square = StartSquare(move); Piece attacker = board[attack_square]; Piece on_square = (TypeOfMove(move) == EnPassant) ? MakePiece(Pawn,oside) : board[square]; Bitboard opp_attacks(board.calcAttacks(square,oside)); if (opp_attacks.isClear()) { // piece is undefended #ifdef ATTACK_TRACE cout << "undefended, returning " << (Gain(move) >= threshold) << endl; #endif return Gain(move) >= threshold; } int score_list[20]; int swap_score = 0; int gain; Bitboard attacks[2]; Square last_attack_sq[2] = {InvalidSquare, InvalidSquare}; attacks[side] = board.calcAttacks(square,side); attacks[oside] = opp_attacks; int count = 0; for (;;) { last_attack_sq[side] = attack_square; attacker = board[attack_square]; #ifdef ATTACK_TRACE cout << " " << PieceImage(TypeOfPiece(attacker)) << " on " << FileImage(attack_square) << RankImage(attack_square) << " takes " << PieceImage(TypeOfPiece(on_square)) << endl; #endif gain = PieceValue(on_square); if (TypeOfPiece(attacker) == Pawn && Rank(square,side) == 8) { if (count == 0) { // initial capture is a promotion (could be under-promotion) gain += (PieceValues[PromoteTo(move)] - PAWN_VALUE); on_square = MakePiece(PromoteTo(move),side); } else { // assume Queen promotion gain += QUEEN_VALUE-PAWN_VALUE; on_square = MakePiece(Queen,side); } } else { on_square = attacker; } if (side == my_side) swap_score += gain; else swap_score -= gain; ASSERT(count < 20); score_list[count++] = swap_score; // remove piece we used from attacks attacks[side].clear(attack_square); // switch sides side = OppositeColor(side); if (count % 2 == 0) { // If it is our turn to move and we are above the threshold // then we can exit - if we capture it only improves the score. if (swap_score >= threshold) { ASSERT(see(board,move) >= threshold); return 1; } // Futility: If capturing the opponent piece for free does // not bring us up to the threshold, exit. (Do not cut off // if we have a potential promotion). if ((Rank(square,side) != 8 || !(attacks[side] & board.pawn_bits[side])) && swap_score + PieceValue(on_square) < threshold) { ASSERT(see(board,move) < threshold); return 0; } } else { // See if opponent already has captured enough that SEE is // below threshold if (swap_score < threshold) { ASSERT(see(board,move) < threshold); return 0; } // Futility: opponent capture cannot get us below threshold if ((Rank(square,side) != 8 || !(attacks[side] & board.pawn_bits[side])) && swap_score - PieceValue(on_square) >= threshold) { ASSERT(see(board,move) >= threshold); return 1; } } const Square atk = last_attack_sq[side]; if (atk != InvalidSquare && TypeOfPiece(board[atk]) != Knight) { // add in x-ray attacks if any Square xray = board.getDirectionalAttack(atk, -Attacks::directions[atk][square], side); if (xray != InvalidSquare) { attacks[side].set(xray); } } if (attacks[side]) { // get next opponent attacker attack_square = minAttacker(board,attacks[side],side); } else { // no more attackers (including x-rays) break; } } ASSERT(count >= 1); // minimax over the score list for (int i = count-1; i > 0; --i) { if (i % 2 == 0) { score_list[i-1] = max(score_list[i],score_list[i-1]); } else { score_list[i-1] = min(score_list[i],score_list[i-1]); } } #ifdef ATTACK_TRACE cout << "returning " << (score_list[0]>=threshold) << endl; #endif ASSERT((score_list[0] >= threshold) == (see(board,move) >= threshold)); return score_list[0] >= threshold; }
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; }
void BoardIO::writeFEN( const Board &board, ostream &o, int addMoveInfo) { // write out the board in Forsythe-Edwards (FEN) notation. for (int i=1;i<=8;i++) { int j = 1; while (j <= 8) { int n = 0; Square sq; Piece p; do { sq = MakeSquare(j,i,Black); p = board.contents[sq]; if (p != EmptyPiece) break; ++j; ++n; } while (j <= 8); if (n) o << (char)(n + '0'); if (p != EmptyPiece) { char img = PieceImage(TypeOfPiece(p)); if (PieceColor(p) == Black) img = tolower(img); o << img; j++; } } if (i != 8) o << '/'; } if (board.sideToMove() == White) o << " w"; else o << " b"; // used in I/O of castling data: const bool kcastle[6] = { true, true, false, false, false, false}; const bool qcastle[6] = { true, false, true, false, false, false}; // note : unfortunately FEN doesn't allow recording if castling // has taken place, only whether or not it is possible. CastleType wcs = board.castleStatus(White); CastleType bcs = board.castleStatus(Black); o << ' '; if (!kcastle[(int)wcs] && !qcastle[(int)bcs]) o << '-'; else { if (kcastle[(int)wcs]) o << 'K'; if (qcastle[(int)wcs]) o << 'Q'; if (kcastle[(int)bcs]) o << 'k'; if (qcastle[(int)bcs]) o << 'q'; } o << ' '; Square epsq = board.enPassantSq(); if (epsq == InvalidSquare) { o << '-'; } else { // FEN stores the destination square for an en passant capture; // we store the location of the capturable pawn. Square target = (board.sideToMove() == White) ? epsq + 8 : epsq - 8; o << FileImage(target) << RankImage(target); } if (addMoveInfo) { // FEN is supposed to include the halfmove and fullmove numbers, // but these are attributes of the game - they are not stored in // the board. o << " 0 1"; } }
void PlacePieces() { for(int i = 0; i < 8; i++) for(int j = 0; j < 8; j++) if(PieceAt(i, j)) DrawFourTilesAt((i * 2) + BOARD_OFFSET_X, (j * 2) + BOARD_OFFSET_Y, 29, _pieces[PieceColor(i, j)][PieceType(i, j)]); }
void AvailableMoves(int x, int y, int* moves, int* takingMoves) { // Maximum number of moves available at one time is 28 (Queen at C3) int kPTC[8][2] = {{-2,-1},{-2,1},{-1,-2},{1,-2},{2,-1},{2,1},{1,2},{-1,2}}; int kingPTC[8][2] = {{-1,0},{1,0},{0,-1},{0,1},{-1,-1},{-1,1},{1,-1},{1,1}}; for(int i = 0; i < 28; i++) moves[i] = -1; for(int i = 0; i < 16; i++) takingMoves[i] = -1; if(PieceAt(x, y)) { int colour = PieceColor(x, y); int type = PieceType(x, y); int nextMoveSlot = 0; int nextTMoveSlot = 0; switch(type) { case KING: for(int i = 0; i < 8; i++) { int nx = x + kingPTC[i][0], ny = y + kingPTC[i][1]; if(nx >= 0 && ny >= 0 && nx < 8 && ny < 8) { if(!PieceAt(nx, ny)) moves[nextMoveSlot++] = ny * 8 + nx; else if(PieceColor(nx, ny) != colour) takingMoves[nextTMoveSlot++] = ny * 8 + nx; } } break; case QUEEN: HorizontalMovesFrom(x, y, moves, nextMoveSlot, takingMoves, nextTMoveSlot); DiagonalMovesFrom(x, y, moves, nextMoveSlot, takingMoves, nextTMoveSlot); break; case BISHOP: DiagonalMovesFrom(x, y, moves, nextMoveSlot, takingMoves, nextTMoveSlot); break; case ROOK: HorizontalMovesFrom(x, y, moves, nextMoveSlot, takingMoves, nextTMoveSlot); break; case KNIGHT: for(int i = 0; i < 8; i++) { int nx = x + kPTC[i][0], ny = y + kPTC[i][1]; if(nx >= 0 && nx < 8 && ny >= 0 && ny < 8) { if(!PieceAt(nx, ny)) moves[nextMoveSlot++] = ny * 8 + nx; else if(PieceColor(nx, ny) != colour) takingMoves[nextTMoveSlot++] = ny * 8 + nx; } } break; case PAWN: if(colour == WHITE) { for(int i = 0; i < (y == 6 ? 2 : 1); i++) if(!PieceAt(x, y - 1 - i)) moves[nextMoveSlot++] = (y - 1 - i) * 8 + x; else break; if(x > 0) if(PieceAt(x - 1, y - 1) && PieceColor(x - 1, y - 1) != colour) takingMoves[nextTMoveSlot++] = (y - 1) * 8 + x - 1; if(x < 7) if(PieceAt(x + 1, y - 1) && PieceColor(x + 1, y - 1) != colour) takingMoves[nextTMoveSlot++] = (y - 1) * 8 + x + 1; } else { for(int i = 0; i < (y == 1 ? 2 : 1); i++) if(!PieceAt(x, y + 1 + i)) moves[nextMoveSlot++] = (y + 1 + i) * 8 + x; else break; if(x > 0) if(PieceAt(x - 1, y + 1) && PieceColor(x - 1, y + 1) != colour) takingMoves[nextTMoveSlot++] = (y + 1) * 8 + x - 1; if(x < 7) if(PieceAt(x + 1, y + 1) && PieceColor(x + 1, y + 1) != colour) takingMoves[nextTMoveSlot++] = (y + 1) * 8 + x + 1; } break; } } }
void DiagonalMovesFrom(int x, int y, int* moves, int &nextMoveSlot, int* takingMoves, int &nextTMoveSlot) { for(int i = 0; i < x && i < y; i++) { int nx = x - i - 1, ny = y - i - 1; if(!PieceAt(nx, ny)) moves[nextMoveSlot++] = ny * 8 + nx; else if(PieceColor(nx, ny) != PieceColor(x, y)) { takingMoves[nextTMoveSlot++] = ny * 8 + nx; break; } else break; } for(int i = 0; i < x && y + i < 8; i++) { int nx = x - i - 1, ny = y + i + 1; if(ny < 8) { if(!PieceAt(nx, ny)) moves[nextMoveSlot++] = ny * 8 + nx; else if(PieceColor(nx, ny) != PieceColor(x, y)) { takingMoves[nextTMoveSlot++] = ny * 8 + nx; break; } else break; } } for(int i = x + 1; i < 8; i++) { int nx = i, ny = y + (i - x); if(ny < 8) { if(!PieceAt(nx, ny)) moves[nextMoveSlot++] = ny * 8 + nx; else if(PieceColor(nx, ny) != PieceColor(x, y)) { takingMoves[nextTMoveSlot++] = ny * 8 + nx; break; } else break; } } for(int i = x + 1; i < 8; i++) { int nx = i, ny = y - (i - x); if(!PieceAt(nx, ny)) moves[nextMoveSlot++] = ny * 8 + nx; else if(PieceColor(nx, ny) != PieceColor(x, y)) { takingMoves[nextTMoveSlot++] = ny * 8 + nx; break; } else break; } }
int main() { LoadAssets(); ClearObjects(); InitialiseStage(); uint16_t oldKeys = REG_P1; Cursor cursor = Cursor(0); bool pieceSelected = false; int currentPiece = 0; int* moves = new int[28]; int* takingMoves = new int[16]; int currentTurnColor = WHITE; for(int i = 0; i < 2; i++) for(int j = 0; j < 16; j++) _lostPieces[i][j] = -1; while (true) { if(!(REG_P1 & KEY_RIGHT) && (oldKeys & KEY_RIGHT)) cursor.Move(1, 0); if(!(REG_P1 & KEY_LEFT) && (oldKeys & KEY_LEFT)) cursor.Move(-1, 0); if(!(REG_P1 & KEY_DOWN) && (oldKeys & KEY_DOWN)) cursor.Move(0, 1); if(!(REG_P1 & KEY_UP) && (oldKeys & KEY_UP)) cursor.Move(0, -1); if(!(REG_P1 & KEY_A) && (oldKeys & KEY_A)) { if(PieceAt(cursor.X(), cursor.Y())) { pieceSelected = true; for(int i = 0; i < 16 && takingMoves[i] >= 0; i++) if(takingMoves[i] % 8 == cursor.X() && takingMoves[i] / 8 == cursor.Y()) { TakePiece(currentPiece % 8, currentPiece / 8, cursor.X(), cursor.Y()); currentTurnColor = (currentTurnColor == WHITE ? BLACK : WHITE); pieceSelected = false; ClearHighlights(); takingMoves[0] = -1; break; } if(pieceSelected && PieceColor(cursor.X(), cursor.Y()) == currentTurnColor) { ClearHighlights(); AvailableMoves(cursor.X(), cursor.Y(), moves, takingMoves); currentPiece = cursor.Y() * 8 + cursor.X(); for(int i = 0; i < 28 && moves[i] >= 0; i++) Highlight(moves[i] % 8, moves[i] / 8, GREEN); for(int i = 0; i < 16 && takingMoves[i] >= 0; i++) Highlight(takingMoves[i] % 8, takingMoves[i] / 8, RED); } } else if(pieceSelected) { ClearHighlights(); if(!PieceAt(cursor.X(), cursor.Y())) { for(int i = 0; i < 28 && moves[i] >= 0; i++) if(moves[i] % 8 == cursor.X() && moves[i] / 8 == cursor.Y()) { MovePiece(currentPiece % 8, currentPiece / 8, cursor.X(), cursor.Y()); currentTurnColor = (currentTurnColor == WHITE ? BLACK : WHITE); pieceSelected = false; break; } } } } oldKeys = REG_P1; if(currentTurnColor == WHITE) DrawString(20, 1, "WHITE", 5); else DrawString(20, 1, "BLACK", 5); WaitVSync(); UpdateObjects(); } return 0; }
ChessPiece::ChessPiece(Piece _type, uint8_t index) :m_type(_type), m_position(index) { m_color = PieceColor(_type > 6); };
ChessPiece::ChessPiece(Piece _type) :m_type(_type) { m_color = PieceColor(_type > 6); };