diff --git a/database.rules.json b/database.rules.json index 8650856..4c54261 100644 --- a/database.rules.json +++ b/database.rules.json @@ -19,7 +19,7 @@ }, "mode": { ".write": "auth != null && auth.uid == data.parent().child('host').val() && data.parent().child('status').val() == 'waiting' && newData.exists()", - ".validate": "newData.isString() && newData.val().matches(/^normal|junior|setchain|ultraset|ultrachain|ultra9|megaset|ghostset|4set|4setjr|4setjrchain|puzzle|ultra9puzzle|shuffle|memory$/)" + ".validate": "newData.isString() && newData.val().matches(/^normal|junior|setchain|ultraset|ultrachain|ultra9|megaset|ghostset|4set|4setjr|4setjrchain|puzzle|ultra9puzzle|4setjrpuzzle|shuffle|memory$/)" }, "enableHint": { ".write": "auth != null && auth.uid == data.parent().child('host').val() && data.parent().child('status').val() == 'waiting' && newData.exists()", @@ -52,7 +52,7 @@ "events": { "$eventId": { ".write": "!data.exists() && newData.exists() && auth != null && root.hasChild('games/' + $gameId + '/users/' + auth.uid) && root.child('games/' + $gameId + '/status').val() == 'ingame'", - ".validate": "newData.hasChildren(['user', 'time', 'c1', 'c2', 'c3']) && (newData.hasChild('c4') == root.child('games/' + $gameId + '/mode').val().matches(/^ultraset|ultrachain|ultra9|ultra9puzzle|ghostset|4set|4setjr|4setjrchain$/)) && (newData.hasChildren(['c5', 'c6']) == (root.child('games/' + $gameId + '/mode').val() == 'ghostset'))", + ".validate": "newData.hasChildren(['user', 'time', 'c1', 'c2', 'c3']) && (newData.hasChild('c4') == root.child('games/' + $gameId + '/mode').val().matches(/^ultraset|ultrachain|ultra9|ultra9puzzle|ghostset|4set|4setjr|4setjrchain|4setjrpuzzle$/)) && (newData.hasChildren(['c5', 'c6']) == (root.child('games/' + $gameId + '/mode').val() == 'ghostset'))", "user": { ".validate": "newData.isString() && newData.val() == auth.uid" }, diff --git a/functions/src/game.ts b/functions/src/game.ts index 46e2c4a..efd8687 100644 --- a/functions/src/game.ts +++ b/functions/src/game.ts @@ -253,12 +253,16 @@ function findSet4Set(deck: string[], gameMode: GameMode, state: FindState) { const deckSet = new Set(deck); const first = modes[gameMode].chain && state.lastSet!.length > 0 ? state.lastSet! : deck; + const foundSets = modes[gameMode].puzzle && state.foundSets!; for (let i = 0; i < first.length; i++) { for (let j = i + 1; j < first.length; j++) { for (let k = first === deck ? j + 1 : 0; k < deck.length; k++) { const c = conjugateCard4Set(first[i], first[j], deck[k]); if (deckSet.has(c)) { - return [first[i], first[j], deck[k], c]; + const set = [first[i], first[j], deck[k], c]; + if (!(foundSets && foundSets.has(set.sort().join("|")))) { + return set; + } } } } @@ -478,6 +482,13 @@ export const modes = { puzzle: true, minBoardSize: 9, }, + "4setjrpuzzle": { + setType: "4Set", + traits: 3, + chain: 0, + puzzle: true, + minBoardSize: 11, + }, shuffle: { setType: "Set", traits: 4, diff --git a/src/game.js b/src/game.js index 04dcf3e..39ca918 100644 --- a/src/game.js +++ b/src/game.js @@ -257,12 +257,16 @@ function findSet4Set(deck, gameMode, state) { const deckSet = new Set(deck); const first = modes[gameMode].chain && state.lastSet.length > 0 ? state.lastSet : deck; + const foundSets = modes[gameMode].puzzle && state.foundSets; for (let i = 0; i < first.length; i++) { for (let j = i + 1; j < first.length; j++) { for (let k = first === deck ? j + 1 : 0; k < deck.length; k++) { const c = conjugateCard4Set(first[i], first[j], deck[k]); if (deckSet.has(c)) { - return [first[i], first[j], deck[k], c]; + const set = [first[i], first[j], deck[k], c]; + if (!(foundSets && foundSets.has(set.sort().join("|")))) { + return set; + } } } } @@ -609,6 +613,16 @@ export const modes = { puzzle: true, minBoardSize: 9, }, + "4setjrpuzzle": { + name: "4Set Jr-Puzzle", + color: "indigo", + description: "Find all 4Sets on the board before moving to the next board.", + setType: "4Set", + traits: 3, + chain: 0, + puzzle: true, + minBoardSize: 11, + }, shuffle: { name: "Shuffle", color: "blue", diff --git a/src/game.test.js b/src/game.test.js index dd02efb..7c1feca 100644 --- a/src/game.test.js +++ b/src/game.test.js @@ -218,4 +218,16 @@ describe("findSet()", () => { verify4Set(findSet(["0000", "0102", "0210", "0003"], "4setjrchain", state)); verify4Set(findSet(["0000", "0102", "0210", "3201"], "4setjrchain", state)); }); + + it("can find puzzle 4sets", () => { + const board = ["0000", "0102", "0210", "0312", "1111", "1013", "1203"]; + const state = { foundSets: new Set() }; + for (let i = 0; i < 7; i++) { + const set = findSet(board, "4setjrpuzzle", state); + verify4Set(set); + expect(state.foundSets.has(set.slice().sort().join("|"))).toBe(false); + state.foundSets.add(set.slice().sort().join("|")); + } + expect(findSet(board, "4setjrpuzzle", state)).toBe(null); + }); });