-
Notifications
You must be signed in to change notification settings - Fork 4
/
pile_tableau.lua
106 lines (95 loc) · 2.77 KB
/
pile_tableau.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
-- class Tableau, derived from Pile
local Pile = require 'pile'
local Util = require 'util'
---@class (exact) Tableau : Pile
---@field __index Tableau
---@field new function
local Tableau = {}
Tableau.__index = Tableau
setmetatable(Tableau, {__index = Pile})
function Tableau.new(o)
o.category = 'Tableau'
o.fanType = o.fanType or 'FAN_DOWN'
o.moveType = o.moveType or 'MOVE_TAIL'
o = Pile.prepare(o)
table.insert(_G.BAIZE.piles, o)
table.insert(_G.BAIZE.tableaux, o)
return setmetatable(o, Tableau)
end
local function powerMoves(pileTarget)
-- (1 + number of empty freecells) * 2 ^ (number of empty columns)
-- see http://ezinearticles.com/?Freecell-PowerMoves-Explained&id=104608
-- and http://www.solitairecentral.com/articles/FreecellPowerMovesExplained.html
local emptyCells, emptyCols = 0, 0
for _, pile in ipairs(_G.BAIZE.piles) do
if #pile.cards == 0 then
if pile.category == 'Cell' then
emptyCells = emptyCells + 1
elseif pile.category == 'Tableau' then
if (not pile.label) and (pile ~= pileTarget) then
emptyCols = emptyCols + 1
end
end
end
end
local n = (1 + emptyCells) * (2 ^ emptyCols)
-- log.info(emptyCells, "emptyCells,", emptyCols, "emptyCols,", n, "powerMoves")
return n
end
---@return string|nil
function Tableau:acceptTailError(tail)
for _, c in ipairs(tail) do
if c.prone then
return 'Cannot add a face down card to a Tableau'
end
end
if self.moveType == 'MOVE_TOP_ONLY_PLUS' then
if _G.SETTINGS.powerMoves then
local moves = powerMoves(self)
if #tail > moves then
if moves == 1 then
return string.format('Space to move 1 card, not %d', #tail)
else
return string.format('Space to move %d cards, not %d', moves, #tail)
end
end
else
if #tail > 1 then
return 'Cannot add more than one card'
end
end
elseif self.moveType == 'MOVE_TOP_ONLY' then
if #tail > 1 then
return 'Cannot add more than one card'
end
-- else
-- log.error('unknown tableau move type', self.moveType)
end
return _G.BAIZE.script:tailAppendError(self, tail)
end
-- use Pile.tailTapped
-- use Pile.collect
---@return integer
function Tableau:unsortedPairs()
return Util.unsortedPairs(self.cards, _G.BAIZE.script.tabCompareFn)
end
function Tableau:movableTails()
local tails = {}
if #self.cards > 0 then
for _, card in ipairs(self.cards) do
if not card.prone then
local tail = self:makeTail(card)
if not self:moveTailError(tail) then
if not _G.BAIZE.script:moveTailError(tail) then
local homes = Util.findHomesForTail(tail)
for _, home in ipairs(homes) do
table.insert(tails, {tail=tail, dst=home.dst})
end
end
end
end
end
end
return tails
end
return Tableau