diff --git a/README.md b/README.md index e605bd1..9077e08 100644 --- a/README.md +++ b/README.md @@ -4,15 +4,19 @@ A brute force solver for Microsoft Tri-Peaks solitaire written in javascript. This is a fork of [Courtney Pitcher's project](https://github.com/IgniparousTempest/javascript-tri-peaks-solitaire-solver), which I've modified for my own purposes. -## Unsolvable Boards +## Fix -The most significant addition is that this solver will return one possible "best path" for unsolvable games — a set of moves that clears the most cards from the board. +It seemed I was getting solutions that didn't make sense, which I tracked down to the logic used to compare cards. I believe I've fixed this, and have now been getting real solutions. -This can help with games where the goal is not clearing the board, but clearing a certain set of cards or hitting a threshold of points. +In fact, it's now able to solve the test game I thought was "unsolvable," so I had to disable that test until I can identify another unsolvable game! But the logic for unsolvable games should still work. -_NOTE:_ The "best path" returned is the first one found that clears the most cards. Hypothetically, a board could have multiple paths to clear the same number of cards. The path the solver returns might not clear the cards you need to clear. A possible future improvement could be returning, say, the top 5 best paths. +## Unsolvable Games -_NOTE:_ Unsolvable boards can take a long time to process, so be patient. The sample unsolvable board below takes my computer almost 6 minutes to conclude. +For unsolvable games, this solver will return one possible "best path" — a set of moves that clears the most cards from the board. If you're playing a game with a goal like "clear all Aces," and the full board is unsolvable, this might help you at least clear those Aces! + +However, it could be that a given board has more than one path to removing most of the cards, and the one this solver returns might not remove the cards you need. If I get around to it, a better improvement might be to return, say, the top 5 best paths. + +_NOTE:_ Unsolvable boards could take up to 10 minutes to process, so be patient. ## Playing @@ -20,12 +24,8 @@ I have yet to implement this in a website but it can be run directly in node. Ev - solvable: "8S TS 4D 7S 5D 7C 2D JH AC 3S 2H 3H 9H KC QC TD 8D 9C 7H 9D JS QS 4H 5C 5S 4C 2C QD 8C KD 3D KS JD 2S 7D KH AH 5H 9S 4S QH 6S 6D 3C JC TC 8H 6C TH AS AD 6H" - partial board: "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2D KH 8C 6S 6H 2C 8H JC 9C 4D AD TH 2S AS QH 5H AH 3H 2H 4S 6D 3C TS JD 9H KD AC JS 9S 4H 4C 5S 5D 5C" -- unsolvable: "2D 6D AD 9S 4C 7C 7S 7D 9C 2S AC 8D 6S 6H 3C 5H QS JS 4S JH 5C AS 3H 3S AH TD 4D 5S TH 7H KS QH 6C KD 8S 2C TC JC 5D 3D 2H TS 4H JD KC KH 8H QC 8C QD 9D 9H" +~~- unsolvable: "2D 6D AD 9S 4C 7C 7S 7D 9C 2S AC 8D 6S 6H 3C 5H QS JS 4S JH 5C AS 3H 3S AH TD 4D 5S TH 7H KS QH 6C KD 8S 2C TC JC 5D 3D 2H TS 4H JD KC KH 8H QC 8C QD 9D 9H"~~ ## Notes Per Courtney Pitcher, "This is probably quite a poor implementation." Please don't fault either of us, he was teaching himself javascript, and I'm probably even less qualified... - -## Tests - -The test for an unsolvable board will cause the tests to take a long time to complete, almost 6 minutes on my computer. diff --git a/solver.js b/solver.js index 48de043..7a0dd3c 100644 --- a/solver.js +++ b/solver.js @@ -19,8 +19,8 @@ class Card { */ isSequential(card) { return ( - (this.integerValue + 1) % 13 === card.integerValue || - (this.integerValue - 1) % 13 === card.integerValue + (this.integerValue + 13 + 1) % 13 === card.integerValue || + (this.integerValue + 13 - 1) % 13 === card.integerValue ); } diff --git a/test.js b/test.js index 3ab919a..84d09ed 100644 --- a/test.js +++ b/test.js @@ -4,15 +4,16 @@ const solver = require("./solver"); const solvable_games = [ "8S TS 4D 7S 5D 7C 2D JH AC 3S 2H 3H 9H KC QC TD 8D 9C 7H 9D JS QS 4H 5C 5S 4C 2C QD 8C KD 3D KS JD 2S 7D KH AH 5H 9S 4S QH 6S 6D 3C JC TC 8H 6C TH AS AD 6H", "5D 9C 5S QS 8S 9D AS 5C 2S QD KC 9H 4H QC 2H 8D 4C 4D JC TS 6D 7H QH 3S 5H JH 6H 2D AC 7S 7C 3D KD 9S 3C TH 6C AH 8H TC 4S 8C AD 3H KS 6S JS 7D JD TD 2C KH", + "JD 4D AH QC 3H 3C 7H TD 4H 2D 7C 7D 3S KH QS JC 2S 7S JS AS TS AD TC QD 9S 4S 2H 9H 8S JH 6C 3D KS 5S 5C 6H 9C 2C AC 8C 6D 5D TH 8D KC KD 9D 4C 5H 8H QH 6S", + "2D 6D AD 9S 4C 7C 7S 7D 9C 2S AC 8D 6S 6H 3C 5H QS JS 4S JH 5C AS 3H 3S AH TD 4D 5S TH 7H KS QH 6C KD 8S 2C TC JC 5D 3D 2H TS 4H JD KC KH 8H QC 8C QD 9D 9H", ]; const partial_games = [ "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2D KH 8C 6S 6H 2C 8H JC 9C 4D AD TH 2S AS QH 5H AH 3H 2H 4S 6D 3C TS JD 9H KD AC JS 9S 4H 4C 5S 5D 5C", ]; -const unsolvable_games = [ - "2D 6D AD 9S 4C 7C 7S 7D 9C 2S AC 8D 6S 6H 3C 5H QS JS 4S JH 5C AS 3H 3S AH TD 4D 5S TH 7H KS QH 6C KD 8S 2C TC JC 5D 3D 2H TS 4H JD KC KH 8H QC 8C QD 9D 9H", -]; +// const unsolvable_games = [ +// ]; it("should solve known games", () => { assert.equal(true, true); @@ -21,7 +22,7 @@ it("should solve known games", () => { const result = solver.solve(array.slice(0, 28), array.slice(28, 52), 0, []); assert.equal(result[0], true); }); -}); +}).timeout(200000); it("should solve partial games", () => { assert.equal(true, true); @@ -32,11 +33,11 @@ it("should solve partial games", () => { }); }); -it("should return a best-moves-sequence for unsolvable games", () => { - assert.equal(true, true); - unsolvable_games.forEach(function (i) { - const array = i.split(" ").map((x) => (x === "0" ? 0 : x)); - const result = solver.solve(array.slice(0, 28), array.slice(28, 52), 0, []); - assert.equal(result[2].length, 40); - }); -}).timeout(400000); +// it("should return a best-moves-sequence for unsolvable games", () => { +// assert.equal(true, true); +// unsolvable_games.forEach(function (i) { +// const array = i.split(" "); +// const result = solver.solve(array.slice(0, 28), array.slice(28, 52), 0, []); +// assert.equal(result[2].length, 43); +// }); +// }).timeout(400000);