void Board::advance_board(CongaBoard* new_conga_board) { for (int x = 0; x < SQUARE_DIMENSION; ++x) { for (int y = 0; y < SQUARE_DIMENSION; ++y) { (*board)[x][y]->set_occupant((*new_conga_board)[x][y]->get_occupant()); (*board)[x][y]->set_num_stones((*new_conga_board)[x][y]->get_num_stones()); } } current_player = toggle_player(current_player); }
// this evaluation function only cares about the moves the opponent can make, // max score is 0 (win). int Board::evaluate(Square::Player evaluate_for_player) { int player_score = 0; Square::Player opponent = toggle_player(evaluate_for_player); for (int i = 0; i < SQUARE_DIMENSION; ++i) { for (int j = 0; j < SQUARE_DIMENSION; ++j) { if ((*board)[i][j]->get_occupant() == opponent) { player_score -= (find_available_directions(*(*board)[i][j])).size(); } } } return player_score; }
bool Reversi::make_move(string move){ //check size of move //cout << "Making move!\n"; //cout << "size of move:" << sizeof(move) << endl; if(move.size() != 2) return false; //check if user has chosen side //cout << "Move sized correctly!\n"; //cout << "current player:" << current_player << endl; if(current_player == 'n') return false; //split move into correct data types //cout << "Player has been set!\n"; //cout << "Move string: " << move << endl; Position current_move; if(isalpha(move[0])) { current_move.column = get_number_of_letter(move[0]); current_move.row = move[1]-'0'-1; } else{ current_move.row = get_number_of_letter(move[0]); current_move.column = move[1]-'0'-1; } //cout << "row: " << current_move.row << endl; //cout << "column: " << current_move.column << endl; // check if valid move bool possible_move_check = false; for(unsigned int i=0; i< available_moves.size(); i++) if(available_moves[i].row == current_move.row && available_moves[i].column == current_move.column) possible_move_check = true; if(!possible_move_check) return false; //cout << "Move is valid!\n"; // save previous state // only need to support 10 undos (20 total saved states) if(previous_states.size() >= 20) previous_states.pop_back(); previous_states.push_front({board, available_moves, white_score, black_score, current_player}); previous_move = move; //check all directions //if valid in a direction flip all appropriate tiles vector<Position> all_positions; vector<Position> temp_positions; all_positions.push_back(current_move); int x_step = 0; int y_step = -1; temp_positions = get_tiles(current_move, x_step, y_step); //check above for(unsigned int i=0; i<temp_positions.size(); i++) all_positions.push_back(temp_positions[i]); y_step = 1; temp_positions = get_tiles(current_move, x_step, y_step); //check below for(unsigned int i=0; i<temp_positions.size(); i++) all_positions.push_back(temp_positions[i]); y_step = 0; x_step = 1; temp_positions = get_tiles(current_move, x_step, y_step); //check right for(unsigned int i=0; i<temp_positions.size(); i++) all_positions.push_back(temp_positions[i]); x_step = -1; temp_positions = get_tiles(current_move, x_step, y_step); //check left for(unsigned int i=0; i<temp_positions.size(); i++) all_positions.push_back(temp_positions[i]); y_step = -1; temp_positions = get_tiles(current_move, x_step, y_step); //check top left for(unsigned int i=0; i<temp_positions.size(); i++) all_positions.push_back(temp_positions[i]); x_step = 1; temp_positions = get_tiles(current_move, x_step, y_step); //check top right for(unsigned int i=0; i<temp_positions.size(); i++) all_positions.push_back(temp_positions[i]); y_step = 1; temp_positions = get_tiles(current_move, x_step, y_step); //check bottom right for(unsigned int i=0; i<temp_positions.size(); i++) all_positions.push_back(temp_positions[i]); x_step = -1; temp_positions = get_tiles(current_move, x_step, y_step); //check bottom left for(unsigned int i=0; i<temp_positions.size(); i++) all_positions.push_back(temp_positions[i]); for(unsigned int i=0; i<all_positions.size(); i++) board[all_positions[i].row][all_positions[i].column] = current_player; update_score(); toggle_player(); available_moves = get_available_moves(); if(available_moves.size() == 0 && !(is_game_over())) { toggle_player(); available_moves = get_available_moves(); } }
std::vector<Board::Direction> Board::find_available_directions(Square& square) { std::vector<Board::Direction> available_directions; Square::Player sq_occupant = square.get_occupant(); if (sq_occupant == Square::NONE) { return available_directions; } Square::Player sq_opponent = toggle_player(sq_occupant); // check to see if movement on 8 directions is within boundaries first // then check the board to make sure at last one adjacent space is available if (square.get_y() + 1 < SQUARE_DIMENSION && (*board)[square.get_x()][square.get_y() + 1]->get_occupant() != sq_opponent) { available_directions.push_back(Board::NORTH); } if (square.get_y() - 1 >= 0 && (*board)[square.get_x()][square.get_y() - 1]->get_occupant() != sq_opponent) { available_directions.push_back(Board::SOUTH); } if (square.get_x() + 1 < SQUARE_DIMENSION && (*board)[square.get_x() + 1][square.get_y()]->get_occupant() != sq_opponent) { available_directions.push_back(Board::EAST); } if (square.get_x() - 1 >= 0 && (*board)[square.get_x() - 1][square.get_y()]->get_occupant() != sq_opponent) { available_directions.push_back(Board::WEST); } if (square.get_x() + 1 < SQUARE_DIMENSION && // check x + 1 square.get_y() + 1 < SQUARE_DIMENSION && // check y + 1 (*board)[square.get_x() + 1][square.get_y() + 1]->get_occupant() != sq_opponent) //check that diagonal is not blocked { available_directions.push_back(Board::NORTH_EAST); } if (square.get_x() + 1 < SQUARE_DIMENSION && square.get_y() - 1 >= 0 && (*board)[square.get_x() + 1][square.get_y() - 1]->get_occupant() != sq_opponent) { available_directions.push_back(Board::SOUTH_EAST); } if (square.get_x() - 1 >= 0 && square.get_y() + 1 < SQUARE_DIMENSION && (*board)[square.get_x() - 1][square.get_y() + 1]->get_occupant() != sq_opponent) { available_directions.push_back(Board::NORTH_WEST); } if (square.get_x() - 1 >= 0 && square.get_y() - 1 >= 0 && (*board)[square.get_x() - 1][square.get_y() - 1]->get_occupant() != sq_opponent) { available_directions.push_back(Board::SOUTH_WEST); } return available_directions; }
Board* Board::travel(Square& square, Board::Direction direction) { // Generate a new CongaBoard that is an exact copy of current Board::CongaBoard* new_board = new Board::CongaBoard(); int x = square.get_x(); int y = square.get_y(); for (int x = 0; x < SQUARE_DIMENSION; ++x) { std::vector<Square*> column; for (int y = 0; y < SQUARE_DIMENSION; ++y) { Square* new_square = new Square(x, y); new_square->set_occupant((*board)[x][y]->get_occupant()); new_square->set_num_stones((*board)[x][y]->get_num_stones()); column.push_back(new_square); } new_board->push_back(column); } Square::Player sq_opponent = toggle_player(current_player); int delta_y = 0; int delta_x = 0; switch (direction) { case NORTH: delta_y = 1; break; case SOUTH: delta_y = -1; break; case EAST: delta_x = 1; break; case WEST: delta_x = -1; break; case NORTH_EAST: delta_y = 1; delta_x = 1; break; case NORTH_WEST: delta_y = 1; delta_x = -1; break; case SOUTH_EAST: delta_y = -1; delta_x = 1; break; case SOUTH_WEST: delta_y = -1; delta_x = -1; break; default: break; } for (int i = 1; i <= SQUARE_DIMENSION; ++i) { int sq_num_stones = (*new_board)[x][y]->get_num_stones(); int y_i = y + i * delta_y; int x_i = x + i * delta_x; if (y_i >= SQUARE_DIMENSION || y_i < 0 || x_i >= SQUARE_DIMENSION || x_i < 0 || (*new_board)[x_i][y_i]->get_occupant() == sq_opponent) { if (i == 1) { // this should not happen printf("i == 1 in travel breaking\n"); break; } // We have hit an opponent square or end of board so put all the // remaining stones on previous square (*new_board)[x_i - delta_x][y_i - delta_y]->set_num_stones((*new_board)[x_i - delta_x][y_i - delta_y]->get_num_stones() + sq_num_stones); sq_num_stones = 0; } else { if (sq_num_stones >= i) { sq_num_stones -= i; (*new_board)[x_i][y_i]->set_num_stones((*new_board)[x_i][y_i]->get_num_stones() + i); } else { (*new_board)[x_i][y_i]->set_num_stones((*new_board)[x_i][y_i]->get_num_stones() + sq_num_stones); sq_num_stones = 0; } (*new_board)[x_i][y_i]->set_occupant(current_player); } (*new_board)[x][y]->set_num_stones(sq_num_stones); if (sq_num_stones == 0) { (*new_board)[x][y]->set_occupant(Square::NONE); break; } } return new Board(new_board, sq_opponent); }