mirror of
https://github.com/shlomif/PySolFC.git
synced 2025-04-05 00:02:29 -04:00
Got the solver for BlackHole to work.
Currently there's some duplicate code between it and the FreeCellSolver_Hint and I haven't checked All in a Row yet.
This commit is contained in:
parent
026025614b
commit
85ecb25e30
2 changed files with 191 additions and 0 deletions
|
@ -35,6 +35,7 @@ from pysollib.stack import *
|
||||||
from pysollib.game import Game
|
from pysollib.game import Game
|
||||||
from pysollib.layout import Layout
|
from pysollib.layout import Layout
|
||||||
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
|
from pysollib.hint import AbstractHint, DefaultHint, CautiousDefaultHint
|
||||||
|
from pysollib.hint import BlackHoleSolverWrapper
|
||||||
from pysollib.pysoltk import MfxCanvasText
|
from pysollib.pysoltk import MfxCanvasText
|
||||||
|
|
||||||
# ************************************************************************
|
# ************************************************************************
|
||||||
|
@ -301,6 +302,7 @@ class BlackHole_RowStack(ReserveStack):
|
||||||
class BlackHole(Game):
|
class BlackHole(Game):
|
||||||
RowStack_Class = StackWrapper(BlackHole_RowStack, max_accept=0, max_cards=3)
|
RowStack_Class = StackWrapper(BlackHole_RowStack, max_accept=0, max_cards=3)
|
||||||
Hint_Class = Golf_Hint
|
Hint_Class = Golf_Hint
|
||||||
|
Solver_Class = BlackHoleSolverWrapper(preset='black_hole')
|
||||||
|
|
||||||
#
|
#
|
||||||
# game layout
|
# game layout
|
||||||
|
@ -434,6 +436,7 @@ class FourLeafClovers(Game):
|
||||||
|
|
||||||
class AllInARow(BlackHole):
|
class AllInARow(BlackHole):
|
||||||
|
|
||||||
|
Solver_Class = BlackHoleSolverWrapper(preset='all_in_a_row')
|
||||||
def createGame(self):
|
def createGame(self):
|
||||||
# create layout
|
# create layout
|
||||||
l, s = Layout(self), self.s
|
l, s = Layout(self), self.s
|
||||||
|
|
188
pysollib/hint.py
188
pysollib/hint.py
|
@ -962,6 +962,185 @@ class FreeCellSolver_Hint:
|
||||||
if os.name == 'posix':
|
if os.name == 'posix':
|
||||||
os.wait()
|
os.wait()
|
||||||
|
|
||||||
|
class BlackHoleSolver_Hint:
|
||||||
|
|
||||||
|
BLACK_HOLE_SOLVER_COMMAND = 'black-hole-solve'
|
||||||
|
def __init__(self, game, dialog, **game_type):
|
||||||
|
self.game = game
|
||||||
|
self.dialog = dialog
|
||||||
|
self.game_type = game_type
|
||||||
|
self.options = {
|
||||||
|
'max_iters': 1000000,
|
||||||
|
'progress': False,
|
||||||
|
'preset': None,
|
||||||
|
}
|
||||||
|
self.hints = []
|
||||||
|
self.hints_index = 0
|
||||||
|
|
||||||
|
self.base_rank = 0
|
||||||
|
|
||||||
|
def config(self, **kw):
|
||||||
|
self.options.update(kw)
|
||||||
|
|
||||||
|
|
||||||
|
def card2str1(self, card):
|
||||||
|
# row and reserves
|
||||||
|
rank = (card.rank-self.base_rank) % 13
|
||||||
|
return "A23456789TJQK"[rank] + "CSHD"[card.suit]
|
||||||
|
def card2str2(self, card):
|
||||||
|
# foundations
|
||||||
|
import pdb; pdb.set_trace()
|
||||||
|
rank = (card.rank-self.base_rank) % 13
|
||||||
|
return "CSHD"[card.suit] + "-" + "A23456789TJQK"[rank]
|
||||||
|
|
||||||
|
# hard solvable: Freecell #47038300998351211829 (65539 iters)
|
||||||
|
|
||||||
|
def getHints(self, taken_hint=None):
|
||||||
|
if taken_hint and taken_hint[6]:
|
||||||
|
return [taken_hint[6]]
|
||||||
|
h = self.hints[self.hints_index]
|
||||||
|
#print 'getHints', taken_hint, h
|
||||||
|
if h is None:
|
||||||
|
return None
|
||||||
|
ncards, src, dest = h
|
||||||
|
thint = None
|
||||||
|
if len(src.cards) > ncards and not src.cards[-ncards-1].face_up:
|
||||||
|
# flip card
|
||||||
|
thint = (999999, 0, 1, src, src, None, None)
|
||||||
|
if dest == None: # foundation
|
||||||
|
cards = src.cards[-ncards:]
|
||||||
|
for f in self.game.s.foundations:
|
||||||
|
if f.acceptsCards(src, cards):
|
||||||
|
dest = f
|
||||||
|
break
|
||||||
|
assert dest
|
||||||
|
hint = (999999, 0, ncards, src, dest, None, thint)
|
||||||
|
self.hints_index += 1
|
||||||
|
#print hint
|
||||||
|
return [hint]
|
||||||
|
|
||||||
|
def colonPrefixMatch(self, prefix, s):
|
||||||
|
m = re.match(prefix + ': (\d+)', s)
|
||||||
|
if m:
|
||||||
|
self._v = int(m.group(1))
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
self._v = None
|
||||||
|
return False
|
||||||
|
|
||||||
|
def computeHints(self):
|
||||||
|
game = self.game
|
||||||
|
game_type = self.game_type
|
||||||
|
progress = self.options['progress']
|
||||||
|
board = ''
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
# import pdb; pdb.set_trace()
|
||||||
|
card = self.game.s.foundations[0].cards[-1]
|
||||||
|
if card:
|
||||||
|
board += 'Foundations: ' + self.card2str1(card) + '\n'
|
||||||
|
|
||||||
|
for s in self.game.s.rows:
|
||||||
|
b = ''
|
||||||
|
for c in s.cards:
|
||||||
|
cs = self.card2str1(c)
|
||||||
|
if not c.face_up:
|
||||||
|
cs = '<%s>' % cs
|
||||||
|
b += cs + ' '
|
||||||
|
board += b.strip() + '\n'
|
||||||
|
#
|
||||||
|
if DEBUG:
|
||||||
|
print '--------------------\n', board, '--------------------'
|
||||||
|
#
|
||||||
|
args = []
|
||||||
|
##args += ['-sam', '-p', '-opt', '--display-10-as-t']
|
||||||
|
args += ['--game', game_type['preset'], '--rank-reach-prune',]
|
||||||
|
args += ['--max-iters', self.options['max_iters'],]
|
||||||
|
#
|
||||||
|
|
||||||
|
command = self.BLACK_HOLE_SOLVER_COMMAND+' '+' '.join([str(i) for i in args])
|
||||||
|
if DEBUG:
|
||||||
|
print command
|
||||||
|
kw = {'shell': True,
|
||||||
|
'stdin': subprocess.PIPE,
|
||||||
|
'stdout': subprocess.PIPE,
|
||||||
|
'stderr': subprocess.PIPE}
|
||||||
|
if os.name != 'nt':
|
||||||
|
kw['close_fds'] = True
|
||||||
|
p = subprocess.Popen(command, **kw)
|
||||||
|
pin, pout, perr = p.stdin, p.stdout, p.stderr
|
||||||
|
pin.write(board)
|
||||||
|
pin.close()
|
||||||
|
#
|
||||||
|
if DEBUG:
|
||||||
|
start_time = time.time()
|
||||||
|
|
||||||
|
import pdb; pdb.set_trace()
|
||||||
|
result = ''
|
||||||
|
# iteration output
|
||||||
|
iter = 0
|
||||||
|
depth = 0
|
||||||
|
states = 0
|
||||||
|
|
||||||
|
for s in pout:
|
||||||
|
if DEBUG >= 5:
|
||||||
|
print s,
|
||||||
|
|
||||||
|
m = re.search('^(Intractable!|Unsolved!|Solved!)\n', s)
|
||||||
|
if m:
|
||||||
|
result = m.group(1)
|
||||||
|
break
|
||||||
|
self.dialog.setText(iter=iter, depth=depth, states=states)
|
||||||
|
|
||||||
|
if (result == 'Intractable!'):
|
||||||
|
return
|
||||||
|
if (result == 'Unsolved!'):
|
||||||
|
return
|
||||||
|
|
||||||
|
hints = []
|
||||||
|
for s in pout:
|
||||||
|
if DEBUG:
|
||||||
|
print s,
|
||||||
|
m = re.match('Total number of states checked is (\d+)\.', s)
|
||||||
|
if m:
|
||||||
|
iter = int(m.group(1))
|
||||||
|
self.dialog.setText(iter=iter)
|
||||||
|
|
||||||
|
m = re.match('This scan generated (\d+) states\.', s)
|
||||||
|
|
||||||
|
if m:
|
||||||
|
states = int(m.group(1))
|
||||||
|
self.dialog.setText(states=states)
|
||||||
|
|
||||||
|
m = re.match('Move a card from stack ([0-9]+) to the foundations', s)
|
||||||
|
if not m:
|
||||||
|
continue
|
||||||
|
|
||||||
|
found_stack_idx = int(m.group(1))
|
||||||
|
ncards = 1
|
||||||
|
st = game.s.rows
|
||||||
|
sn = found_stack_idx
|
||||||
|
src = st[sn] # source stack
|
||||||
|
dest = None
|
||||||
|
|
||||||
|
hints.append([ncards, src, dest])
|
||||||
|
##print src, dest, ncards
|
||||||
|
|
||||||
|
#
|
||||||
|
if DEBUG:
|
||||||
|
print 'time:', time.time()-start_time
|
||||||
|
##print perr.read(),
|
||||||
|
|
||||||
|
self.hints = hints
|
||||||
|
self.hints.append(None) # XXX
|
||||||
|
|
||||||
|
##print self.hints
|
||||||
|
|
||||||
|
pout.close()
|
||||||
|
perr.close()
|
||||||
|
if os.name == 'posix':
|
||||||
|
os.wait()
|
||||||
|
|
||||||
class FreeCellSolverWrapper:
|
class FreeCellSolverWrapper:
|
||||||
|
|
||||||
|
@ -972,3 +1151,12 @@ class FreeCellSolverWrapper:
|
||||||
hint = FreeCellSolver_Hint(game, dialog, **self.game_type)
|
hint = FreeCellSolver_Hint(game, dialog, **self.game_type)
|
||||||
return hint
|
return hint
|
||||||
|
|
||||||
|
class BlackHoleSolverWrapper:
|
||||||
|
|
||||||
|
def __init__(self, **game_type):
|
||||||
|
self.game_type = game_type
|
||||||
|
|
||||||
|
def __call__(self, game, dialog):
|
||||||
|
hint = BlackHoleSolver_Hint(game, dialog, **self.game_type)
|
||||||
|
return hint
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue