From 52b1f1cb9f8d4e1fb1fcbde59930a105a819b0b4 Mon Sep 17 00:00:00 2001 From: Eric Hameleers Date: Thu, 30 Jul 2020 19:45:19 +0200 Subject: Cleanup unused KDE patches Thanks to Patrick Volkerding for the effort. --- kde/patch/kpat/kpat_no_freecell_solver_dep.patch | 1475 ---------------------- 1 file changed, 1475 deletions(-) delete mode 100644 kde/patch/kpat/kpat_no_freecell_solver_dep.patch (limited to 'kde/patch/kpat') diff --git a/kde/patch/kpat/kpat_no_freecell_solver_dep.patch b/kde/patch/kpat/kpat_no_freecell_solver_dep.patch deleted file mode 100644 index 06aedca..0000000 --- a/kde/patch/kpat/kpat_no_freecell_solver_dep.patch +++ /dev/null @@ -1,1475 +0,0 @@ -Commit https://cgit.kde.org/kpat.git/patch/?id=fc1d54ced6a727382599d767e55879b6843c3456 -Introduces a hard dependency on fc-solver which in turn has new dependencies -So, we revert this commit to avoid dropping kpat altogether - -From ed0e53e0888da7123f4a0d2097f8da7fb105ca18 Mon Sep 17 00:00:00 2001 -From: Fabian Kosmale <0inkane@googlemail.com> -Date: Sun, 13 May 2018 15:14:53 +0200 -Subject: Use Freecell Solver for FreeCell and Simple Simon - -Summary: This uses http://fc-solve.shlomifish.org/ and prevents the looping in the existing solvers. - -Test Plan: Test that the solvers are working. - -Reviewers: #kde_games, fabiank - -Subscribers: kde-games-devel, aacid, #kde_games - -Tags: #kde_games - -Differential Revision: https://phabricator.kde.org/D12415 ---- - CMakeLists.txt | 6 +- - dealer.cpp | 4 + - freecell.cpp | 35 ++++ - freecell.h | 1 + - patsolve/abstract_fc_solve_solver.cpp | 239 ++++++++++++++++++++++++++ - patsolve/abstract_fc_solve_solver.h | 52 ++++++ - patsolve/freecellsolver.cpp | 310 +++++++++++++++++----------------- - patsolve/freecellsolver.h | 23 ++- - patsolve/patsolve.h | 12 +- - patsolve/simonsolver.cpp | 129 +++++++++++++- - patsolve/simonsolver.h | 20 ++- - patsolve/solverinterface.h | 2 + - pileutils.cpp | 61 +++++++ - pileutils.h | 4 + - simon.cpp | 56 +++++- - simon.h | 1 + - 16 files changed, 779 insertions(+), 176 deletions(-) - create mode 100644 patsolve/abstract_fc_solve_solver.cpp - create mode 100644 patsolve/abstract_fc_solve_solver.h - -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 8f738bf..c043c45 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -4,6 +4,8 @@ cmake_minimum_required (VERSION 2.8.12 FATAL_ERROR) - set (QT_MIN_VERSION "5.7.0") - set (KF5_MIN_VERSION "5.30.0") - -+include(FindPkgConfig) -+pkg_check_modules(FC_SOLVE REQUIRED libfreecell-solver) - find_package(ECM ${KF5_MIN_VERSION} REQUIRED CONFIG) - set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) - -@@ -45,7 +47,7 @@ add_subdirectory(sounds) - add_subdirectory(themes) - add_subdirectory(doc) - --set(kpat_SRCS -+set(kpat_SRCS ${libfcs_SRCS} - main.cpp - dealer.cpp - dealerinfo.cpp -@@ -59,6 +61,7 @@ set(kpat_SRCS - soundengine.cpp - statisticsdialog.cpp - view.cpp -+ patsolve/abstract_fc_solve_solver.cpp - patsolve/memory.cpp - patsolve/patsolve.cpp - -@@ -101,6 +104,7 @@ target_link_libraries(kpat - KF5::KIOCore - KF5KDEGames - kcardgame -+ ${FC_SOLVE_LDFLAGS} - ) - - install(TARGETS kpat ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) -diff --git a/dealer.cpp b/dealer.cpp -index 7c03ebf..a2558fc 100644 ---- a/dealer.cpp -+++ b/dealer.cpp -@@ -1724,6 +1724,10 @@ void DealerScene::startSolver() - - bool DealerScene::isGameLost() const - { -+ if (! m_winningMoves.isEmpty()) -+ { -+ return false; -+ } - if ( solver() ) - { - if ( m_solverThread && m_solverThread->isRunning() ) -diff --git a/freecell.cpp b/freecell.cpp -index f870cdb..9a7c278 100644 ---- a/freecell.cpp -+++ b/freecell.cpp -@@ -111,6 +111,41 @@ void Freecell::restart( const QList & cards ) - } - - -+QString Freecell::solverFormat() const -+{ -+ QString output; -+ QString tmp; -+ for (int i = 0; i < 4 ; i++) { -+ if (target[i]->isEmpty()) -+ continue; -+ tmp += suitToString(target[i]->topCard()->suit()) + '-' + rankToString(target[i]->topCard()->rank()) + ' '; -+ } -+ if (!tmp.isEmpty()) -+ output += QString::fromLatin1("Foundations: %1\n").arg(tmp); -+ -+ tmp.truncate(0); -+ for (int i = 0; i < 4 ; i++) { -+ if (freecell[i]->isEmpty()) -+ tmp += "- "; -+ else -+ tmp += rankToString(freecell[i]->topCard()->rank()) + suitToString(freecell[i]->topCard()->suit()) + ' '; -+ } -+ if (!tmp.isEmpty()) -+ { -+ QString a = QString::fromLatin1("Freecells: %1\n"); -+ output += a.arg(tmp); -+ } -+ -+ for (int i = 0; i < 8 ; i++) -+ { -+ QList cards = store[i]->cards(); -+ for (QList::ConstIterator it = cards.begin(); it != cards.end(); ++it) -+ output += rankToString((*it)->rank()) + suitToString((*it)->suit()) + ' '; -+ output += '\n'; -+ } -+ return output; -+} -+ - void Freecell::cardsDroppedOnPile( const QList & cards, KCardPile * pile ) - { - if ( cards.size() <= 1 ) -diff --git a/freecell.h b/freecell.h -index 7b0b2cb..9f7d84b 100644 ---- a/freecell.h -+++ b/freecell.h -@@ -62,6 +62,7 @@ protected slots: - private: - bool canPutStore( const KCardPile * pile, const QList & cards ) const; - -+ virtual QString solverFormat() const; - PatPile* store[8]; - PatPile* freecell[4]; - PatPile* target[4]; -diff --git a/patsolve/abstract_fc_solve_solver.cpp b/patsolve/abstract_fc_solve_solver.cpp -new file mode 100644 -index 0000000..11e5baa ---- /dev/null -+++ b/patsolve/abstract_fc_solve_solver.cpp -@@ -0,0 +1,239 @@ -+/* -+ * Copyright (C) 2006-2009 Stephan Kulow -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation; either version 2 of -+ * the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+#include -+#include -+ -+#include "freecell-solver/fcs_user.h" -+#include "freecell-solver/fcs_cl.h" -+ -+#include "abstract_fc_solve_solver.h" -+ -+const int CHUNKSIZE = 100; -+const long int MAX_ITERS_LIMIT = 200000; -+ -+#define PRINT 0 -+ -+/* These two routines make and unmake moves. */ -+ -+void FcSolveSolver::make_move(MOVE *) -+{ -+ return; -+} -+ -+void FcSolveSolver::undo_move(MOVE *) -+{ -+ return; -+} -+ -+/* Get the possible moves from a position, and store them in Possible[]. */ -+SolverInterface::ExitStatus FcSolveSolver::patsolve( int _max_positions ) -+{ -+ int current_iters_count; -+ max_positions = (_max_positions < 0) ? MAX_ITERS_LIMIT : _max_positions; -+ -+ init(); -+ -+ if (!solver_instance) -+ { -+ { -+ solver_instance = freecell_solver_user_alloc(); -+ -+ solver_ret = FCS_STATE_NOT_BEGAN_YET; -+ -+ char * error_string; -+ int error_arg; -+ const char * known_parameters[1] = {NULL}; -+ /* A "char *" copy instead of "const char *". */ -+ -+ int parse_args_ret_code = freecell_solver_user_cmd_line_parse_args( -+ solver_instance, -+ get_cmd_line_arg_count() , -+ get_cmd_line_args(), -+ 0, -+ known_parameters, -+ NULL, -+ NULL, -+ &error_string, -+ &error_arg -+ ); -+ -+ Q_ASSERT(!parse_args_ret_code); -+ } -+ -+ /* Not needed for Simple Simon because it's already specified in -+ * freecell_solver_cmd_line_args. TODO : abstract . -+ * -+ * Shlomi Fish -+ * */ -+ setFcSolverGameParams(); -+ -+ current_iters_count = CHUNKSIZE; -+ freecell_solver_user_limit_iterations(solver_instance, current_iters_count); -+ } -+ -+ if (solver_instance) -+ { -+ bool continue_loop = true; -+ while (continue_loop && -+ ( (solver_ret == FCS_STATE_NOT_BEGAN_YET) -+ || (solver_ret == FCS_STATE_SUSPEND_PROCESS)) -+ && -+ (current_iters_count < MAX_ITERS_LIMIT) -+ ) -+ { -+ current_iters_count += CHUNKSIZE; -+ freecell_solver_user_limit_iterations(solver_instance, current_iters_count); -+ -+ if (solver_ret == FCS_STATE_NOT_BEGAN_YET) -+ { -+ solver_ret = -+ freecell_solver_user_solve_board( -+ solver_instance, -+ board_as_string -+ ); -+ } -+ else -+ { -+ solver_ret = freecell_solver_user_resume_solution(solver_instance); -+ } -+ { -+ // QMutexLocker lock( &endMutex ); -+ if ( m_shouldEnd ) -+ { -+ continue_loop = false; -+ } -+ } -+ } -+ } -+ -+ switch (solver_ret) -+ { -+ case FCS_STATE_IS_NOT_SOLVEABLE: -+ if (solver_instance) -+ { -+ freecell_solver_user_free(solver_instance); -+ solver_instance = NULL; -+ } -+ return Solver::NoSolutionExists; -+ -+ case FCS_STATE_WAS_SOLVED: -+ { -+ if (solver_instance) -+ { -+ m_winMoves.clear(); -+ while (freecell_solver_user_get_moves_left(solver_instance)) -+ { -+ fcs_move_t move; -+ MOVE new_move; -+ const int verdict = !freecell_solver_user_get_next_move( -+ solver_instance, &move) -+ ; -+ -+ Q_ASSERT (verdict); -+ -+ new_move.fcs = move; -+ -+ m_winMoves.append( new_move ); -+ } -+ -+ freecell_solver_user_free(solver_instance); -+ solver_instance = NULL; -+ } -+ return Solver::SolutionExists; -+ } -+ -+ case FCS_STATE_SUSPEND_PROCESS: -+ return Solver::UnableToDetermineSolvability; -+ -+ default: -+ if (solver_instance) -+ { -+ freecell_solver_user_free(solver_instance); -+ solver_instance = NULL; -+ } -+ return Solver::NoSolutionExists; -+ } -+} -+ -+/* Get the possible moves from a position, and store them in Possible[]. */ -+ -+int FcSolveSolver::get_possible_moves(int *, int *) -+{ -+ return 0; -+} -+ -+bool FcSolveSolver::isWon() -+{ -+ return true; -+} -+ -+int FcSolveSolver::getOuts() -+{ -+ return 0; -+} -+ -+FcSolveSolver::FcSolveSolver() -+ : Solver() -+ , solver_instance(NULL) -+ , solver_ret(FCS_STATE_NOT_BEGAN_YET) -+ , board_as_string("") -+{ -+} -+ -+unsigned int FcSolveSolver::getClusterNumber() -+{ -+ return 0; -+} -+ -+void FcSolveSolver::print_layout() -+{ -+#if 0 -+ int i, w, o; -+ -+ fprintf(stderr, "print-layout-begin\n"); -+ for (w = 0; w < 10; ++w) { -+ Q_ASSERT( Wp[w] == &W[w][Wlen[w]-1] ); -+ fprintf( stderr, "Play%d: ", w ); -+ for (i = 0; i < Wlen[w]; ++i) { -+ printcard(W[w][i], stderr); -+ } -+ fputc('\n', stderr); -+ } -+ fprintf( stderr, "Off: " ); -+ for (o = 0; o < 4; ++o) { -+ if ( O[o] != -1 ) -+ printcard( O[o] + PS_KING, stderr); -+ } -+ fprintf(stderr, "\nprint-layout-end\n"); -+#endif -+} -+ -+void FcSolveSolver::unpack_cluster( unsigned int) -+{ -+ return; -+} -+ -+FcSolveSolver::~FcSolveSolver() -+{ -+ if (solver_instance) -+ { -+ freecell_solver_user_free(solver_instance); -+ solver_instance = NULL; -+ } -+} -+ -diff --git a/patsolve/abstract_fc_solve_solver.h b/patsolve/abstract_fc_solve_solver.h -new file mode 100644 -index 0000000..d2d072d ---- /dev/null -+++ b/patsolve/abstract_fc_solve_solver.h -@@ -0,0 +1,52 @@ -+/* -+ * Copyright (C) 2006-2009 Stephan Kulow -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation; either version 2 of -+ * the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+#ifndef ABSTRACT_FC_SOLVE_SOLVER_H -+#define ABSTRACT_FC_SOLVE_SOLVER_H -+ -+#include "patsolve.h" -+ -+struct FcSolveSolver : public Solver<10> -+{ -+public: -+ FcSolveSolver(); -+ virtual ~FcSolveSolver(); -+ virtual int get_possible_moves(int *a, int *numout); -+ virtual bool isWon(); -+ virtual void make_move(MOVE *m); -+ virtual void undo_move(MOVE *m); -+ virtual int getOuts(); -+ virtual unsigned int getClusterNumber(); -+ virtual void translate_layout() = 0; -+ virtual void unpack_cluster( unsigned int k ); -+ virtual MoveHint translateMove(const MOVE &m) = 0; -+ virtual SolverInterface::ExitStatus patsolve( int _max_positions = -1); -+ virtual void setFcSolverGameParams() = 0; -+ -+ virtual void print_layout(); -+ -+ virtual int get_cmd_line_arg_count() = 0; -+ virtual const char * * get_cmd_line_args() = 0; -+/* Names of the cards. The ordering is defined in pat.h. */ -+ -+ void * solver_instance; -+ int solver_ret; -+ // More than enough space for two decks. -+ char board_as_string[4 * 13 * 2 * 4 * 3]; -+}; -+ -+#endif // ABSTRACT_FC_SOLVE_SOLVER_H -diff --git a/patsolve/freecellsolver.cpp b/patsolve/freecellsolver.cpp -index 39eff50..e92000f 100644 ---- a/patsolve/freecellsolver.cpp -+++ b/patsolve/freecellsolver.cpp -@@ -16,12 +16,18 @@ - * along with this program. If not, see . - */ - -+#include -+#include -+ -+#include "freecell-solver/fcs_user.h" -+#include "freecell-solver/fcs_cl.h" -+ - #include "freecellsolver.h" - - #include "../freecell.h" - -- --/* Some macros used in get_possible_moves(). */ -+const int CHUNKSIZE = 100; -+const long int MAX_ITERS_LIMIT = 200000; - - /* The following function implements - (Same_suit ? (suit(a) == suit(b)) : (color(a) != color(b))) -@@ -32,10 +38,13 @@ namespace { - - /* Statistics. */ - -+#if 0 - int FreecellSolver::Xparam[] = { 4, 1, 8, -1, 7, 11, 4, 2, 2, 1, 2 }; -+#endif - - /* These two routines make and unmake moves. */ - -+#if 0 - void FreecellSolver::make_move(MOVE *m) - { - int from, to; -@@ -85,7 +94,9 @@ void FreecellSolver::undo_move(MOVE *m) - Wlen[from]++; - hashpile(from); - } -+#endif - -+#if 0 - /* Move prioritization. Given legal, pruned moves, there are still some - that are a waste of time, especially in the endgame where there are lots of - possible moves, but few productive ones. Note that we also prioritize -@@ -178,9 +189,11 @@ void FreecellSolver::prioritize(MOVE *mp0, int n) - } - } - } -+#endif - - /* Automove logic. Freecell games must avoid certain types of automoves. */ - -+#if 0 - int FreecellSolver::good_automove(int o, int r) - { - int i; -@@ -220,148 +233,43 @@ int FreecellSolver::good_automove(int o, int r) - - return true; - } -+#endif - --/* Get the possible moves from a position, and store them in Possible[]. */ -+#define CMD_LINE_ARGS_NUM 2 - --int FreecellSolver::get_possible_moves(int *a, int *numout) -+static const char * freecell_solver_cmd_line_args[CMD_LINE_ARGS_NUM] = - { -- int i, n, t, w, o, empty, emptyw; -- card_t card; -- MOVE *mp; -- -- /* Check for moves from W to O. */ -- -- n = 0; -- mp = Possible; -- for (w = 0; w < Nwpiles + Ntpiles; ++w) { -- if (Wlen[w] > 0) { -- card = *Wp[w]; -- o = SUIT(card); -- empty = (O[o] == NONE); -- if ((empty && (RANK(card) == PS_ACE)) || -- (!empty && (RANK(card) == O[o] + 1))) { -- mp->card_index = 0; -- mp->from = w; -- mp->to = o; -- mp->totype = O_Type; -- mp->turn_index = -1; -- mp->pri = 0; /* unused */ -- n++; -- mp++; -- -- /* If it's an automove, just do it. */ -- -- if (good_automove(o, RANK(card))) { -- *a = true; -- mp[-1].pri = 127; -- if (n != 1) { -- Possible[0] = mp[-1]; -- return 1; -- } -- return n; -- } -- } -- } -- } -- -- /* No more automoves, but remember if there were any moves out. */ -- -- *a = false; -- *numout = n; -- -- /* Check for moves from non-singleton W cells to one of any -- empty W cells. */ -+ "--load-config", "video-editing" -+}; - -- emptyw = -1; -- for (w = 0; w < Nwpiles; ++w) { -- if (Wlen[w] == 0) { -- emptyw = w; -- break; -- } -- } -- if (emptyw >= 0) { -- for (i = 0; i < Nwpiles + Ntpiles; ++i) { -- if (i == emptyw || Wlen[i] == 0) { -- continue; -- } -- bool allowed = false; -- if ( i < Nwpiles) -- allowed = true; -- if ( i >= Nwpiles ) -- allowed = true; -- if ( allowed ) { -- card = *Wp[i]; -- mp->card_index = 0; -- mp->from = i; -- mp->to = emptyw; -- mp->totype = W_Type; -- mp->turn_index = -1; -- if ( i >= Nwpiles ) -- mp->pri = Xparam[6]; -- else -- mp->pri = Xparam[3]; -- n++; -- mp++; -- } -- } -- } -- -- /* Check for moves from W to non-empty W cells. */ -- -- for (i = 0; i < Nwpiles + Ntpiles; ++i) { -- if (Wlen[i] > 0) { -- card = *Wp[i]; -- for (w = 0; w < Nwpiles; ++w) { -- if (i == w) { -- continue; -- } -- if (Wlen[w] > 0 && -- (RANK(card) == RANK(*Wp[w]) - 1 && -- suitable(card, *Wp[w]))) { -- mp->card_index = 0; -- mp->from = i; -- mp->to = w; -- mp->totype = W_Type; -- mp->turn_index = -1; -- if ( i >= Nwpiles ) -- mp->pri = Xparam[5]; -- else -- mp->pri = Xparam[4]; -- n++; -- mp++; -- } -- } -- } -- } -- -- /* Check for moves from W to one of any empty T cells. */ -- -- for (t = 0; t < Ntpiles; ++t) { -- if (!Wlen[t+Nwpiles]) { -- break; -- } -- } -+int FreecellSolver::get_cmd_line_arg_count() -+{ -+ return CMD_LINE_ARGS_NUM; -+} - -- if (t < Ntpiles) { -- for (w = 0; w < Nwpiles; ++w) { -- if (Wlen[w] > 0) { -- card = *Wp[w]; -- mp->card_index = 0; -- mp->from = w; -- mp->turn_index = -1; -- mp->to = t+Nwpiles; -- mp->totype = W_Type; -- mp->pri = Xparam[7]; -- n++; -- mp++; -- } -- } -- } -+const char * * FreecellSolver::get_cmd_line_args() -+{ -+ return freecell_solver_cmd_line_args; -+} - - -- return n; -+void FreecellSolver::setFcSolverGameParams() -+{ -+ /* -+ * I'm using the more standard interface instead of the depracated -+ * user_set_game one. I'd like that each function will have its -+ * own dedicated purpose. -+ * -+ * Shlomi Fish -+ * */ -+ freecell_solver_user_set_num_freecells(solver_instance,4); -+ freecell_solver_user_set_num_stacks(solver_instance,8); -+ freecell_solver_user_set_num_decks(solver_instance,1); -+ freecell_solver_user_set_sequences_are_built_by_type(solver_instance, FCS_SEQ_BUILT_BY_ALTERNATE_COLOR); -+ freecell_solver_user_set_sequence_move(solver_instance, 0); -+ freecell_solver_user_set_empty_stacks_filled_by(solver_instance, FCS_ES_FILLED_BY_ANY_CARD); - } -- -+#if 0 - void FreecellSolver::unpack_cluster( unsigned int k ) - { - /* Get the Out cells from the cluster number. */ -@@ -373,27 +281,13 @@ void FreecellSolver::unpack_cluster( unsigned int k ) - k >>= 4; - O[3] = k & 0xF; - } -+#endif - --bool FreecellSolver::isWon() --{ -- // maybe won? -- for (int o = 0; o < 4; ++o) { -- if (O[o] != PS_KING) { -- return false; -- } -- } -- -- return true; --} -- --int FreecellSolver::getOuts() --{ -- return O[0] + O[1] + O[2] + O[3]; --} - - FreecellSolver::FreecellSolver(const Freecell *dealer) -- : Solver() -+ : FcSolveSolver() - { -+#if 0 - Osuit[0] = PS_DIAMOND; - Osuit[1] = PS_CLUB; - Osuit[2] = PS_HEART; -@@ -402,12 +296,15 @@ FreecellSolver::FreecellSolver(const Freecell *dealer) - Nwpiles = 8; - Ntpiles = 4; - -+#endif -+ - deal = dealer; - } - - /* Read a layout file. Format is one pile per line, bottom to top (visible - card). Temp cells and Out on the last two lines, if any. */ - -+#if 0 - void FreecellSolver::translate_layout() - { - /* Read the workspace. */ -@@ -447,9 +344,78 @@ void FreecellSolver::translate_layout() - } - } - } -+#endif - - MoveHint FreecellSolver::translateMove( const MOVE &m ) - { -+ fcs_move_t move = m.fcs; -+ int cards = fcs_move_get_num_cards_in_seq(move); -+ PatPile *from = 0; -+ PatPile *to = 0; -+ -+ switch(fcs_move_get_type(move)) -+ { -+ case FCS_MOVE_TYPE_STACK_TO_STACK: -+ from = deal->store[fcs_move_get_src_stack(move)]; -+ to = deal->store[fcs_move_get_dest_stack(move)]; -+ break; -+ -+ case FCS_MOVE_TYPE_FREECELL_TO_STACK: -+ from = deal->freecell[fcs_move_get_src_freecell(move)]; -+ to = deal->store[fcs_move_get_dest_stack(move)]; -+ cards = 1; -+ break; -+ -+ case FCS_MOVE_TYPE_FREECELL_TO_FREECELL: -+ from = deal->freecell[fcs_move_get_src_freecell(move)]; -+ to = deal->freecell[fcs_move_get_dest_freecell(move)]; -+ cards = 1; -+ break; -+ -+ case FCS_MOVE_TYPE_STACK_TO_FREECELL: -+ from = deal->store[fcs_move_get_src_stack(move)]; -+ to = deal->freecell[fcs_move_get_dest_freecell(move)]; -+ cards = 1; -+ break; -+ -+ case FCS_MOVE_TYPE_STACK_TO_FOUNDATION: -+ from = deal->store[fcs_move_get_src_stack(move)]; -+ cards = 1; -+ to = 0; -+ break; -+ -+ case FCS_MOVE_TYPE_FREECELL_TO_FOUNDATION: -+ from = deal->freecell[fcs_move_get_src_freecell(move)]; -+ cards = 1; -+ to = 0; -+ } -+ Q_ASSERT(from); -+ Q_ASSERT(cards <= from->cards().count()); -+ Q_ASSERT(to || cards == 1); -+ KCard *card = from->cards()[from->cards().count() - cards]; -+ -+ if (!to) -+ { -+ PatPile *target = 0; -+ PatPile *empty = 0; -+ for (int i = 0; i < 4; ++i) { -+ KCard *c = deal->target[i]->topCard(); -+ if (c) { -+ if ( c->suit() == card->suit() ) -+ { -+ target = deal->target[i]; -+ break; -+ } -+ } else if ( !empty ) -+ empty = deal->target[i]; -+ } -+ to = target ? target : empty; -+ } -+ Q_ASSERT(to); -+ -+ return MoveHint(card, to, 0); -+ -+#if 0 - // this is tricky as we need to want to build the "meta moves" - - PatPile *frompile = nullptr; -@@ -486,8 +452,43 @@ MoveHint FreecellSolver::translateMove( const MOVE &m ) - - return MoveHint( card, target, m.pri ); - } -+#endif - } - -+void FreecellSolver::translate_layout() -+{ -+ strcpy(board_as_string, deal->solverFormat().toLatin1()); -+ -+ if (solver_instance) -+ { -+ freecell_solver_user_recycle(solver_instance); -+ solver_ret = FCS_STATE_NOT_BEGAN_YET; -+ } -+#if 0 -+ /* Read the workspace. */ -+ int total = 0; -+ -+ for ( int w = 0; w < 10; ++w ) { -+ int i = translate_pile(deal->store[w], W[w], 52); -+ Wp[w] = &W[w][i - 1]; -+ Wlen[w] = i; -+ total += i; -+ } -+ -+ for (int i = 0; i < 4; ++i) { -+ O[i] = -1; -+ KCard *c = deal->target[i]->top(); -+ if (c) { -+ total += 13; -+ O[i] = translateSuit( c->suit() ); -+ } -+ } -+#endif -+} -+ -+ -+ -+#if 0 - unsigned int FreecellSolver::getClusterNumber() - { - int i = O[0] + (O[1] << 4); -@@ -496,7 +497,9 @@ unsigned int FreecellSolver::getClusterNumber() - k |= i << 8; - return k; - } -+#endif - -+#if 0 - void FreecellSolver::print_layout() - { - int i, t, w, o; -@@ -519,3 +522,4 @@ void FreecellSolver::print_layout() - } - fprintf(stderr, "\nprint-layout-end\n"); - } -+#endif -diff --git a/patsolve/freecellsolver.h b/patsolve/freecellsolver.h -index 45ca063..99d1dbb 100644 ---- a/patsolve/freecellsolver.h -+++ b/patsolve/freecellsolver.h -@@ -19,16 +19,17 @@ - #ifndef FREECELLSOLVER_H - #define FREECELLSOLVER_H - --class Freecell; --#include "patsolve.h" -+#include "abstract_fc_solve_solver.h" - - constexpr auto Nwpiles = 8; - constexpr auto Ntpiles = 4; -+class Freecell; - --class FreecellSolver : public Solver -+class FreecellSolver : public FcSolveSolver - { - public: - explicit FreecellSolver(const Freecell *dealer); -+#if 0 - int good_automove(int o, int r); - int get_possible_moves(int *a, int *numout) Q_DECL_OVERRIDE; - bool isWon() Q_DECL_OVERRIDE; -@@ -40,8 +41,17 @@ public: - void translate_layout() Q_DECL_OVERRIDE; - void unpack_cluster( unsigned int k ) Q_DECL_OVERRIDE; - MoveHint translateMove(const MOVE &m) Q_DECL_OVERRIDE; -- -- void print_layout() Q_DECL_OVERRIDE; -+#endif -+ virtual void translate_layout(); -+#if 0 -+ virtual void unpack_cluster( unsigned int k ); -+#endif -+ virtual MoveHint translateMove(const MOVE &m); -+ virtual void setFcSolverGameParams(); -+ virtual int get_cmd_line_arg_count(); -+ virtual const char * * get_cmd_line_args(); -+#if 0 -+ virtual void print_layout(); - - int Nwpiles; /* the numbers we're actually using */ - int Ntpiles; -@@ -51,10 +61,11 @@ public: - card_t O[4]; /* output piles store only the rank or NONE */ - card_t Osuit[4]; - -- const Freecell *deal; - - static int Xparam[]; -+#endif - -+ const Freecell *deal; - }; - - #endif // FREECELLSOLVER_H -diff --git a/patsolve/patsolve.h b/patsolve/patsolve.h -index 03285d4..1c3a7c6 100644 ---- a/patsolve/patsolve.h -+++ b/patsolve/patsolve.h -@@ -33,6 +33,10 @@ - - #include - -+/* A card is represented as ( down << 6 ) + (suit << 4) + rank. */ -+ -+typedef quint8 card_t; -+ - struct POSITION { - POSITION *queue; /* next position in the queue */ - POSITION *parent; /* point back up the move stack */ -@@ -48,14 +52,15 @@ class MemoryManager; - template - class Solver : public SolverInterface - { -+ - public: - - Solver(); - virtual ~Solver(); -- ExitStatus patsolve( int max_positions = -1) final; -+ virtual ExitStatus patsolve( int max_positions = -1); -+ bool recursive(POSITION *pos = nullptr); - virtual void translate_layout() = 0; - virtual MoveHint translateMove(const MOVE &m ) = 0; -- - void stopExecution() final; - QList firstMoves() const final; - QList winMoves() const final; -@@ -126,8 +131,7 @@ protected: - POSITION *Stack = nullptr; - QMap recu_pos; - int max_positions; -- --private: -+protected: - QList m_firstMoves; - QList m_winMoves; - std::atomic_bool m_shouldEnd; -diff --git a/patsolve/simonsolver.cpp b/patsolve/simonsolver.cpp -index a9d640c..e75dcaa 100644 ---- a/patsolve/simonsolver.cpp -+++ b/patsolve/simonsolver.cpp -@@ -15,17 +15,26 @@ - * along with this program. If not, see . - */ - -+#include -+#include -+ -+#include "freecell-solver/fcs_user.h" -+#include "freecell-solver/fcs_cl.h" -+ - #include "simonsolver.h" - - #include "../simon.h" - - #include - -+const int CHUNKSIZE = 100; -+const long int MAX_ITERS_LIMIT = 200000; - - #define PRINT 0 - - /* These two routines make and unmake moves. */ - -+#if 0 - void SimonSolver::make_move(MOVE *m) - { - #if PRINT -@@ -136,13 +145,62 @@ void SimonSolver::undo_move(MOVE *m) - print_layout(); - #endif - } -+#endif -+ -+#define CMD_LINE_ARGS_NUM 4 -+static const char * freecell_solver_cmd_line_args[CMD_LINE_ARGS_NUM] = -+{ -+ "-g", "simple_simon", "--load-config", "the-last-mohican" -+}; -+ -+int SimonSolver::get_cmd_line_arg_count() -+{ -+ return CMD_LINE_ARGS_NUM; -+} -+ -+const char * * SimonSolver::get_cmd_line_args() -+{ -+ return freecell_solver_cmd_line_args; -+} -+ -+void SimonSolver::setFcSolverGameParams() -+{ -+ freecell_solver_user_apply_preset(solver_instance, "simple_simon"); -+} - -+#if 0 - /* Get the possible moves from a position, and store them in Possible[]. */ - - int SimonSolver::get_possible_moves(int *a, int *numout) - { - MOVE *mp; -+ int n; -+ -+ mp = Possible; -+ n = 0; -+ *a = 1; -+ -+ while (freecell_solver_user_get_moves_left(solver_instance)) -+ { -+ fcs_move_t move; -+ fcs_move_t * move_ptr; -+ if (!freecell_solver_user_get_next_move(solver_instance, &move)) { -+ move_ptr = new fcs_move_t; -+ *move_ptr = move; -+ mp->ptr = (void *)move_ptr; -+ mp++; -+ n++; -+ } -+ else -+ { -+ Q_ASSERT(0); -+ } -+ } -+ -+ *numout = n; -+ return n; - -+#if 0 - /* Check for moves from W to O. */ - - int n = 0; -@@ -301,8 +359,11 @@ int SimonSolver::get_possible_moves(int *a, int *numout) - } - - return n; -+#endif - } -+#endif - -+#if 0 - void SimonSolver::unpack_cluster( unsigned int k ) - { - // TODO: this only works for easy -@@ -314,7 +375,9 @@ void SimonSolver::unpack_cluster( unsigned int k ) - O[i] = -1; - } - } -+#endif - -+#if 0 - bool SimonSolver::isWon() - { - // maybe won? -@@ -324,7 +387,9 @@ bool SimonSolver::isWon() - - return true; - } -+#endif - -+#if 0 - int SimonSolver::getOuts() - { - int k = 0; -@@ -334,9 +399,10 @@ int SimonSolver::getOuts() - - return k; - } -+#endif - - SimonSolver::SimonSolver(const Simon *dealer) -- : Solver() -+ : FcSolveSolver() - { - deal = dealer; - } -@@ -346,6 +412,14 @@ card). Temp cells and Out on the last two lines, if any. */ - - void SimonSolver::translate_layout() - { -+ strcpy(board_as_string, deal->solverFormat().toLatin1()); -+ -+ if (solver_instance) -+ { -+ freecell_solver_user_recycle(solver_instance); -+ solver_ret = FCS_STATE_NOT_BEGAN_YET; -+ } -+#if 0 - /* Read the workspace. */ - int total = 0; - -@@ -364,8 +438,10 @@ void SimonSolver::translate_layout() - O[i] = translateSuit( c->suit() ); - } - } -+#endif - } - -+#if 0 - unsigned int SimonSolver::getClusterNumber() - { - unsigned int k = 0; -@@ -376,7 +452,9 @@ unsigned int SimonSolver::getClusterNumber() - } - return k; - } -+#endif - -+#if 0 - void SimonSolver::print_layout() - { - int i, w, o; -@@ -397,9 +475,57 @@ void SimonSolver::print_layout() - } - fprintf(stderr, "\nprint-layout-end\n"); - } -+#endif - - MoveHint SimonSolver::translateMove( const MOVE &m ) - { -+ fcs_move_t move = m.fcs; -+ int cards = fcs_move_get_num_cards_in_seq(move); -+ PatPile *from = 0; -+ PatPile *to = 0; -+ -+ switch(fcs_move_get_type(move)) -+ { -+ case FCS_MOVE_TYPE_STACK_TO_STACK: -+ from = deal->store[fcs_move_get_src_stack(move)]; -+ to = deal->store[fcs_move_get_dest_stack(move)]; -+ break; -+ -+ case FCS_MOVE_TYPE_SEQ_TO_FOUNDATION: -+ from = deal->store[fcs_move_get_src_stack(move)]; -+ cards = 13; -+ to = deal->target[fcs_move_get_foundation(move)]; -+ break; -+ -+ } -+ Q_ASSERT(from); -+ Q_ASSERT(cards <= from->cards().count()); -+ Q_ASSERT(to || cards == 1); -+ KCard *card = from->cards()[from->cards().count() - cards]; -+ -+ if (!to) -+ { -+ PatPile *target = 0; -+ PatPile *empty = 0; -+ for (int i = 0; i < 4; ++i) { -+ KCard *c = deal->target[i]->topCard(); -+ if (c) { -+ if ( c->suit() == card->suit() ) -+ { -+ target = deal->target[i]; -+ break; -+ } -+ } else if ( !empty ) -+ empty = deal->target[i]; -+ } -+ to = target ? target : empty; -+ } -+ -+ Q_ASSERT(to); -+ -+ return MoveHint(card, to, 0); -+ -+#if 0 - Q_ASSERT( m.from < 10 && m.to < 10 ); - - PatPile *frompile = deal->store[m.from]; -@@ -414,4 +540,5 @@ MoveHint SimonSolver::translateMove( const MOVE &m ) - - Q_ASSERT( m.to < 10 ); - return MoveHint( card, deal->store[m.to], m.pri ); -+#endif - } -diff --git a/patsolve/simonsolver.h b/patsolve/simonsolver.h -index 2d57dda..4a417b1 100644 ---- a/patsolve/simonsolver.h -+++ b/patsolve/simonsolver.h -@@ -18,29 +18,37 @@ - #ifndef SIMONSOLVER_H - #define SIMONSOLVER_H - --#include "patsolve.h" -+#include "abstract_fc_solve_solver.h" -+#include "simon.h" - class Simon; - - --class SimonSolver : public Solver<10> -+class SimonSolver : public FcSolveSolver - { - public: - explicit SimonSolver(const Simon *dealer); -+#if 0 - int get_possible_moves(int *a, int *numout) Q_DECL_OVERRIDE; - bool isWon() Q_DECL_OVERRIDE; - void make_move(MOVE *m) Q_DECL_OVERRIDE; - void undo_move(MOVE *m) Q_DECL_OVERRIDE; - int getOuts() Q_DECL_OVERRIDE; - unsigned int getClusterNumber() Q_DECL_OVERRIDE; -- void translate_layout() Q_DECL_OVERRIDE; -+#endif -+ virtual void translate_layout() Q_DECL_OVERRIDE; -+ virtual MoveHint translateMove(const MOVE &m) Q_DECL_OVERRIDE; -+#if 0 - void unpack_cluster( unsigned int k ) Q_DECL_OVERRIDE; -- MoveHint translateMove(const MOVE &m) Q_DECL_OVERRIDE; -- - void print_layout() Q_DECL_OVERRIDE; -+#endif -+ virtual void setFcSolverGameParams(); - -+ virtual int get_cmd_line_arg_count(); -+ virtual const char * * get_cmd_line_args(); -+#if 0 - /* Names of the cards. The ordering is defined in pat.h. */ -- - int O[4]; -+#endif - const Simon *deal; - }; - -diff --git a/patsolve/solverinterface.h b/patsolve/solverinterface.h -index d99d3b8..77fd410 100644 ---- a/patsolve/solverinterface.h -+++ b/patsolve/solverinterface.h -@@ -4,6 +4,7 @@ - #include - - #include "../hint.h" -+#include "freecell-solver/fcs_user.h" - - - /* A card is represented as ( down << 6 ) + (suit << 4) + rank. */ -@@ -22,6 +23,7 @@ public: - PileType totype; - signed char pri; /* move priority (low priority == low value) */ - int turn_index; /* turn the card index */ -+ fcs_move_t fcs; /* A Freecell Solver move. */ - - bool operator<( const MOVE &m) const - { -diff --git a/pileutils.cpp b/pileutils.cpp -index 1e3da3e..609c716 100644 ---- a/pileutils.cpp -+++ b/pileutils.cpp -@@ -48,6 +48,33 @@ bool isSameSuitAscending( const QList & cards ) - return true; - } - -+int countSameSuitDescendingSequences( const QList & cards ) -+{ -+ if ( cards.size() <= 1 ) -+ return 0; -+ -+ int suit = cards.first()->suit(); -+ int lastRank = cards.first()->rank(); -+ -+ int count = 1; -+ -+ for( int i = 1; i < cards.size(); ++i ) -+ { -+ --lastRank; -+ -+ if ( cards[i]->rank() != lastRank ) -+ return -1; -+ -+ if ( cards[i]->suit() != suit ) -+ { -+ count++; -+ suit = cards[i]->suit(); -+ } -+ } -+ return count; -+} -+ -+ - - bool isSameSuitDescending( const QList & cards ) - { -@@ -121,3 +148,37 @@ bool checkAddAlternateColorDescendingFromKing( const QList & oldCards, c - && newCards.first()->rank() == oldCards.last()->rank() - 1; - } - -+QString suitToString(int s) { -+ switch (s) { -+ case KCardDeck::Clubs: -+ return "C"; -+ case KCardDeck::Hearts: -+ return "H"; -+ case KCardDeck::Diamonds: -+ return "D"; -+ case KCardDeck::Spades: -+ return "S"; -+ default: -+ exit(-1); -+ } -+ return QString(); -+} -+ -+QString rankToString(int r) -+{ -+ switch (r) { -+ case KCardDeck::King: -+ return "K"; -+ case KCardDeck::Ace: -+ return "A"; -+ case KCardDeck::Jack: -+ return "J"; -+ case KCardDeck::Queen: -+ return "Q"; -+ case KCardDeck::Ten: -+ return "T"; -+ default: -+ return QString::number(r); -+ } -+} -+ -diff --git a/pileutils.h b/pileutils.h -index 2fa1657..faa8c40 100644 ---- a/pileutils.h -+++ b/pileutils.h -@@ -26,9 +26,13 @@ class KCard; - bool isSameSuitAscending( const QList & cards ); - bool isSameSuitDescending( const QList & cards ); - bool isAlternateColorDescending( const QList & cards ); -+int countSameSuitDescendingSequences( const QList & cards ); - - bool checkAddSameSuitAscendingFromAce( const QList & oldCards, const QList & newCards ); - bool checkAddAlternateColorDescending( const QList & oldCards, const QList & newCards ); - bool checkAddAlternateColorDescendingFromKing( const QList & oldCards, const QList & newCards ); - -+extern QString suitToString(int s); -+extern QString rankToString(int r); -+ - #endif -diff --git a/simon.cpp b/simon.cpp -index 8e3ef10..834dd55 100644 ---- a/simon.cpp -+++ b/simon.cpp -@@ -111,24 +111,70 @@ bool Simon::checkAdd(const PatPile * pile, const QList & oldCards, const - { - if (pile->pileRole() == PatPile::Tableau) - { -- return oldCards.isEmpty() -- || oldCards.last()->rank() == newCards.first()->rank() + 1; -+ if (! (oldCards.isEmpty() -+ || oldCards.last()->rank() == newCards.first()->rank() + 1 )) -+ { -+ return false; -+ } -+ -+ int seqs_count = countSameSuitDescendingSequences(newCards); -+ -+ if (seqs_count < 0) -+ return false; -+ -+ // This is similar to the supermoves of Freecell - we can use empty -+ // columns to temporarily hold intermediate sub-sequences which are -+ // not the same suit - only a "false" parent. -+ // Shlomi Fish -+ -+ int empty_piles_count = 0; -+ -+ for (int i = 0; i < 10; ++i ) -+ if (store[i]->isEmpty() && ( store[i]->index() != pile->index() )) -+ empty_piles_count++; -+ -+ return (seqs_count <= (1 << empty_piles_count)); - } - else - { - return oldCards.isEmpty() - && newCards.first()->rank() == KCardDeck::King -- && newCards.last()->rank() == KCardDeck::Ace; -+ && newCards.last()->rank() == KCardDeck::Ace -+ && isSameSuitDescending(newCards); - } - } - - bool Simon::checkRemove(const PatPile * pile, const QList & cards) const - { -- return pile->pileRole() == PatPile::Tableau -- && isSameSuitDescending(cards); -+ if (pile->pileRole() != PatPile::Tableau) -+ return false; -+ -+ int seqs_count = countSameSuitDescendingSequences(cards); -+ -+ return (seqs_count >= 0); - } - -+QString Simon::solverFormat() const -+{ -+ QString output; -+ QString tmp; -+ for (int i = 0; i < 4 ; i++) { -+ if (target[i]->isEmpty()) -+ continue; -+ tmp += suitToString(target[i]->topCard()->suit()) + "-K "; -+ } -+ if (!tmp.isEmpty()) -+ output += QString::fromLatin1("Foundations: %1\n").arg(tmp); - -+ for (int i = 0; i < 10 ; i++) -+ { -+ QList cards = store[i]->cards(); -+ for (QList::ConstIterator it = cards.begin(); it != cards.end(); ++it) -+ output += rankToString((*it)->rank()) + suitToString((*it)->suit()) + ' '; -+ output += '\n'; -+ } -+ return output; -+} - - static class SimonDealerInfo : public DealerInfo - { -diff --git a/simon.h b/simon.h -index 83d10ab..d816f27 100644 ---- a/simon.h -+++ b/simon.h -@@ -57,6 +57,7 @@ private: - PatPile* store[10]; - PatPile* target[4]; - -+ virtual QString solverFormat() const; - friend class SimonSolver; - }; - --- -cgit v0.11.2 - -- cgit v1.2.3-65-gdbad