FC-SOLVE(6)

๐Ÿ’– FC-SOLVE(6) ๐Ÿ’–

โœจ NAME โœจ

fc-solve โ€” automated solver for Freecell and related Solitiare variants


๐ŸŒธ INTRODUCTION ๐ŸŒธ

okay so this is Freecell Solver version 6.16.x, and it's literally a program that automatically solves most layouts of Freecell, and similar Solitaire variants as well as those of Simple Simon. slay.

Freecell Solver is distributed under the MIT/Expat License ( http://en.wikipedia.org/wiki/MIT_License ), a free, permissive, open-source license. ๐Ÿ’–

Note that the Freecell Solver source and Win32 binary distributions do not provide a graphical user-interface (GUI) and are primarily meant to be used by Solitaire researchers and software developers. If youโ€™re looking for a suitable GUI based on Freecell Solver, see our links at: http://fc-solve.shlomifish.org/links.html#front_ends

I hope youโ€™ll enjoy using Freecell Solver, and make the best of it. ๐Ÿซถ

โ€” Shlomi Fish ( http://www.shlomifish.org/ )


๐Ÿ› ๏ธ BUILDING ๐Ÿ› ๏ธ

Read the file INSTALL.txt for information on how to do that. no cap.


๐ŸŽ€ USAGE ๐ŸŽ€

The program is called fc-solve. You invoke it like this:

fc-solve board_file

board_file is the filename with a valid Freecell startup board. The file is built as follows:

  • It has the 8 Freecell stacks.
  • Each stack contains its cards separated by a whitespace and terminated with a newline character ( itโ€™s important that the last stack will also be terminated with a newline !). The cards in the line are ordered from the topmost card (= the card right on the virtual table and the one with the most cards placed on it) in the left, to the bottommost card in the right (= the card with no other cards placed on it).
  • A card string contains the rank of the card followed by its suit. The card number is one of: A,1,2,3,4,5,6,7,8,9,T,J,Q,K. Alternatively, 10 can be used instead of T, but using that is discouraged and is only supported for backward compatibility. The card suit is one of: H,S,D,C (standing for Hearts, Spades, Diamonds and Clubs respectively).

Here is an example board: (PySol/Microsoft board No. 24)

4C 2C 9C 8C QS 4S 2H
5H QH 3C AC 3H 4H QD
QC 9S 6H 9H 3S KS 3D
5D 2S JC 5C JH 6D AS
2D KD TH TC TD 8D
7H JS KH TS KC 7C
AH 5S 6S AD 8H JD
7S 6C 7D 4D 8S 9D

Visually, it appears as this:

[Freecell Deal No. 24]

As can be seen, the four of clubs (4C), five of hearts (5H), etc. are at the bottom of the stacks and the start of the lines in the board input.

And another one: (PySol board No. 198246790)

KD JH 5H 7D 9H KC 9D
3H JD 5D 8H QH 7H 2D
4D 3S QC 3C 6S QS KS
TC 9S 6D 9C QD 8S TD
TS 8C 7S TH 2C AS
8D AC AH 4H JC 4C
6H 7C 4S 5S 5C JS
AD KH 6C 2H 3D 2S

Starting from Freecell Solver 3.14.x, a stack can also start with a leading colon (:). This is to allow input from states as output by Freecell Solver using the -p option.

You can specify the contents of the freecells by prefixing the line with FC: or with Freecells:. For example:

FC: 3H QC

will specify that the cards 3 of hearts and queen of clubs are present in the freecells. To specify an empty freecell use a - as its designator.

If thereโ€™s another FC: line, the previous line will be overridden.

You can specify the contents of the foundations by prefixing the line with Founds: or with Foundations: and then using a format as follows:

Founds: H-5 C-A S-0 D-K

Hence, the suit ID followed by a dash followed by the card number in the foundation. A suit that is not present will be assumed to be 0. Again, if thereโ€™s more than one line like that, then the previous lines will be ignored and overridden.

The program will stop processing the input as soon as it read 8 lines of standard stacks. Therefore, it is recommended that the foundations and freecells lines will come at the beginning of the file.

The program will process the board and try to solve it. If it succeeds it will output the states from the initial board to its final solution to the standard output. If it fails, it will notify it.

For information about the various command-line switches that Freecell Solver accepts, read the USAGE.txt file in this directory.

To solve Simple Simon boards append --game simple_simon right after the fc-solve program name.


๐ŸŒˆ THE BOARD GENERATION PROGRAMS ๐ŸŒˆ

Several programs which can generate the initial boards of various Freecell implementations can be found in the board_gen/ sub-directory. Read the README.txt file there for details on how they can be compiled and used.

In any case, they can save you the time of inputting the board yourself. ๐Ÿ’…


๐Ÿ’œ SOME COMPLETE EXAMPLES FOR LAYOUTS ๐Ÿ’œ

A layout in the middle of the MS Freecell deal No. 109 solution:

Foundations: H-6 C-9 D-2 S-0
Freecells:  QS  3S  2S  KD
: 8H 3D
: KS QD JC
: AS 8D TD 7D JH TS 9D
: 7S 6D
: 5S
: KH QC JD TC 9H 8S 7H 6S 5D 4S
: KC QH JS TH 9S
: 4D

Similar, but with an empty Freecell:

Foundations: H-6 C-9 D-2 S-0
Freecells:  QS  3S  -  KD
: 8H 3D 2S
: KS QD JC
: AS 8D TD 7D JH TS 9D
: 7S 6D
: 5S
: KH QC JD TC 9H 8S 7H 6S 5D 4S
: KC QH JS TH 9S
: 4D

Likewise, only without leading colons where unnecessary:

Foundations: H-6 C-9 D-2 S-0
Freecells:  QS  3S  -  KD
8H 3D 2S
KS QD JC
AS 8D TD 7D JH TS 9D
7S 6D
5S
KH QC JD TC 9H 8S 7H 6S 5D 4S
KC QH JS TH 9S
4D

๐Ÿ”ฅ HOW TO READ THE SOLUTIONS ๐Ÿ”ฅ

The file USAGE.txt covers all of Freecell Solverโ€™s command line options, but it may be too exhaustive for casual users. As a result, here is a shorter tutorial. First of all whenever invoking fc-solve one should add the flags -p -t -sam -sel which will make the solution easier to understand. Then, assuming the board could be successfully solved, one will be given the layouts in the solution (in the format given above) vis-a-vis with the moves as the string. Note that the indexes of the resources given in the moves are 0-based rather than the more natural 1-based notation.


๐Ÿ‘‘ THE PROGRAMS ๐Ÿ‘‘

Most command-line switches have two versions:

  • A short POSIX one which is a dash followed by a letter or a few. This option must come standalone and not clustered: -sam is not equivalent to specifying -s, -a and -m.
  • A long switch which is two dashes followed by the command string. For example: --prelude, --st-name.

If command line arguments have parameters, they are followed in separate parameters - Freecell Solver wonโ€™t recognise a parameter preceded by an equal sign. --st-name=myname is invalid, while --st-name myname is OK.

๐ŸŒธ The Scope of the Options ๐ŸŒธ

The scope of the options is mentioned along with them. Options can be:

  1. Global - affects all the soft-threads.
  2. Instance-specific - affects an instance (separated by the --next-instance option below). Each instance consists of several flares.
  3. Flare-specific - affects the current flare (separated by the --next-flare option below. Each flare consists of several hard threads.
  4. Hard-thread-specific - affects the current hard thread (separated by the --next-hard-thread option below. Each hard thread consists of several soft threads.
  5. Soft-thread-specific - affects only the current soft thread.

๐Ÿซถ GETTING HELP ๐Ÿซถ

  • -h, --help โ€” Global โ€” This option displays a help text on the screen. This help gives a help display summarizing some ways to use the program and get more help.
  • --version โ€” Global โ€” This option displays the version number of the components that make the executable (and then exits).
  • --help-configs โ€” Global โ€” Some help on the various configurations of Freecell Solver.
  • --help-options โ€” Global โ€” A help screen giving an overview of all available options.
  • --help-real-help โ€” Global โ€” Explains how to change the default help screen to a different one.
  • --help-short-sol โ€” Global โ€” How to generate shorter solutions.
  • --help-summary โ€” Global โ€” The default help screen.

๐ŸŒˆ OUTPUT OPTIONS ๐ŸŒˆ

okay bestie, this is where you get to pick how fc-solve shows you the tea. every single one of these is Global, which means it applies to the whole run, not to some lil sub-thing. let's get into it ๐Ÿ’…


โœจ -p, --parseable-output โœจ

Global

this one is giving machine-readable main character energy. it shows the columns in a format that's way easier for text-processing programs like grep or perl to chew on. specifically: the freecells show up all on one line, and the foundations get their own separate line. plus, each column gets printed horizontally, on its own line, and starts with a :.

โœจ -t, --display-10-as-t โœจ

Global

instead of showing the 10 cards as 10, this displays them as a capital T. so everything lines up all pretty and aligned. โœจ

for example, here's a command line using both -p and -t:

$ pi-make-microsoft-freecell-board 24 | fc-solve -p -t
-=-=-=-=-=-=-=-=-=-=-=-

Foundations: H-0 C-0 D-0 S-0
Freecells:
: 4C 2C 9C 8C QS 4S 2H
: 5H QH 3C AC 3H 4H QD
: QC 9S 6H 9H 3S KS 3D
: 5D 2S JC 5C JH 6D AS
: 2D KD TH TC TD 8D
: 7H JS KH TS KC 7C
: AH 5S 6S AD 8H JD
: 7S 6C 7D 4D 8S 9D

====================

Foundations: H-0 C-0 D-0 S-A
Freecells:
: 4C 2C 9C 8C QS 4S 2H
: 5H QH 3C AC 3H 4H QD
: QC 9S 6H 9H 3S KS 3D
: 5D 2S JC 5C JH 6D
: 2D KD TH TC TD 8D
: 7H JS KH TS KC 7C
: AH 5S 6S AD 8H JD
: 7S 6C 7D 4D 8S 9D

โœจ -c, --canonized-order-output โœจ

Global

so Freecell Solver lowkey re-arranges the stacks and freecells in a given state based on their first card. it keeps their actual position stashed away somewhere separate, but internally it vibes with the canonized place instead. use this option if you want Freecell Solver to display them in that order.

โš ๏ธ fair warning bestie: that way, the place of a given stack in the board will not be preserved throughout the solution. so if you're tracking positions, that's gonna get messy. ๐Ÿ˜ญ

โœจ -m, --display-moves โœจ

Global

this one shows you the moves instead of the intermediate states. each move gets its own separate line, in a format that's human-readable but can also be parsed and analyzed by a computer program โ€” with some effort on the programmer's part, ngl.

for example:

$ pi-make-microsoft-freecell-board 24 | fc-solve -m | head -30
-=-=-=-=-=-=-=-=-=-=-=-

Move a card from stack 3 to the foundations

====================

Move a card from stack 6 to freecell 0

====================

Move a card from stack 6 to freecell 1

โœจ -sn, --standard-notation โœจ

Global

displays the moves in standard notation, where every move is exactly two characters and there are ten moves in a line. ๐Ÿ’…

obvi this option only becomes apparent if display moves is specified โ€” it does not implicitly specify it, so don't come for me.

for more info on standard notation, there's this web-page:

http://www.solitairelaboratory.com/solutioncatalog.html

โœจ -snx, --standard-notation-extended โœจ

Global

basically the same as the previous one, except when a sequence move is made to an empty stack with more than one card in the sequence, the move gets followed with "v" and the number of cards moved in hexadecimal. fancy fr fr. ๐Ÿ”ฅ

โœจ -sam, --display-states-and-moves โœจ

Global

this one serves both the intermediate states and the moves needed to get from one to another. and yes, the standard notation option applies to it too. โœจ

$ pi-make-microsoft-freecell-board 24 | fc-solve -sam -p -t | head -50
-=-=-=-=-=-=-=-=-=-=-=-

Foundations: H-0 C-0 D-0 S-0
Freecells:
: 4C 2C 9C 8C QS 4S 2H
: 5H QH 3C AC 3H 4H QD
: QC 9S 6H 9H 3S KS 3D
: 5D 2S JC 5C JH 6D AS
: 2D KD TH TC TD 8D
: 7H JS KH TS KC 7C
: AH 5S 6S AD 8H JD
: 7S 6C 7D 4D 8S 9D

====================

Move a card from stack 3 to the foundations

Foundations: H-0 C-0 D-0 S-A
Freecells:
: 4C 2C 9C 8C QS 4S 2H
: 5H QH 3C AC 3H 4H QD
: QC 9S 6H 9H 3S KS 3D
: 5D 2S JC 5C JH 6D
: 2D KD TH TC TD 8D
: 7H JS KH TS KC 7C
: AH 5S 6S AD 8H JD
: 7S 6C 7D 4D 8S 9D

====================

Move a card from stack 6 to freecell 0

Foundations: H-0 C-0 D-0 S-A
Freecells:  JD
: 4C 2C 9C 8C QS 4S 2H
: 5H QH 3C AC 3H 4H QD
: QC 9S 6H 9H 3S KS 3D
: 5D 2S JC 5C JH 6D
: 2D KD TH TC TD 8D
: 7H JS KH TS KC 7C
: AH 5S 6S AD 8H
: 7S 6C 7D 4D 8S 9D

====================

Move a card from stack 6 to freecell 1

โœจ -pi, --display-parent-iter โœจ

Global

this option โ€” assuming the -s and -i options are specified โ€” will also show you the iteration index of the state that the current state was derived from. super useful for BeFS (the so-called a-star) or BFS scans. ๐Ÿ‘‘

โœจ -o [filename], --output [filename] โœจ

Global

outputs to a file instead of standard output. so, like:

$ fc-solve -o 2405.solution.txt 2405.board

this will put the solution to the file in 2405.board into the file 2405.solution.txt. and you can do the exact same thing with:

$ fc-solve --output 2405.solution.txt 2405.board

โœจ -sel, --show-exceeded-limits โœจ

Global

this shows a different status message โ€” "Iterations count exceeded." โ€” instead of "I could not solve this game." when the iterations count was exceeded.

this one is recommended, because "I could not solve this game." can also mean that the entire game graph was fully traversed (within the limitations of the specified moves' types), and so no solution is possible. two very different moods, bestie, and you deserve to know which one you're in. ๐Ÿ˜ญ

this option is not the default, to retain compatibility with previous versions of Freecell Solver, and was added in version 3.12.0 of fc-solve.

โœจ -hoi, --hint-on-intractable โœจ

Global

presents the moves to the intermediate reached state, if the maximal number of iterations was reached without a conclusion (= "intractable"). so when it's stuck, it still gives you a lil hint. ๐Ÿซถ

this option is not the default, to retain compatibility with previous versions of Freecell Solver, and was added in version 4.20.0 of fc-solve.

๐ŸŽฎ GAME VARIANTS OPTIONS ๐ŸŽฎ

okay bestie this is the part where we tell the solver what game we're even playing, because "solitaire" is not one game, it's like forty games wearing the same trenchcoat ๐Ÿ’…

--freecells-num [Number of Freecells]

Global โœจ

This one tells the program how many freecells it gets to play with. Freecell Solver can rock any number of freecells, as long as it doesn't go over its maximal number. ๐Ÿƒ

That maximum is hard-coded straight into the program, and you can set it at compile-time by editing the file config.h. Want the deets? Go read the file INSTALL (or, if you're feeling html-y, INSTALL.html). ๐Ÿ“–

--stacks-num [Number of Stacks]

Global โœจ

This sets how many stacks are chillin' on the board. And yeah, same rule as before: this number can't exceed the maximal number of stacks, which you can set in the file config.h when you compile Freecell Solver. ๐ŸŒธ

--decks-num [Number of Decks]

Global โœจ

How many decks are on the board, bestie? That's this option. And โ€” you already know โ€” this number cannot exceed the maximal number of decks, which the Freecell Solver build system gets to specify. ๐ŸŽด

--sequences-are-built-by {suit|alternate_color|rank}

Global โœจ

Decides whether a card sequence gets built by suit, by alternate_color, or by rank (as in, regardless of suit, we simply do not care). ๐ŸŒˆ

--sequence-move {limited|unlimited}

Global โœจ

Is the sequence move limited by the number of freecells or vacant stacks, or is it not? That's literally the whole question. limited = yes it's capped, unlimited = no cap, go off. ๐Ÿ‘‘

--empty-stacks-filled-by {kings|none|all}

Global โœจ

Specifies which cards are allowed to fill an empty stack. Choose your fighter: kings, none, or all. ๐Ÿซถ

--game [game] , --preset [game] , -g [game]

Global โœจ

This is the main character option โ€” it picks the type of game. Each preset implies several of the settings options we just talked about above, and sometimes even the moves' order that's coming down below. The default configuration is for Freecell. ๐ŸŽ€

Available presets, bestie, in all their glory:

  • bakers_dozen โ€” Bakerโ€™s Dozen
  • bakers_game โ€” Bakerโ€™s Game
  • beleaguered_castle โ€” Beleaguered Castle
  • citadel โ€” Citadel
  • cruel โ€” Cruel
  • der_katz โ€” Der Katzenschwanz
  • die_schlange โ€” Die Schlange
  • eight_off โ€” Eight Off
  • fan โ€” Fan
  • forecell โ€” Forecell
  • freecell โ€” Freecell (default)
  • good_measure โ€” Good Measure
  • ko_bakers_game โ€” Kings' Only Bakerโ€™s Game
  • relaxed_freecell โ€” Relaxed Freecell
  • relaxed_sehaven โ€” Relaxed Seahaven Towers
  • seahaven โ€” Seahaven Towers
  • simple_simon โ€” Simple Simon
  • streets_and_alleys โ€” Streets and Alleys
โš ๏ธ Note, and this one's important: to solve Der Katzenschwanz and Die Schlange, I recommend you compile Freecell Solver with the INDIRECT_STACK_STATES option, or else it will consume much more memory. For details, consult the file INSTALL. ๐Ÿ˜ญ

โœจ Examples โœจ

Wanna solve PySol Eight Off game No. 1,000? Type:

$ make_pysol_freecell_board.py 1000 eight_off | fc-solve -g eight_off

Wanna solve PySol Bakerโ€™s Game No. 50? Type:

$ make_pysol_freecell_board.py 50 bakers_game | fc-solve -g bakers_game

And if you want to solve a game similar to Freecell but with sequences built by rank only, plus unlimited sequence move, do:

$ fc-solve -g freecell --sequences-are-built-by rank --sequence-move unlimited

๐Ÿง  SOLVING ALGORITHM OPTIONS ๐Ÿง 

this is the "how hard should the solver try" section and honestly it's giving strategy meeting ๐Ÿ’€

-mi [Iterations num] , --max-iters [Iterations num]

Global โœจ

This caps the maximal number of states to check. It gives you a rough limit on how much time gets spent solving a given board. โณ

-md [Maximal depth] , --max-depth [Maximal depth]

Not currently implemented ๐Ÿ™ˆ

So, Freecell Solver recurses into the solution, right? This parameter specifies a maximal recursion depth. But generally speaking, setting it is not a good idea, because that way several important intermediate states may become inaccessible. So likeโ€ฆ maybe don't. ๐Ÿ’€

-mss [num] , --max-stored-states [num]

Global โœจ

Limits how many states the program stores in the computer's memory. And the way this differs from the maximal number of iterations is that it's totally possible a stored state was not checked yet. ๐Ÿ‘€

-tmss [num] , --trim-max-stored-states [num]

Instance-wide โœจ

This also limits the number of trimmed stored states, but this time it'll try to trim them once the limit has been reached โ€” which is time consuming and may cause states to be traversed again in the future. ๐Ÿ˜ญ worth knowing!

-to [Movesโ€™ Order] , --tests-order [Moves Order]

Soft-thread-specific โœจ

This one sets the order in which Freecell Solver tries the different types of moves โ€” formerly called "tests", iykyk. Each move is specified by one character, and they're performed in the order they appear in the parameter string. And you can omit moves entirely by just not including their corresponding characters in the string. ๐ŸŽฏ

The moves, and the lil character that summons each one: ๐Ÿ‘‡

๐ŸŒธ Freecell Moves

  • 0 โ€” put top stack cards in the foundations โœจ
  • 1 โ€” put freecell cards in the foundations ๐Ÿ’–
  • 2 โ€” put freecell cards on top of stacks ๐ŸŽ€
  • 3 โ€” put non-top stack cards in the foundations ๐Ÿ‘‘
  • 4 โ€” move stack cards to different stacks ๐Ÿฆ‹
  • 5 โ€” move stack cards to a parent card on the same stack ๐ŸŒธ
  • 6 โ€” move sequences of cards onto free stacks ๐Ÿ’…
  • 7 โ€” put freecell cards on empty stacks ๐Ÿซถ
  • 8 โ€” move cards to a different parent ๐Ÿ”ฅ
  • 9 โ€” empty an entire stack into the freecells ๐Ÿ’€
  • j โ€” put freecell cards on empty stacks and right away put cards on top ๐Ÿ™ˆ

๐Ÿ’œ Atomic Freecell Moves

  • A โ€” move a stack card to an empty stack โญ
  • B โ€” move a stack card to a parent on a different stack ๐ŸŒˆ
  • C โ€” move a stack card to a freecell ๐Ÿ“
  • D โ€” move a freecell card to a parent ๐Ÿงš
  • E โ€” move a freecell card to an empty stack ๐Ÿ’œ

๐ŸŽ€ Simple Simon Moves

  • a โ€” move a full sequence to the foundations โœจ
  • b โ€” move a sequence to a true parent of his ๐Ÿ’–
  • c โ€” move a whole stack sequence to a false parent (in order to clear the stack) ๐Ÿ‘€
  • d โ€” move a sequence to a true parent that has some cards above it ๐Ÿฆ‹
  • e โ€” move a sequence with some cards above it to a true parent ๐ŸŒธ
  • f โ€” move a sequence with a junk sequence above it to a true parent that has some cards above it ๐Ÿ’…
  • g โ€” move a whole stack sequence to a false parent which has some cards above it ๐Ÿซถ
  • h โ€” move a sequence to a parent on the same stack ๐Ÿ”ฅ
  • i โ€” move any sequence to a false parent (using it may make the solution much slower) ๐Ÿ’€

okay bestie, real talk: messing with the moves order can be so helpful for getting a quick solution on a given board. If you found that a certain board cannot be solved after a long time, or in a certain maximal number of iterations, you should try different moves' orders. Usually, one can find a moves order that solves a board very quickly. ๐Ÿƒโ€โ™€๏ธ๐Ÿ’จโœจ

okay so real talk about that moves' order: it usually only makes sense for the Soft-DFS and Random DFS scans (peep the --method option further down ๐Ÿ‘€).

And also, no cap: Freecell moves are not suitable for solving Simple Simon games, and Simple Simon moves are not suitable for solving anything except Simple Simon. That's just how it is. ๐Ÿ’€

You can group moves together into groups using parentheses, like "(0123)", or square brackets, like "[012][3456789]". That grouping is only relevant to the Random DFS scan (see below ๐Ÿ‘‡). A group can optionally be followed by the equal sign "=" and by an ordering specifier:

  • if you specify "=rand()", the derived states get randomised based on the seed โ€” which is literally what happens when no equal sign is specified at all ๐ŸŽฒ
  • but if you specify something like "=asw(5,0,5,0,0,5)", then those numbers inside the parentheses get treated as weights for the same ordering function used by the -asw flag (see below, iykyk โœจ)

And if the order specifier is "=all()", then all the moves in the group will be run, even if some derived states have already been yielded by earlier moves in the group. (This was added in version 5.24.0. ๐ŸŽ€)


-dto2 [Min Depth],[Moves' Order], --depth-tests-order2 [Min Depth],[Moves' Order]

Soft-thread-specific ๐Ÿงต

Sets the Moves' order starting from the minimal depth onwards. So like, if a Soft-DFS scan recurses super deep into the game, it'll switch up to a different moves' order. Main character energy, honestly. ๐Ÿ‘‘

Careful though โ€” if you set the moves' order of a minimal depth of say 50, it overrides all the moves' order of 50 and above. Which is why it's recommended that you set the minimal depth moves order in an increasing depth. ๐Ÿ“ˆ

Also worth clocking: the -to or --tests-order option above is equivalent to using this option with a minimal depth of 0. โœจ

Here are some examples:

-to 0123456789 -dto2 30,0138924567

This sets the moves' order to 0123456789 for all depths below 30 and to 0138924567 for all depths above it. ๐Ÿ’…

-to 0123457 -dto2 10,750123 -dto2 25,710235

This sets the moves' order to 0123457 for depths -9 (those below 10), to 750123 for depths 10-24, and to 710235 for the depths 25 onwards. ๐Ÿฆ‹

-to 0123457 -dto2 "10,[012357]=asw(1)"

This sorts the moves starting from 10 onward based on the asw() function. ๐Ÿ”ฅ

-to 0123457 -dto2 "10,[012357]=rand()"

This randomises the moves from 10 onward. ๐ŸŽฒ

-to 0123457 -dto2 "10,[012357]"

This does the same thing as the previous example. (Yes, fr fr, same vibe.) ๐ŸŒธ

Note: this option should be used instead of the older -dto option given below, which mutilates the moves order parameter and is still provided for backward compatibility. ๐Ÿ’€

-dto [Min Depth],[Moves' Order], --depth-tests-order [Min Depth],[Moves' Order]

This is equivalent to specifying -dto2 [Min Depth],[Min Depth],[Moves' Order] โ€” i.e: the "[Min Depth]," string is prefixed to the given moves order.

This option is provided for backward compatibility with older versions of Freecell Solver. It's giving legacy code, but respectfully. ๐Ÿซถ

-me [Solving Method], --method [Solving Method]

Soft-thread-specific ๐Ÿงต

This option specifies the solving method that will be used to solve the board. Currently, the following methods are available:

  • a-star โ€” A Best-First-Search scan (not "A*", as it was once thought to be ๐Ÿ‘€)
  • bfs โ€” A Breadth-First Search (or BFS) scan
  • dfs โ€” A Depth-First Search (or DFS) scan
  • random-dfs โ€” A randomized DFS scan
  • patsolve โ€” uses the scan of patsolve
  • soft-dfs โ€” A "soft" DFS scan

Starting from recent Freecell Solver versions there is no difference between dfs and soft-dfs. In earlier versions, use of soft-dfs is recommended. And random-dfs is similar to soft-dfs only it determines which states to recurse into randomly. Its behaviour will differ depending on the seed you supply to it (see the -seed option below ๐ŸŒฑ).

BFS does not yield good results, and a-star has a mixed behaviour, so for the time being I recommend using Soft-DFS or Random-DFS. Slay. ๐Ÿ’…

The Random-DFS scan processes every moves' random group, randomizes the states that it found, and recurses into them one by one. Standalone moves that do not belong to any group are processed in a non-random manner. ๐ŸŒˆ

-asw [BeFS Weights], --a-star-weight [BeFS Weights]

Soft-thread-specific ๐Ÿงต

Specify weights for the a-star (= "Best-First Search") scan, assuming it is used. The parameter should be a comma-separated list of numbers, each one proportional to the weight of its corresponding test. ๐Ÿ”ข

The numbers are, in order:

  1. The number of cards out.
  2. The maximal sequence move.
  3. The number of cards under sequences.
  4. The length of the sequences which are found over renegade cards.
  5. The depth of the board in the solution.
  6. The negative of the number of cards that are not placed above their parents. To get the irreversibility depth, give equal weight to this weight and to the number of cards out. โœจ

The default weights are respectively: {0.5, 0, 0.3, 0, 0.2, 0}

-seed [Seed Number]

Soft-thread-specific ๐Ÿงต

Specifies a seed to be used by Freecell Solver's internal random number generator. This seed may alter the behaviour and speed of the random-dfs scan. ๐ŸŒฑโœจ

--set-pruning [Pruning], -sp [Pruning]

Soft-thread-specific ๐Ÿงต

This option sets the pruning algorithm for the soft thread. Current valid values are the empty string ("") for no pruning, and r:tf (short for "Run: to foundations") for Horne's rule. See:

https://groups.yahoo.com/neo/groups/fc-solve-discuss/conversations/topics/214

To move one-card columns to the freecells when possible, use r:oc. ๐ŸŽ€

If the string contains both r:tf and r:oc, then both will be attempted. Double the pruning, double the chaos. ๐Ÿ’…

-opt, --optimize-solution

Flare-wide โ˜€๏ธ

This option instructs Freecell Solver to try and optimize the solution path so it will have a smaller number of moves. Shorter solutions are just... better? Iconic behaviour, honestly. ๐Ÿ‘‘

-opt-to [moves order], --optimization-tests-order [moves order]

Flare-wide โ˜€๏ธ

This argument specifies the moves order for the optimization scan, in case it should be different than an order that contains all the moves that were used in all the normal scans. ๐ŸŒธ

--reparent-states

Flare-wide โ˜€๏ธ

This option specifies that states that were encountered whose depth in the states graph can be improved should be reparented to the new parent. This option can possibly make solutions shorter. No promises, but potentially slay. โœจ

--calc-real-depth

Flare-wide โ˜€๏ธ

This option becomes effective only if --reparent-states is specified. What it does is explicitly calculate the depth of the state by tracing its path to the initial state. This may make depth consideration more accurate. ๐Ÿ”

--patsolve-x-param [pos],[value]

Soft-thread-specific ๐Ÿงต

Sets the patsolve's scan X param (an integer) in position "pos" into "value".

Examples:

--patsolve-x-param 0,5
--patsolve-x-param 2,100

--patsolve-y-param [pos],[value]

Soft-thread-specific ๐Ÿงต

Sets the patsolve Y param (a floating point number) in position "pos" into "value".

Examples:

--patsolve-y-param 0,0.5
--patsolve-y-param 1,103.2

RUNNING SEVERAL SCANS IN PARALLEL ๐Ÿƒโ™€๏ธ๐Ÿ’จ

Okay bestie, listen โ€” starting from Version 2.4.0, Freecell Solver can run several scans in parallel on the same state collection. Each scan gets to live in its own little "Soft Thread". So if you specify a bunch of soft threads on the command line, you're basically creating and running several task-switched scans at once. And the moment one of the scans reaches a solution, boom โ€” the solution gets displayed. Slay. โœจ


  • -nst, --next-soft-thread โ€” Hard-thread-specific

This option creates a new soft-thread and makes all the following scan-specific options initialize it. Like, for example:

$ fc-solve --method a-star -nst --method soft-dfs -to 0123467 myboard.txt

which will run an BeFS scan and a Soft-DFS scan with a moves order of 0123467 on myboard.txt. Two scans, one board, we love to see it. ๐Ÿ’…

  • -step [Step], --soft-thread-step [Step] โ€” Soft-thread-specific

This one sets the number of iterations with which to run the soft thread before switching over to the next one. So if you give a certain scan a larger step, you're basically handing it a longer run-time and a higher priority. Queen behavior.

Note: after some experimentation, we have concluded that the --prelude option normally yields better results, but -step can be used as a fallback. So like, --prelude is the main character here, and -step is the trusty understudy. ๐ŸŽ€
  • -nht, --next-hard-thread โ€” Flare-wide

This argument lets you initialize the next hard thread. If Freecell Solver was compiled with such support, then it's possible to run each hard thread in its own system thread. And each hard-thread contains one or more soft threads. Threads within threads, it's giving inception fr fr. ๐ŸŒ€

  • --st-name [soft thread name] โ€” Soft-thread-specific

Sets the name used to identify the current soft thread. And this name can later be used to construct the prelude (see below, bestie, it's right there ๐Ÿ‘‡).

  • --prelude [\i1@st1{,\i2@st2{,\i3@st3...}}] โ€” Hard-thread-specific

Sets the prelude for the hard thread. At the beginning of the search, the hard thread plays a static sequence of iterations</badge> at each of the soft threads specified in the prelude, for however many iterations you specified.

So like, imagine you had three soft threads named "foo", "bar" and "rin". Then this prelude:

--prelude 500@foo,1590@bar,100@foo,200@rin

Will run 500 iterations in "foo", then 1590 in "bar", then 100 in "foo" again, and then 200 in "rin". And once the prelude finishes? The hard thread runs the scans one after the other in the sequence they were defined for their step number. Iconic sequencing. ๐Ÿ’–

  • --scans-synergy {none|dead-end-marks} โ€” Flare-wide

Specifies the synergy between the various scans โ€” aka how much they cooperate with each other. none means they do not cooperate and only share the same memory resources. dead-end-marks means they try to mark states that they have withdrawn from, and states whose all their derived states are such, as "dead ends". This may or may not improve the speed of the solution. (ngl it's a vibe check situation, sometimes yes sometimes no ๐Ÿ™ˆ)

  • -ni, --next-instance โ€” Global

This option lets you run two or more separate solvers one after the other. If the first one returned an unsolvable verdict, then the second one would run, and so on. One use of it is to run an atomic moves scan after a meta-moves scan, so we will always get an accurate verdict and still enjoy some of the speed benefits of the meta-moves scan. Best of both worlds, no cap. ๐Ÿ”ฅ

  • -nf, --next-flare โ€” Instance-wide

Each instance contains several flares. Flares are various alternative scans that are ran one after another, as specified in the --flares-plan below or defaulting to running only the first flare (which isn't very useful, lowkey ๐Ÿ’€). Out of all the flares that are successful in solving a board, Freecell Solver picks the one with the shortest solution. Queen picks the best one, periodt.

  • --flare-name [flare name] โ€” Flare-wide

This is a name that identifies the flare for use in the flares' plan.

  • --flares-plan [flare plan] โ€” Instance-wide

This instance-wide parameter gives a plan for the flares as a big string. Here are some examples:

--flares-plan "RunIndef:FlareyFlare"

This plan will run the flare with the name FlareyFlare indefinitely, until it terminates. And once a RunIndef action is encountered, the rest of the plan is ignored.

--flares-plan "Run:500@MyFlare,Run:2000@FooFlare"

Runs MyFlare for 500 iterations and FooFlare for 2,000 iterations. Note that both flares will be run and won't share any resources between them, and then the minimal solution out of both flares (or only those that finished). If no flares finished, then Freecell Solver will run them both again for the same number of iterations each, until at least one finishes (or it ran out of the iterations' limit). Determination fr fr ๐Ÿ’ช

--flares-plan "Run:500@dfs,Run:1500@befs,CP:,Run:10000@funky"

This runs the flares identified by dfs and befs and then see if a solution was reached ("CP:" stands for "checkpoint"), and if so yield it. If both flares did not reach a solution yet, or failed to solve the board, it will run the flare funky for 10,000 iterations and yield its solution. And like the previous case, this solution will loop after it ended for as long as the no flare solved the board or the program did not run out of iterations.

Using checkpoints one can yield a possibly sub-optimal (as far as solution length is concerned) solution that will still solve faster than letting all the flares run. Sometimes you just gotta take the W you can get. ๐Ÿซถ

  • --flares-choice [choice] โ€” Global

This dictates how to choose the winning flare based on if more than one yielded a solution. Possible options are:

  1. --flares-choice fc_solve โ€” the default, which picks up the solutions based on the length of the solution in Freecell Solver's moves.
  2. --flares-choice fcpro โ€” picks up the shortest solution based on the number of Freecell Pro moves, while not considering implicit moves to the foundations using Horne's Prune / Raymond Prune.
  • -fif [factor], --flares-iters-factor [factor] โ€” Global

Sets a global, floating-point number, factor, to multiply all the iterations counts in the flares plans. The higher it is, the longer the scans will take, but there is a greater chance more of them will succeed, and, as a result, the solution may be shorter. Trade-offs, bestie, it's all trade-offs. โš–๏ธ

As an example, the following:

--flares-plan "Run:500@MyFlare,Run:2000@FooFlare" --flares-iters-factor 2

Is equivalent to:

--flares-plan "Run:1000@MyFlare,Run:4000@FooFlare"

while:

--flares-plan "Run:500@MyFlare,Run:2000@FooFlare" --flares-iters-factor 0.5

Is equivalent to:

--flares-plan "Run:250@MyFlare,Run:1000@FooFlare"
  • --cache-limit [cache limit] โ€” Global

This is a numeric limit to the LRU cache which only matters if Freecell Solver was compiled with FCS_RCS_STATES enabled. This value should be a positive integer and the higher it is, the more quickly it is likely that Freecell Solver will run, but it will also consume more memory. (The entire point of FCS_RCS_STATES is to conserve memory). So like, it's a memory-versus-speed moment. Pick your fighter. ๐Ÿ’…


META-OPTIONS ๐Ÿงšโœจ

  • --reset โ€” Global

This option resets the program to its initial state, losing all the configuration logic that was input to it up to that state. Afterwards, it can be set to a different configuration, again. Fresh start, clean slate, new me energy. ๐ŸŒธ

  • --read-from-file [num_skip,]filename โ€” Global (but context-specific).

This option will read the configuration options from a file. The format of the file is similar to that used by the UNIX Bourne Shell. (i.e: spaces denote separate arguments, double-quotes encompass arguments, backslash escapes characters).

The filename can be preceded by an optional number of the arguments to skip followed by a comma. (the default is 0)

  • -l [preset], --load-config [preset] โ€” Global (but context-specific).

Reads the configuration specified by [preset] and configures the solver accordingly. A preset is a set of command line arguments to be analyzed in the place of this option. They are read from a set of presetrc files : one installed system-wide, the other at $HOME/.freecell-solver/presetrc and the third at the path specified by the FREECELL_SOLVER_PRESETRC environment variable. You can add more presets at any of these places. (refer to http://groups.yahoo.com/group/fc-solve-discuss/message/403 for information about their format)

Presets are literally the "save your fave settings" feature bestie, use them. ๐Ÿ’œ

Presets that are shipped with Freecell Solver: ๐Ÿ’–

  • abra-kadabra โ€” a meta-moves preset โœจ
  • amateur-star โ€” a meta-moves preset that yields solutions faster on average than three-eighty ๐Ÿฆ‹
  • blue-yonder โ€” a meta-moves preset generated by a quota optimization algorithm ๐ŸŒˆ
  • children-playing-ball โ€” a meta-moves and flare-based preset that tends to yield very short solution, but is very slow (solves only 3 boards per second on a Pentium 4 2.4GHz) ๐Ÿ˜ญ
  • conspiracy-theory โ€” a meta-moves preset that yields solutions faster on average than amateur-star ๐Ÿ‘‘
  • cookie-monster โ€” a meta-moves preset that yields solutions faster on average than one-big-family ๐Ÿช
  • cool-jives โ€” a meta-moves preset ๐Ÿ’…
  • crooked-nose โ€” an atomic-moves preset (guarantees an accurate verdict) ๐Ÿ”ฅ
  • enlightened-ostrich โ€” a meta-moves preset (that depends on Freecell Solver 3.4.0 and above) that yields solutions faster on average than foss-nessy ๐Ÿฆฉ
  • fools-gold โ€” an atomic-moves preset โœจ
  • foss-nessy โ€” a meta-moves preset (that depends on Freecell Solver 3.2.0 and above) that yields solutions faster on average than the-iglu-cabal ๐Ÿงš
  • good-intentions โ€” runs "cool-jives" and then "fools-gold" ๐Ÿซถ
  • gooey-unknown-thing โ€” a meta-moves preset that aims to minimise the outcome solution's length ๐Ÿ’€
  • hello-world โ€” a meta-moves preset ๐ŸŒธ
  • john-galt-line โ€” a meta-moves preset ๐Ÿ’œ
  • looking-glass โ€” a meta-moves preset that yields solutions faster on average than cookie-monster ๐Ÿชž
  • maliciously-obscure โ€” a meta-moves and flare-based preset that tends to yield very short solutions (even in comparison to children-playing-ball ) but is slow ๐Ÿ™ˆ
  • micro-finance โ€” a meta-moves and flare-based preset that tends to yield very short solutions (even in comparison to

โ€ฆmaliciously-obscure ) but is even slower. ๐Ÿ’€

okay bestie, we're back in the preset menu and it's giving choices. here's the rest, fr fr:

  • micro-finance-improved โ€” a meta-moves and flare-based preset, based on micro-finance that yields somewhat shorter solutions on average, and should not be slower. โœจ
  • one-big-family โ€” a meta-moves preset that yields solutions faster on average than conspiracy-theory. ๐Ÿ”ฅ
  • qualified-seed โ€” a meta-moves and flare-based preset, based on micro-finance-improved that yields somewhat shorter solutions on average, and should not be slower. ๐ŸŽ€
  • qualified-seed-improved โ€” qualified-seed with -fif 5 and --flares-choice fcpro ๐Ÿ’…
  • rin-tin-tin โ€” a meta-moves preset ๐Ÿถ
  • sand-stone โ€” an atomic-moves preset that aims to minimise the outcome solutionโ€™s length. ๐Ÿ–๏ธ
  • slick-rock โ€” run "gooey-unknown-thing" and then "sand-stone" ๐Ÿชจ
  • sentient-pearls โ€” a meta-moves and flares based preset with short solutions. Much faster than children-playing-ball but yields less optimal solutions. ๐Ÿฆช
  • tea-for-two โ€” a meta-moves preset optimized for two-freecells' Freecell games (although it can work on other Freecell-like games as well). ๐Ÿซ–
  • the-iglu-cabal โ€” a meta-moves preset that yields faster solutions on average than blue-yonder. โ„๏ธ
  • the-last-mohican โ€” a preset for solving Simple Simon. Yields less false negatives than the default one, but might be slower. ๐Ÿชถ
  • three-eighty โ€” a meta-moves preset (that depends on Freecell Solver 3.4.0 and above) that yields solutions faster on average than enlightened-ostrich. ๐Ÿฆ
  • toons-for-twenty-somethings โ€” an atomic-moves preset that solves more boards efficiently than "fools-gold". ๐Ÿ“บ
  • video-editing โ€” a meta-moves and flare-based preset, based on qualified-seed that yields shorter solutions on average, but may be somewhat slower. Named to commemorate the earlier work of Adrian Ettlinger (1925-2013) <http://en.wikipedia.org/wiki/Adrian_Ettlinger> who later contributed to Freecell Solver and to Freecell research. ๐ŸŽฌ
  • yellow-brick-road โ€” a meta-moves preset ๐Ÿ›ฃ๏ธโœจ

ok so those presets can be shortened to their lowercase acronym, like "ak" or "rtt" โ€” periodt, no extra typing needed ๐Ÿ’…

โœจ RUN-TIME DISPLAY OPTIONS โœจ

๐Ÿ’– -i, --iter-output ๐Ÿ’–

Global

bestie this one makes fc-solve print the iteration number and the recursion depth of every single state it checks, straight to standard output. it's lowkey a great way to keep an eye on how it's doing, but heads up โ€” the output slows it down a lil bit ๐Ÿ˜ญ still worth it for the vibes though.

๐Ÿ’– --iter-output-step [step] ๐Ÿ’–

Global

only prints the current iteration if -i is specified, and only every [step] steps, where [step] is a positive integer. so like, if you do fc-solve -i --iter-output-step 100, you'll see this:

Iteration: 0
Iteration: 100
Iteration: 200
Iteration: 300

this option was added in Freecell Solver 4.20.0 and it's iconic for speeding up the runtime process by avoiding excessive output ๐Ÿƒโ™€๏ธ๐Ÿ’จ

๐Ÿ’– -s, --state-output ๐Ÿ’–

Global

this option implies -i btw. if you specify it, it outputs the cards and formation of the board itself, for every state that's checked. fc-solve -s gives you a nice real-time display of Freecell Solver's progress, but honestly you usually can't even tell what's going on because it's so fast ๐Ÿ’€ it's giving speedrun.


๐Ÿšจ SIGNAL COMBINATIONS ๐Ÿšจ

if you're on a UNIX or a similar system, then you can set some run-time options in fc-solve by sending it some signal combinations ๐Ÿฆ‹

  • send fc-solve a single ABRT signal โ†’ fc-solve will terminate the scan prematurely, and report that the iterations's limit has been exceeded. very dramatic of it ngl.
  • send the signal USR1, without sending any other signals before that โ†’ fc-solve will output the present number of iterations. this method is a good way to monitor an instance that takes a long time to solve ๐Ÿ‘‘
  • send it USR2 and then USR1 โ†’ fc-solve will print the iteration number and depth on every state that it checks. it's the equivalent of specifying (or unspecifying) the option -i/--iter-output ๐Ÿ’ซ
  • send it two USR2 signals and then USR1 โ†’ fc-solve will also print the board of every state. again, this will only be done assuming the iteration output is turned on ๐ŸŒธ
ok but fr fr, the signal girlies are not for the faint of heart โ€” do not come for me if you spam ABRT and your scan just stops, that's literally the whole point ๐Ÿ˜ญ

๐Ÿ‘‘ AUTHOR ๐Ÿ‘‘

Shlomi Fish


and that's a wrap on the whole thing bestie!! ๐ŸŽ€ the page you just read is from 2025-11-17, it's FC-SOLVE(6) in the manual, and you ate every single bit of it. go solve some freecells, you absolute legend ๐Ÿ’…โœจ๐Ÿฆ‹

๐Ÿ“ฆ where this page comes from