@@ -60,8 +60,8 @@ function makeRandom(seed: string) {
60
60
let c = parseInt ( seed . slice ( 19 , 27 ) , 16 ) >>> 0 ;
61
61
let d = parseInt ( seed . slice ( 27 , 35 ) , 16 ) >>> 0 ;
62
62
return ( ) => {
63
- let t = b << 9 ,
64
- r = b * 5 ;
63
+ const t = b << 9 ;
64
+ let r = b * 5 ;
65
65
r = ( ( r << 7 ) | ( r >>> 25 ) ) * 9 ;
66
66
c ^= a ;
67
67
d ^= b ;
@@ -92,14 +92,15 @@ function shuffleCards(deck: string[], count: number, random: Random) {
92
92
}
93
93
94
94
function generateDeck ( gameMode : GameMode , random : Random | null ) {
95
- const deck = makeCards ( [ "0" , "1" , "2" ] , modes [ gameMode ] . traits ) ;
96
- if ( random ) {
97
- shuffleCards ( deck , deck . length , random ) ;
98
- }
99
- return new Set ( deck ) ;
95
+ const symbols = Array . from (
96
+ Array ( setTypes [ modes [ gameMode ] . setType ] . variants ) ,
97
+ ( _ , i ) => i + ""
98
+ ) ;
99
+ const deck = makeCards ( symbols , modes [ gameMode ] . traits ) ;
100
+ return new Set ( random ? shuffleCards ( deck , deck . length , random ) : deck ) ;
100
101
}
101
102
102
- /** Returns the unique card c such that {a, b, c} form a set. */
103
+ /** Return the unique card c such that {a, b, c} form a set. */
103
104
function conjugateCard ( a : string , b : string ) {
104
105
const zeroCode = "0" . charCodeAt ( 0 ) ;
105
106
let c = "" ;
@@ -112,25 +113,35 @@ function conjugateCard(a: string, b: string) {
112
113
return c ;
113
114
}
114
115
116
+ /** Return the unique card d such that {a, b, c, d} form a 4Set. */
117
+ function conjugateCard4Set ( a : string , b : string , c : string ) {
118
+ let d = "" ;
119
+ for ( let i = 0 ; i < a . length ; i ++ ) {
120
+ d += String . fromCharCode (
121
+ a . charCodeAt ( i ) ^ b . charCodeAt ( i ) ^ c . charCodeAt ( i )
122
+ ) ;
123
+ }
124
+ return d ;
125
+ }
126
+
115
127
/** Check if three cards form a set. */
116
- export function checkSetNormal ( a : string , b : string , c : string ) {
128
+ function checkSetNormal ( a : string , b : string , c : string ) {
117
129
for ( let i = 0 ; i < a . length ; i ++ ) {
118
- if ( ( a . charCodeAt ( i ) + b . charCodeAt ( i ) + c . charCodeAt ( i ) ) % 3 !== 0 )
119
- return null ;
130
+ if ( ( a . charCodeAt ( i ) + b . charCodeAt ( i ) + c . charCodeAt ( i ) ) % 3 ) return null ;
120
131
}
121
132
return [ a , b , c ] ;
122
133
}
123
134
124
135
/** Check if four cards form an ultraset */
125
- export function checkSetUltra ( a : string , b : string , c : string , d : string ) {
136
+ function checkSetUltra ( a : string , b : string , c : string , d : string ) {
126
137
if ( conjugateCard ( a , b ) === conjugateCard ( c , d ) ) return [ a , b , c , d ] ;
127
138
if ( conjugateCard ( a , c ) === conjugateCard ( b , d ) ) return [ a , c , b , d ] ;
128
139
if ( conjugateCard ( a , d ) === conjugateCard ( b , c ) ) return [ a , d , b , c ] ;
129
140
return null ;
130
141
}
131
142
132
143
/** Check if six cards form a ghostset */
133
- export function checkSetGhost (
144
+ function checkSetGhost (
134
145
a : string ,
135
146
b : string ,
136
147
c : string ,
@@ -146,11 +157,20 @@ export function checkSetGhost(
146
157
d . charCodeAt ( i ) +
147
158
e . charCodeAt ( i ) +
148
159
f . charCodeAt ( i ) ;
149
- if ( sum % 3 !== 0 ) return null ;
160
+ if ( sum % 3 ) return null ;
150
161
}
151
162
return [ a , b , c , d , e , f ] ;
152
163
}
153
164
165
+ /** Check if four cards form a 4Set */
166
+ function checkSet4Set ( a : string , b : string , c : string , d : string ) {
167
+ for ( let i = 0 ; i < a . length ; i ++ ) {
168
+ if ( a . charCodeAt ( i ) ^ b . charCodeAt ( i ) ^ c . charCodeAt ( i ) ^ d . charCodeAt ( i ) )
169
+ return null ;
170
+ }
171
+ return [ a , b , c , d ] ;
172
+ }
173
+
154
174
function findSetNormal ( deck : string [ ] , gameMode : GameMode , state : FindState ) {
155
175
const deckSet = new Set ( deck ) ;
156
176
const first =
@@ -221,6 +241,21 @@ function findSetGhost(deck: string[], gameMode: GameMode, state: FindState) {
221
241
return null ;
222
242
}
223
243
244
+ function findSet4Set ( deck : string [ ] , gameMode : GameMode , state : FindState ) {
245
+ const deckSet = new Set ( deck ) ;
246
+ for ( let i = 0 ; i < deck . length ; i ++ ) {
247
+ for ( let j = i + 1 ; j < deck . length ; j ++ ) {
248
+ for ( let k = j + 1 ; k < deck . length ; k ++ ) {
249
+ const c = conjugateCard4Set ( deck [ i ] , deck [ j ] , deck [ k ] ) ;
250
+ if ( deckSet . has ( c ) ) {
251
+ return [ deck [ i ] , deck [ j ] , deck [ k ] , c ] ;
252
+ }
253
+ }
254
+ }
255
+ }
256
+ return null ;
257
+ }
258
+
224
259
/** Find a set in an unordered collection of cards, if any, depending on mode. */
225
260
export function findSet ( deck : string [ ] , gameMode : GameMode , state : FindState ) {
226
261
return setTypes [ modes [ gameMode ] . setType ] . findFn ( deck , gameMode , state ) ;
@@ -251,7 +286,7 @@ function findBoard(
251
286
state : FindState
252
287
) {
253
288
const deckIter = deck . values ( ) ;
254
- let board : string [ ] = [ ] ;
289
+ const board : string [ ] = [ ] ;
255
290
copyFrom ( deckIter , board , minBoardSize ) ;
256
291
while ( board . length < deck . size && ! findSet ( board , gameMode , state ) ) {
257
292
copyFrom ( deckIter , board , 3 - ( board . length % 3 ) ) ;
@@ -316,20 +351,29 @@ function replayEvent(internalGameState: InternalGameState, event: GameEvent) {
316
351
317
352
const setTypes = {
318
353
Set : {
354
+ variants : 3 ,
319
355
size : 3 ,
320
356
checkFn : checkSetNormal ,
321
357
findFn : findSetNormal ,
322
358
} ,
323
359
UltraSet : {
360
+ variants : 3 ,
324
361
size : 4 ,
325
362
checkFn : checkSetUltra ,
326
363
findFn : findSetUltra ,
327
364
} ,
328
365
GhostSet : {
366
+ variants : 3 ,
329
367
size : 6 ,
330
368
checkFn : checkSetGhost ,
331
369
findFn : findSetGhost ,
332
370
} ,
371
+ "4Set" : {
372
+ variants : 4 ,
373
+ size : 4 ,
374
+ checkFn : checkSet4Set ,
375
+ findFn : findSet4Set ,
376
+ } ,
333
377
} ;
334
378
335
379
export const modes = {
@@ -389,6 +433,13 @@ export const modes = {
389
433
puzzle : false ,
390
434
minBoardSize : 10 ,
391
435
} ,
436
+ "4set" : {
437
+ setType : "4Set" ,
438
+ traits : 4 ,
439
+ chain : 0 ,
440
+ puzzle : false ,
441
+ minBoardSize : 15 ,
442
+ } ,
392
443
puzzle : {
393
444
setType : "Set" ,
394
445
traits : 4 ,
0 commit comments