Commit 96474eba authored by Michael Lang's avatar Michael Lang Committed by Albert Astals Cid
Browse files

Added several Freecell game variants:

Baker's Game
Eight Off
Forecell
Seahaven Towers
Other custom configurations
parent 0e6e7d28
......@@ -333,6 +333,28 @@ The maximum amount of cards you can move is calculated by:
(#{free cells} + 1) * 2<superscript>#{free piles}</superscript>
</para></sidebar>
<variablelist>
<varlistentry><term>Variations:</term>
<listitem>
<para>
- Baker's Game is like Freecell, but the piles are built down by suit.
</para>
<para>
- Eight Off is like Freecell, but the piles are built down by suit. You have 8 reserves and only kings can fill empty spaces. Four reserves are filled at game start.
</para>
<para>
- Forecell is like Freecell, but the reserves are filled at game start, and only kings can fill empty spaces.
</para>
<para>
- Seahaven Towers is like Freecell, but with 10 piles which are built down by suit, and only kings can fill empty spaces. Two reserves are filled at game start.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
To solve this game it is recommended to grab the cards out of the playing
sequences in the same order they have to be put into the foundation (first the
......
......@@ -56,7 +56,7 @@ public:
KlondikeDrawOneId = 0,
GrandfatherId = 1,
AcesUpId = 2,
FreecellId = 3,
FreecellGeneralId = 3,
Mod3Id = 5,
GypsyId = 7,
FortyAndEightId = 8,
......@@ -75,7 +75,13 @@ public:
BakersDozenSpanishId= 21,
BakersDozenCastlesId= 22,
BakersDozenPortugueseId= 23,
BakersDozenCustomId = 24
BakersDozenCustomId = 24,
FreecellId = 30,
FreecellBakersId = 31,
FreecellEightOffId = 32,
FreecellForeId = 33,
FreecellSeahavenId = 34,
FreecellCustomId = 39
};
DealerInfo( const QByteArray & untranslatedBaseName, int baseId );
......
This diff is collapsed.
......@@ -41,6 +41,7 @@
#include "dealer.h"
#include "hint.h"
class KSelectAction;
class Freecell : public DealerScene
{
......@@ -49,13 +50,18 @@ class Freecell : public DealerScene
public:
explicit Freecell( const DealerInfo * di );
void initialize() override;
void mapOldId(int id) override;
int oldId() const override;
QList<QAction*> configActions() const override;
protected:
bool checkAdd(const PatPile * pile, const QList<KCard*> & oldCards, const QList<KCard*> & newCards) const override;
bool checkRemove(const PatPile * pile, const QList<KCard*> & cards) const override;
void cardsDroppedOnPile( const QList<KCard*> & cards, KCardPile * pile ) override;
void restart( const QList<KCard*> & cards ) override;
QList<MoveHint> getHints() override;
private Q_SLOTS:
void gameTypeChanged();
protected Q_SLOTS:
bool tryAutomaticMove( KCard * c ) override;
......@@ -63,10 +69,34 @@ protected Q_SLOTS:
private:
bool canPutStore( const KCardPile * pile, const QList<KCard*> & cards ) const;
void configOptions();
void setOptions(int v);
void getSavedOptions();
void setSavedOptions();
void matchVariant();
virtual QString solverFormat() const;
PatPile* store[8];
PatPile* freecell[4];
PatPile* target[4];
PatPile* store[12];
PatPile* freecell[8];
PatPile* target[12];
KSelectAction *options;
int m_variation;
KSelectAction *m_emptyStackFillOption;
int m_emptyStackFill;
KSelectAction *m_sequenceBuiltByOption;
int m_sequenceBuiltBy;
KSelectAction *m_reservesOption;
int m_reserves;
KSelectAction *m_stacksOption;
int m_stacks;
KSelectAction *m_decksOption;
int m_decks;
friend class FreecellSolver;
};
......
......@@ -35,6 +35,21 @@
<entry name="FreecellSolverIterationsLimit" key="FreecellSolverIterationsLimit" type="Int">
<default>200000</default>
</entry>
<entry name="FreecellEmptyStackFill" key="FreecellEmptyStackFill" type="Int">
<default>0</default>
</entry>
<entry name="FreecellSequenceBuiltBy" key="FreecellSequenceBuiltBy" type="Int">
<default>0</default>
</entry>
<entry name="FreecellReserves" key="FreecellReserves" type="Int">
<default>4</default>
</entry>
<entry name="FreecellStacks" key="FreecellStacks" type="Int">
<default>2</default>
</entry>
<entry name="FreecellDecks" key="FreecellDecks" type="Int">
<default>0</default>
</entry>
<entry name="SimpleSimonSolverIterationsLimit" key="SimpleSimonSolverIterationsLimit" type="Int">
<default>200000</default>
</entry>
......
......@@ -21,7 +21,7 @@
// own
#include "patsolve.h"
struct FcSolveSolver : public Solver<13>
struct FcSolveSolver : public Solver<20>
{
public:
FcSolveSolver();
......
......@@ -21,6 +21,7 @@
// own
#include "patsolve-config.h"
#include "../freecell.h"
#include "../settings.h"
// freecell-solver
#include "freecell-solver/fcs_user.h"
#include "freecell-solver/fcs_cl.h"
......@@ -28,6 +29,12 @@
#include <cstdlib>
#include <cstring>
int m_reserves = Settings::freecellReserves();
int m_stacks = Settings::freecellStacks() + 6;
int m_decks = Settings::freecellDecks() + 1;
int m_emptyStackFill = Settings::freecellEmptyStackFill();
int m_sequenceBuiltBy = Settings::freecellSequenceBuiltBy();
const int CHUNKSIZE = 100;
const long int MAX_ITERS_LIMIT = 200000;
......@@ -202,7 +209,7 @@ int FreecellSolver::good_automove(int o, int r)
return true;
}
for (int foundation_idx = 0; foundation_idx < 4; ++foundation_idx) {
for (int foundation_idx = 0; foundation_idx < 4 * m_decks; ++foundation_idx) {
KCard *c = deal->target[foundation_idx]->topCard();
if (c) {
O[translateSuit( c->suit() ) >> 4] = c->rank();
......@@ -210,7 +217,7 @@ int FreecellSolver::good_automove(int o, int r)
}
/* Check the Out piles of opposite color. */
for (int i = 1 - (o & 1); i < 4; i += 2) {
for (int i = 1 - (o & 1); i < 4 * m_decks; i += 2) {
if (O[i] < r - 1) {
#if 1 /* Raymond's Rule */
......@@ -221,7 +228,7 @@ int FreecellSolver::good_automove(int o, int r)
the loop variable i. We return here and never
make it back to the outer loop. */
for (i = 1 - (o & 1); i < 4; i += 2) {
for (i = 1 - (o & 1); i < 4 * m_decks; i += 2) {
if (O[i] < r - 2) {
return false;
}
......@@ -250,7 +257,7 @@ int FreecellSolver::get_possible_moves(int *a, int *numout)
int n = 0;
mp = Possible;
for (w = 0; w < Nwpiles + Ntpiles; ++w) {
for (w = 0; w < m_stacks + m_reserves; ++w) {
if (Wlen[w] > 0) {
card = *Wp[w];
int out_suit = SUIT(card);
......@@ -316,12 +323,24 @@ void FreecellSolver::setFcSolverGameParams()
*
* 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);
m_reserves = Settings::freecellReserves();
freecell_solver_user_set_num_freecells(solver_instance, m_reserves);
m_stacks = Settings::freecellStacks() + 6;
freecell_solver_user_set_num_stacks(solver_instance, m_stacks);
m_decks = Settings::freecellDecks() + 1;
freecell_solver_user_set_num_decks(solver_instance, m_decks);
//FCS_ES_FILLED_BY_ANY_CARD = 0, FCS_ES_FILLED_BY_KINGS_ONLY = 1,FCS_ES_FILLED_BY_NONE = 2
m_emptyStackFill = Settings::freecellEmptyStackFill();
freecell_solver_user_set_empty_stacks_filled_by(solver_instance, m_emptyStackFill);
//FCS_SEQ_BUILT_BY_ALTERNATE_COLOR = 0, FCS_SEQ_BUILT_BY_SUIT = 1, FCS_SEQ_BUILT_BY_RANK = 2
m_sequenceBuiltBy = Settings::freecellSequenceBuiltBy();
freecell_solver_user_set_sequences_are_built_by_type(solver_instance, m_sequenceBuiltBy);
}
#if 0
void FreecellSolver::unpack_cluster( unsigned int k )
......@@ -409,7 +428,7 @@ MoveHint FreecellSolver::translateMove( const MOVE &m )
{
PatPile *target = nullptr;
PatPile *empty = nullptr;
for (int i = 0; i < 4; ++i) {
for (int i = 0; i < 4 * m_decks; ++i) {
KCard *c = deal->target[i]->topCard();
if (c) {
if ( c->suit() == card->suit() )
......@@ -431,17 +450,17 @@ MoveHint FreecellSolver::translateMove( const MOVE &m )
// this is tricky as we need to want to build the "meta moves"
PatPile *frompile = nullptr;
if ( m.from < 8 )
if ( m.from < m_stacks )
frompile = deal->store[m.from];
else
frompile = deal->freecell[m.from-8];
frompile = deal->freecell[m.from - m_stacks];
KCard *card = frompile->at( frompile->count() - m.card_index - 1);
if ( m.totype == O_Type )
{
PatPile *target = nullptr;
PatPile *empty = nullptr;
for (int i = 0; i < 4; ++i) {
for (int i = 0; i < 4 * m_decks; ++i) {
KCard *c = deal->target[i]->topCard();
if (c) {
if ( c->suit() == card->suit() )
......@@ -457,10 +476,10 @@ MoveHint FreecellSolver::translateMove( const MOVE &m )
return MoveHint( card, target, m.pri );
} else {
PatPile *target = nullptr;
if ( m.to < 8 )
if ( m.to < m_stacks )
target = deal->store[m.to];
else
target = deal->freecell[m.to-8];
target = deal->freecell[m.to - m_stacks];
return MoveHint( card, target, m.pri );
}
......@@ -495,32 +514,32 @@ void FreecellSolver::translate_layout()
/* Read the workspace. */
int total = 0;
for ( int w = 0; w < 8; ++w ) {
int i = translate_pile(deal->store[w], W[w], 52);
for ( int w = 0; w < m_stacks; ++w ) {
int i = translate_pile(deal->store[w], W[w], 52 * m_decks);
Wp[w] = &W[w][i - 1];
Wlen[w] = i;
total += i;
if (w == Nwpiles) {
if (w == m_stacks) {
break;
}
}
/* Temp cells may have some cards too. */
for (int w = 0; w < Ntpiles; ++w)
for (int w = 0; w < m_reserves; ++w)
{
int i = translate_pile( deal->freecell[w], W[w+Nwpiles], 52 );
Wp[w+Nwpiles] = &W[w+Nwpiles][i-1];
Wlen[w+Nwpiles] = i;
int i = translate_pile( deal->freecell[w], W[w+m_stacks], 52 * m_decks );
Wp[w+m_stacks] = &W[w+m_stacks][i-1];
Wlen[w+m_stacks] = i;
total += i;
}
/* Output piles, if any. */
for (int i = 0; i < 4; ++i) {
for (int i = 0; i < 4 * m_decks; ++i) {
O[i] = NONE;
}
if (total != 52) {
for (int i = 0; i < 4; ++i) {
if (total != 52 * m_decks) {
for (int i = 0; i < 4 * m_decks; ++i) {
KCard *c = deal->target[i]->topCard();
if (c) {
O[translateSuit( c->suit() ) >> 4] = c->rank();
......
......@@ -64,7 +64,7 @@ public:
static int Xparam[];
#endif
card_t O[4]; /* output piles store only the rank or NONE */
card_t O[12]; /* output piles store only the rank or NONE */
const Freecell *deal;
};
......
......@@ -990,4 +990,5 @@ template class Solver<34>;
template class Solver<15>;
template class Solver<7>;
template class Solver<13>;
template class Solver<20>;
template class Solver<Nwpiles + Ntpiles>;
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment