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 }