void pickPiece(int col, int row){ Piece* piece = piece_at(col,row); if(piece != NULL){ if((piece->color == BLACK && gamestate == BLACK_TURN) || (piece->color == WHITE && gamestate == WHITE_TURN)){ if(piece == selected_piece){ for(int j = 0; j <= pieces.size()-1; j++){ pieces.at(j)->unpick(); } selected_piece = NULL; for(int i = 0; i < 56; i++) for(int j = 0; j < 2; j++) highlighted_tiles[i][j] = 0; } else{ for(int j = 0; j <= pieces.size()-1; j++){ pieces.at(j)->unpick(); } piece->pick(); selected_piece = piece; } } } }
AIMoves *ai_marks(const Board *b, PIECE min) { AIMoves *moves = aimoves_new(); AIMove move; PIECE p; for (move.y = 0; move.y < board_size; move.y++) for (move.x = 0; move.x < board_size; move.x++) if ((p = piece_at(b, move.x, move.y)) >= min) { move.weight = p - PIECE_THREAT0; aimoves_set(moves, &move); } return moves; }
AIMoves *ai_random(const Board *b) /* Returns a list of all empty tiles */ { AIMove move; AIMoves *moves; moves = aimoves_new(); for (move.y = 0; move.y < board_size; move.y++) for (move.x = 0; move.x < board_size; move.x++) if (piece_empty(piece_at(b, move.x, move.y))) { move.weight = g_random_int_range(AIW_MIN, AIW_MAX); aimoves_append(moves, &move); } return moves; }
static gboolean is_adjacent(const Board *b, BCOORD x, BCOORD y, int dist) { int dx, dy, count; PIECE p; if (!piece_empty(piece_at(b, x, y))) return FALSE; for (dy = -1; dy < 2; dy++) for (dx = -1; dx < 2; dx++) { if (!dx && !dy) continue; count = count_pieces(b, x, y, PIECE_NONE, dx, dy, &p); if (count - 1 < dist && p != PIECE_NONE) return TRUE; } return FALSE; }
bool can_castle(string input, unordered_map< string, string > *board, struct PlayerStatus &player_ps) //if can successfully castle, updates board and returns true; returns false otherwise { char player = piece_at(board, to_cart(player_ps.k_pos))[0]; int row = (player == 'W')? 1:8; vector<int> king_start {5,row}; vector<int> rook_start, rook_end, king_end; if (input == "0-0"){ //king-side castling if (!player_ps.castle_k_side) return false; vector<int> rook_start {8,row}; vector<int> rook_end {6,row}; vector<int> king_end {7,row}; } else{ //queen-side castling vector<int> queen_spot {4, row}; if (!player_ps.castle_q_side || occupied(board, queen_spot)) return false; vector<int> rook_start {1,row}; vector<int> rook_end {4,row}; vector<int> king_end {3,row}; } if (!occupied(board,king_end) && !occupied(board,rook_end)){ unordered_map<string,string> board2 = unordered_map<string,string>(*board); //make copy of board update_board(rook_start, rook_end, &board2); update_board(king_start, king_end, &board2); if (is_king_safe(&board2, player_ps)){ update_board(rook_start, rook_end, board); update_board(king_start, king_end, board); player_ps.k_pos = to_str(king_end); player_ps.castle_k_side = false; player_ps.castle_q_side = false; return true; } } return false; }
bool is_legal_move(vector<int> start, vector<int> end, const unordered_map< string, string > *board) { int x1 = start[0], y1= start[1]; // 'start' coordinates int x2 = end[0], y2 = end[1]; // 'end' coordinates int devX = (x2 - x1 >= 0)? x2-x1: x1-x2; //absolute column deviation int devY = (y2 - y1 >= 0)? y2-y1: y1-y2; //absolute row deviation bool start_in_range = (x1 >= 1) && (x1 <= 8) && (y1 >= 1) && (y1 <= 8); // is valid starting point bool end_in_range = (x2 >= 1) && (x2 <= 8) && (y2 >= 1) && (y2 <= 8); // is valid ending point if (!(start_in_range && end_in_range)) // position(s) are off the board! return false; char colour = piece_at(board, start)[0]; char piece = piece_at(board, start)[1]; vector<int> intermediate; if (piece_at(board, end)[0] != colour){ //ending point is not already occupied by you if (piece == 'P'){ //PAWN int sign = (colour == 'W')? 1: -1; if( !occupied(board,end) && y2 == y1 + sign && devX == 0){ //standard jump return true; } else if (colour == 'W' && y1 == 2 && y2 == 4 && devX == 0){ //if white's first move, double jump allowed vector<int> intermediate {x1,3}; //intermediate position if (!occupied(board, end) && !occupied(board,intermediate)) return true; } else if (colour == 'B' && y1 == 7 && y2 == 5 && devX == 0){ //if black's first move, double jump allowed vector<int> intermediate {x1,6}; //intermediate position if (!occupied(board, end) && !occupied(board,intermediate)) return true; } else if (occupied(board,end) && y2 == y1 + sign && devX == 1) //pawn makes a kill return true; } else if (piece == 'R' || piece == 'Q'){ //ROOK/QUEEN int sign; if (devY == 0) //no row deviation; moves along row sign = (x2 - x1) > 0? 1: -1; int j; for(j = 1; j < devX; ++j) { vector<int> intermediate {x1 + sign*j, y1}; //jth intermediate space if (occupied(board, intermediate)) return false; } return true; if (devX == 0) //no column deviation; moves along column sign = (y2 - y1) > 0? 1: -1; int i; for(i = 1; i < devY; ++i) { vector<int> intermediate {x1,y1 + sign*i}; //jth intermediate space if (occupied(board, intermediate)) return false; } return true; } else if (piece == 'N'){ //KNIGHT if ( (devY == 2 && devX == 1) || (devY == 1 && devX == 2)) return true; } else if (piece == 'B' || piece == 'Q'){ //BISHOP/QUEEN if (devX == devY) {//absolute row deviation = absolute column deviation int y_sign = (y2 - y1) > 0? 1: -1; int x_sign = (x2 - x1) > 0? 1: -1; int k; for (k=1; k < devX; ++k){ vector<int> intermediate {x1 + (x_sign)*k,y1 + (y_sign)*k}; //kth intermediate space if (occupied(board,intermediate)) return false; } return true; } } else if (piece == 'K'){ //KING if ( devX <= 1 && devY <= 1) //ensures that 'end' is only one move away from 'start' return true; } return false; } else return false; }
// does the proposed move put player 'colour' in check? // **will run after is_legal_move, so proposed move will always be legal** bool is_king_safe(const unordered_map< string, string > *board, struct PlayerStatus player_ps) { vector<int> king_pos = to_cart(player_ps.k_pos); char player = (piece_at(board, king_pos)[0] == 'W')?'W':'B'; char opponent = (player == 'W')? 'B': 'W'; int king_x = king_pos[0], king_y = king_pos[1]; int i; string piece; //determine if enemy rook (or queen) is in striking distance for(i=1; i < 8; ++i){ //searching right vector<int> position {king_x + i, king_y}; if (!((board -> find(to_str(position))) == (board -> end()))) { piece = piece_at(board, position); if( (piece[0] == opponent) && ( piece[1] == 'R' || piece[1] == 'Q')){ //if piece is an enemy rook or queen return false; } else i = 8; } } for(i=1; i < 8; ++i){ //searching left vector<int> position {king_x - i, king_y}; if (!((board -> find(to_str(position))) == (board -> end()))) { piece = piece_at(board, position); if( (piece[0] == opponent) && ( piece[1] == 'R' || piece[1] == 'Q')){ //if piece is an enemy rook or queen return false; } else i = 8; } } for(i=1; i < 8; ++i){ //searching up vector<int> position {king_x, king_y + i}; if (!((board -> find(to_str(position))) == (board -> end()))) { piece = piece_at(board, position); if( (piece[0] == opponent) && ( piece[1] == 'R' || piece[1] == 'Q')){ //if piece is an enemy rook or queen return false; } else i = 8; } } for(i=1; i < 8; ++i){ //searching down vector<int> position {king_x, king_y - i}; if (!((board -> find(to_str(position))) == (board -> end()))) { piece = piece_at(board, position); if( (piece[0] == opponent) && ( piece[1] == 'R' || piece[1] == 'Q')){ //if piece is an enemy rook or queen return false; } else i = 8; } } //determine if enemy bishop (or queen) is in striking distance for(i= 1; i < 8; ++i){ //searching right-up direction vector<int> position {king_x + i, king_y + i}; if (!((board -> find(to_str(position))) == (board -> end()))){ piece = piece_at(board,position); if( (piece[0] == opponent) && ( piece[1] == 'B' || piece[1] == 'Q')){ //if piece is an enemy bishop or queen return false; } else i = 8; } } for(i= 1; i < 8; ++i){ //searching right-down direction vector<int> position {king_x + i, king_y - i}; if (!((board -> find(to_str(position))) == (board -> end()))){ piece = piece_at(board,position); if( (piece[0] == opponent) && ( piece[1] == 'B' || piece[1] == 'Q')){ //if piece is an enemy bishop or queen return false; } else i = 8; } } for(i= 1; i < 8; ++i){ //searching left-up direction vector<int> position {king_x - i, king_y + i}; if (!((board -> find(to_str(position))) == (board -> end()))){ piece = piece_at(board,position); if( (piece[0] == opponent) && ( piece[1] == 'B' || piece[1] == 'Q')){ //if piece is an enemy bishop or queen return false; } else i = 8; } } for(i= 1; i < 8; ++i){ //searching left-down direction vector<int> position {king_x - i, king_y - i}; if (!((board -> find(to_str(position))) == (board -> end()))){ //if position is on board (and not where king is) piece = piece_at(board,position); if( (piece[0] == opponent) && ( piece[1] == 'B' || piece[1] == 'Q')){ //if piece is an enemy bishop or queen return false; } else i = 8; } } //determine if enemy knight is in striking distance vector<int> N_positions {king_x - 2,king_y - 1,king_x - 2, king_y + 1, king_x + 2, king_y - 1, king_x + 2, king_y + 1, king_x - 1, king_y - 2, king_x - 1, king_y + 2, king_x + 1, king_y - 2, king_x + 1, king_y + 2}; for (i = 0; i < 16; i = i+2){ vector<int> position {N_positions[i], N_positions[i+1]}; if (!((board -> find(to_str(position))) == (board -> end()) )) { piece = piece_at(board,position); if ((piece[0] == opponent) && (piece[1] == 'N')) return false; } } //determine if enemy pawn is in striking distance int sign = (player == 'W')? 1 : -1 ; vector<int> P_positions {king_x - 1, king_y + sign, king_x + 1, king_y + sign}; for (i=0; i < 4; i=i+2){ vector<int> position {P_positions[i], P_positions[i+1]}; if (!((board -> find(to_str(position))) == (board -> end()))) { piece = piece_at(board,position); if ((piece[0] == opponent) && (piece[1] == 'P')) return false; } } //determine if enemy king is in striking distance vector<int> K_positions {king_x-1,king_y-1,king_x,king_y-1,king_x+1, king_y-1,king_x-1,king_y,king_x+1,king_y,king_x-1,king_y+1,king_x, king_y+1,king_x+1,king_y+1}; for (i = 0; i < 16; i = i + 2){ vector<int> position {K_positions[i], K_positions[i+1]}; if (!((board -> find(to_str(position))) == (board -> end()) )) { piece = piece_at(board,position); if ((piece[0] == opponent) && (piece[1] == 'K')) return false; } } return true; }
static int threat_window(int x, int y, int dx, int dy, PIECE *ptype, int *pdouble) { int min, max, count = 0; PIECE p, type = PIECE_NONE; /* Check if this tile is empty */ p = piece_at(b, x, y); if (!piece_empty(p)) return 0; /* Push forward the max and find the window type */ for (max = 1; max < connect_k; max++) { p = piece_at(b, x + dx * max, y + dy * max); if (p == PIECE_ERROR) break; if (!piece_empty(p)) { if (type == PIECE_NONE) type = p; else if (type != p) break; count++; } } max--; /* Try to push the entire window back */ for (min = -1; min > -connect_k; min--) { p = piece_at(b, x + dx * min, y + dy * min); if (p == PIECE_ERROR || piece_empty(p)) break; if (type == PIECE_NONE) type = p; else if (type != p) break; if (max - min > connect_k - 1) { p = piece_at(b, x + dx * max, y + dy * max); if (p == type) count--; max--; } count++; } min++; /* Push back min if we haven't formed a complete window, this window can't be a double */ if (max - min < connect_k - 1) { for (min--; min > max - connect_k; min--) { p = piece_at(b, x + dx * min, y + dy * min); if (p == PIECE_ERROR) break; if (!piece_empty(p)) { if (type != p) break; if (type == PIECE_NONE) type = p; count++; } } *pdouble = 0; min++; } *ptype = type; if (max - min >= connect_k - 1) return count; return 0; }
static AIWEIGHT threat_line(int x, int y, int dx, int dy) { int i; AIWEIGHT weight = 0; /* Mark the maximum threat for each */ for (i = 0; x >= 0 && x < board_size && y >= 0 && y < board_size; i++) { int count[2], tmp, double_threat = 1; PIECE type[2]; count[0] = threat_window(x, y, dx, dy, type, &double_threat); count[1] = threat_window(x, y, -dx, -dy, type + 1, &double_threat); if (count[1] > count[0]) { tmp = count[1]; count[1] = count[0]; count[0] = tmp; tmp = type[1]; type[1] = type[0]; type[0] = tmp; } line[i].threat[0] = 0; line[i].threat[1] = 0; threat_mark(i, count[0], type[0]); if (double_threat) threat_mark(i, count[1], type[1]); x += dx; y += dy; } /* Commit stored line values to the board */ x -= dx; y -= dy; for (i--; x >= 0 && x < board_size && y >= 0 && y < board_size; i--) { AIWEIGHT bits[2]; PIECE p; bits[0] = threat_bits(line[i].threat[0], line[i].turn[0]); bits[1] = threat_bits(line[i].threat[1], line[i].turn[1]); p = piece_at(b, x, y); if (piece_empty(p) && line[i].threat[0]) { threat_counts[line[i].threat[0]][line[i].turn[0] - 1]++; if (line[i].threat[1]) threat_counts[line[i].threat[1]] [line[i].turn[1] - 1]++; if (p >= PIECE_THREAT0) place_threat(b, x, y, p - PIECE_THREAT0 + bits[0] + bits[1]); else place_threat(b, x, y, bits[0] + bits[1]); } if (b->turn != line[i].turn[0]) bits[0] = -bits[0]; if (b->turn != line[i].turn[1]) bits[1] = -bits[1]; weight += bits[0] + bits[1]; x -= dx; y -= dy; } return weight; }