File indexing completed on 2024-06-09 04:03:36
0001 /* 0002 * Copyright (C) 2006-2009 Stephan Kulow <coolo@kde.org> 0003 * 0004 * This program is free software; you can redistribute it and/or 0005 * modify it under the terms of the GNU General Public License as 0006 * published by the Free Software Foundation; either version 2 of 0007 * the License, or (at your option) any later version. 0008 * 0009 * This program is distributed in the hope that it will be useful, 0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0012 * GNU General Public License for more details. 0013 * 0014 * You should have received a copy of the GNU General Public License 0015 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0016 */ 0017 0018 #include "golfsolver.h" 0019 0020 // own 0021 #include "../golf.h" 0022 #include "../kpat_debug.h" 0023 0024 const int CHUNKSIZE = 10000; 0025 0026 #define BHS__GOLF__NUM_COLUMNS 7 0027 #define BHS__GOLF__MAX_NUM_CARDS_IN_COL 5 0028 #define BHS__GOLF__BITS_PER_COL 3 0029 0030 static volatile std::atomic_bool stop_exec = false; 0031 0032 GolfSolver::GolfSolver(const Golf *dealer) 0033 { 0034 deal = dealer; 0035 // Set default_max_positions to an initial 0036 // value so it will not accidentally be used uninitialized. 0037 // Note: it will be overrided by the Settings anyhow. 0038 default_max_positions = 100000; 0039 solver_instance = nullptr; 0040 solver_ret = BLACK_HOLE_SOLVER__OUT_OF_ITERS; 0041 } 0042 0043 void GolfSolver::stopExecution() 0044 { 0045 stop_exec = true; 0046 } 0047 0048 void GolfSolver::free_solver_instance() 0049 { 0050 if (solver_instance) { 0051 black_hole_solver_free(solver_instance); 0052 solver_instance = nullptr; 0053 } 0054 } 0055 0056 SolverInterface::ExitStatus GolfSolver::patsolve(int max_positions) 0057 { 0058 int current_iters_count = 0; 0059 if (max_positions < 0) { 0060 max_positions = default_max_positions; 0061 } 0062 stop_exec = false; 0063 if (solver_instance) { 0064 return SolverInterface::UnableToDetermineSolvability; 0065 } 0066 if (black_hole_solver_create(&solver_instance)) { 0067 fputs("Could not initialise solver_instance (out-of-memory)\n", stderr); 0068 exit(-1); 0069 } 0070 black_hole_solver_enable_rank_reachability_prune(solver_instance, true); 0071 black_hole_solver_enable_wrap_ranks(solver_instance, false); 0072 black_hole_solver_enable_place_queens_on_kings(solver_instance, true); 0073 #ifdef BLACK_HOLE_SOLVER__API__REQUIRES_SETUP_CALL 0074 black_hole_solver_config_setup(solver_instance); 0075 #endif 0076 0077 int error_line_num; 0078 int num_columns = BHS__GOLF__NUM_COLUMNS; 0079 if (black_hole_solver_read_board(solver_instance, 0080 board_as_string, 0081 &error_line_num, 0082 num_columns, 0083 BHS__GOLF__MAX_NUM_CARDS_IN_COL, 0084 BHS__GOLF__BITS_PER_COL)) { 0085 fprintf(stderr, "Error reading the board at line No. %d!\n", error_line_num); 0086 exit(-1); 0087 } 0088 #ifdef BLACK_HOLE_SOLVER__API__REQUIRES_SETUP_CALL 0089 black_hole_solver_setup(solver_instance); 0090 #endif 0091 solver_ret = BLACK_HOLE_SOLVER__OUT_OF_ITERS; 0092 0093 if (solver_instance) { 0094 while (!stop_exec && ((solver_ret == BLACK_HOLE_SOLVER__OUT_OF_ITERS)) && (current_iters_count < max_positions)) { 0095 current_iters_count += CHUNKSIZE; 0096 black_hole_solver_set_max_iters_limit(solver_instance, current_iters_count); 0097 0098 solver_ret = black_hole_solver_run(solver_instance); 0099 } 0100 } 0101 switch (solver_ret) { 0102 case BLACK_HOLE_SOLVER__OUT_OF_ITERS: 0103 free_solver_instance(); 0104 return SolverInterface::UnableToDetermineSolvability; 0105 0106 case 0: { 0107 if (solver_instance) { 0108 m_winMoves.clear(); 0109 int col_idx, card_rank, card_suit; 0110 int next_move_ret_code; 0111 #ifdef BLACK_HOLE_SOLVER__API__REQUIRES_SETUP_CALL 0112 black_hole_solver_init_solution_moves(solver_instance); 0113 #endif 0114 while ((next_move_ret_code = black_hole_solver_get_next_move(solver_instance, &col_idx, &card_rank, &card_suit)) == BLACK_HOLE_SOLVER__SUCCESS) { 0115 MOVE new_move; 0116 new_move.card_index = 0; 0117 new_move.from = col_idx; 0118 m_winMoves.append(new_move); 0119 } 0120 } 0121 free_solver_instance(); 0122 return SolverInterface::SolutionExists; 0123 } 0124 0125 default: 0126 free_solver_instance(); 0127 return SolverInterface::UnableToDetermineSolvability; 0128 0129 case BLACK_HOLE_SOLVER__NOT_SOLVABLE: 0130 free_solver_instance(); 0131 return SolverInterface::NoSolutionExists; 0132 } 0133 } 0134 0135 void GolfSolver::translate_layout() 0136 { 0137 strcpy(board_as_string, deal->solverFormat().toLatin1().constData()); 0138 free_solver_instance(); 0139 } 0140 0141 MoveHint GolfSolver::translateMove(const MOVE &m) 0142 { 0143 if (m.from >= 7) 0144 return MoveHint(); 0145 PatPile *frompile = deal->stack[m.from]; 0146 0147 KCard *card = frompile->at(frompile->count() - m.card_index - 1); 0148 0149 return MoveHint(card, deal->waste, m.pri); 0150 }