ichabod801 / t_games

A collection of command-line interface games written in Python.
GNU General Public License v3.0
21 stars 4 forks source link

Guessing not working in two deck games. #577

Closed ichabod801 closed 4 years ago

ichabod801 commented 4 years ago

Often when trying to sort, especially late in the game, guess lanes a card instead of sorting it.

ichabod801 commented 4 years ago

Part of the problem might be Mutlisolitaire.find_foundation. Check that it is correctly finding all the foundations, especially in one and two suit games. Also check that Solitaire.sort_check is returning True.

ichabod801 commented 4 years ago

Here's a case, from Gargantua:

7C 8D 6H TS 8C 9D 9H JS

KD KS KH KC QC KD -- KH ??
QS QD QC QD          QS ??
JD JC JH JS          JH ??
   TD TC TD          TC QH
   9C                9D JC

-- QH

What is your move? td

7C 8D 6H TS 8C 9D 9H JS

KD KS KH KC QC KD -- KH ??
QS QD QC QD          QS ??
JD JC JH JS          JH ??
   TD TC             TC QH
   9C                9D JC
                        TD

-- QH

The TD from the fourth tableau pile could have sorted to the sixth foundation pile. Instead, it moved to the JC in the ninth tableau pile.

ichabod801 commented 4 years ago

I went back and looked at that case. Both foundations were found for the TD, and sort_check is returning True for that card and the sixth foundation.

ichabod801 commented 4 years ago

And note that it goes back and forth if you leave it to guessing: doing 'TD' again moves it back to the JS.

ichabod801 commented 4 years ago

But it's not always the case that it fails to sort if it could build. Later on in the same game there was this:

7C 8D 6H JS 8C QD 9H JS

KD KS KH KC QC KD KS KH ??
QS QD QC QH       QH QS 8C
JD JC JH          JC JH
   TD TC             TC
   9C                9D

-- TH

What is your move? 8c

8C 8D 6H JS 8C QD 9H JS

KD KS KH KC QC KD KS KH 9C
QS QD QC QH       QH QS
JD JC JH          JC JH
   TD TC             TC
   9C                9D

-- TH

Here, the 8C was sorted correctly, even though it could have been put on the 9D.

ichabod801 commented 4 years ago

But then we have the problem again here:

8C 8D 6H JS 9C QD 9H JS

KD KS KH KC QC KD KS KH 9C
QS QD QC QH       QH QS
JD JC JH          JC JH
   TD TC             TC
                     9D

-- TH

What is your move? tc

8C 8D 6H JS 9C QD 9H JS

KD KS KH KC QC KD KS KH 9C
QS QD QC QH       QH QS
JD JC JH          JC JH
TC TD                TC
                     9D

-- TH

It seems like if you have a foundation that is too low, it ignores a valid but higher foundation, and then builds instead.

ichabod801 commented 4 years ago

Got it. Here's what is happening in the last example. There are two TC's available, TC-3 and TC-8. But deck.find('TC') returns TC-8 first, so guess checks that first. TC-8 can't be sorted, but it can be built onto JD-1. So guess stops checking because of the conditional on like 1368, and never checks TC-3. What it does is return 'build TC JD'.

That goes to do_build. That method check both TCs, to keep track of alternate moves. Again, it checks TC-8 first, leaving the TC-3 move at the end of the list of possible moves. It returns the pop of the list of possible moves, returning the TC-3 move.

ichabod801 commented 4 years ago

You have the exact same thing in the first example, just with two TD's.

ichabod801 commented 4 years ago

Do I fix? Something needs to be done, because guess is not working as documented. I think it is possible to fix: Remove the conditional on 1368 so that all cards are checked. Then, don't just append the move text to moves. Append a sorting key and the move_text as a tuple. Then sort moves at the end. I think I was trying to avoid something like that when I set this up, but that is obviously not working.

Could I do it with a lambda? Let's see:

moves.sort(key = lambda x: ('sort', 'buil', 'matc', 'free', 'lane').index(x[:4])), reverse = True)

98 characters plus 3 indents x 4 character each puts it over the line limit. It would fit if I made it index a string and not a tuple. And actually, you only need to sort by the first character.

In any case, sleep on it (maybe there's another solution) and decide another day.

ichabod801 commented 4 years ago

Revised lambda for the hell of it:

moves.sort(key = lambda x: 'sbmfl'.index(x[0])), reverse = True)

65 characters plus the indents puts it under the PEP 8 limit. It is less clear but could be commented.

ichabod801 commented 4 years ago

Tested it in Spider and Gargantua. I'm seeing no problems with it in normal guessing. I potential error cases as above it worked correctly 10 times in a row. That makes the odds of it still being broken less than one in a thousand.