@pompidup/kingdomino-engine 1.1.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,609 +1,929 @@
1
- // src/adapters/driver/index.ts
2
- import { loadEnvFile } from "process";
3
-
4
1
  // src/datasources/dominoes.json
5
- var dominoes_default = [
6
- {
7
- left: {
8
- type: "wheat",
9
- crowns: 0
10
- },
11
- right: {
12
- type: "wheat",
13
- crowns: 0
14
- },
15
- number: 1
16
- },
17
- {
18
- left: {
19
- type: "wheat",
20
- crowns: 0
21
- },
22
- right: {
23
- type: "wheat",
24
- crowns: 0
25
- },
26
- number: 2
27
- },
28
- {
29
- left: {
30
- type: "forest",
31
- crowns: 0
32
- },
33
- right: {
34
- type: "forest",
35
- crowns: 0
36
- },
37
- number: 3
38
- },
39
- {
40
- left: {
41
- type: "forest",
42
- crowns: 0
43
- },
44
- right: {
45
- type: "forest",
46
- crowns: 0
47
- },
48
- number: 4
49
- },
50
- {
51
- left: {
52
- type: "forest",
53
- crowns: 0
54
- },
55
- right: {
56
- type: "forest",
57
- crowns: 0
58
- },
59
- number: 5
60
- },
61
- {
62
- left: {
63
- type: "forest",
64
- crowns: 0
65
- },
66
- right: {
67
- type: "forest",
68
- crowns: 0
69
- },
70
- number: 6
71
- },
72
- {
73
- left: {
74
- type: "water",
75
- crowns: 0
76
- },
77
- right: {
78
- type: "water",
79
- crowns: 0
80
- },
81
- number: 7
82
- },
83
- {
84
- left: {
85
- type: "water",
86
- crowns: 0
87
- },
88
- right: {
89
- type: "water",
90
- crowns: 0
91
- },
92
- number: 8
93
- },
94
- {
95
- left: {
96
- type: "water",
97
- crowns: 0
98
- },
99
- right: {
100
- type: "water",
101
- crowns: 0
102
- },
103
- number: 9
104
- },
105
- {
106
- left: {
107
- type: "grass",
108
- crowns: 0
109
- },
110
- right: {
111
- type: "grass",
112
- crowns: 0
113
- },
114
- number: 10
115
- },
116
- {
117
- left: {
118
- type: "grass",
119
- crowns: 0
120
- },
121
- right: {
122
- type: "grass",
123
- crowns: 0
124
- },
125
- number: 11
126
- },
127
- {
128
- left: {
129
- type: "swamp",
130
- crowns: 0
131
- },
132
- right: {
133
- type: "swamp",
134
- crowns: 0
135
- },
136
- number: 12
137
- },
138
- {
139
- left: {
140
- type: "wheat",
141
- crowns: 0
142
- },
143
- right: {
144
- type: "forest",
145
- crowns: 0
146
- },
147
- number: 13
148
- },
149
- {
150
- left: {
151
- type: "wheat",
152
- crowns: 0
153
- },
154
- right: {
155
- type: "water",
156
- crowns: 0
157
- },
158
- number: 14
159
- },
160
- {
161
- left: {
162
- type: "wheat",
163
- crowns: 0
164
- },
165
- right: {
166
- type: "grass",
167
- crowns: 0
168
- },
169
- number: 15
170
- },
171
- {
172
- left: {
173
- type: "wheat",
174
- crowns: 0
175
- },
176
- right: {
177
- type: "swamp",
178
- crowns: 0
179
- },
180
- number: 16
181
- },
182
- {
183
- left: {
184
- type: "forest",
185
- crowns: 0
186
- },
187
- right: {
188
- type: "water",
189
- crowns: 0
190
- },
191
- number: 17
192
- },
193
- {
194
- left: {
195
- type: "forest",
196
- crowns: 0
197
- },
198
- right: {
199
- type: "grass",
200
- crowns: 0
201
- },
202
- number: 18
203
- },
204
- {
205
- left: {
206
- type: "wheat",
207
- crowns: 1
208
- },
209
- right: {
210
- type: "forest",
211
- crowns: 0
212
- },
213
- number: 19
214
- },
215
- {
216
- left: {
217
- type: "wheat",
218
- crowns: 1
219
- },
220
- right: {
221
- type: "water",
222
- crowns: 0
223
- },
224
- number: 20
225
- },
226
- {
227
- left: {
228
- type: "wheat",
229
- crowns: 1
230
- },
231
- right: {
232
- type: "grass",
233
- crowns: 0
234
- },
235
- number: 21
236
- },
237
- {
238
- left: {
239
- type: "wheat",
240
- crowns: 1
241
- },
242
- right: {
243
- type: "swamp",
244
- crowns: 0
245
- },
246
- number: 22
247
- },
248
- {
249
- left: {
250
- type: "wheat",
251
- crowns: 1
252
- },
253
- right: {
254
- type: "mine",
255
- crowns: 0
256
- },
257
- number: 23
258
- },
259
- {
260
- left: {
261
- type: "forest",
262
- crowns: 1
263
- },
264
- right: {
265
- type: "wheat",
266
- crowns: 0
267
- },
268
- number: 24
269
- },
270
- {
271
- left: {
272
- type: "forest",
273
- crowns: 1
274
- },
275
- right: {
276
- type: "wheat",
277
- crowns: 0
2
+ var dominoes_default = {
3
+ Classic: [
4
+ {
5
+ left: {
6
+ type: "wheat",
7
+ crowns: 0
8
+ },
9
+ right: {
10
+ type: "wheat",
11
+ crowns: 0
12
+ },
13
+ number: 1
278
14
  },
279
- number: 25
280
- },
281
- {
282
- left: {
283
- type: "forest",
284
- crowns: 1
15
+ {
16
+ left: {
17
+ type: "wheat",
18
+ crowns: 0
19
+ },
20
+ right: {
21
+ type: "wheat",
22
+ crowns: 0
23
+ },
24
+ number: 2
285
25
  },
286
- right: {
287
- type: "wheat",
288
- crowns: 0
26
+ {
27
+ left: {
28
+ type: "forest",
29
+ crowns: 0
30
+ },
31
+ right: {
32
+ type: "forest",
33
+ crowns: 0
34
+ },
35
+ number: 3
289
36
  },
290
- number: 26
291
- },
292
- {
293
- left: {
294
- type: "forest",
295
- crowns: 1
37
+ {
38
+ left: {
39
+ type: "forest",
40
+ crowns: 0
41
+ },
42
+ right: {
43
+ type: "forest",
44
+ crowns: 0
45
+ },
46
+ number: 4
296
47
  },
297
- right: {
298
- type: "wheat",
299
- crowns: 0
48
+ {
49
+ left: {
50
+ type: "forest",
51
+ crowns: 0
52
+ },
53
+ right: {
54
+ type: "forest",
55
+ crowns: 0
56
+ },
57
+ number: 5
300
58
  },
301
- number: 27
302
- },
303
- {
304
- left: {
305
- type: "forest",
306
- crowns: 1
59
+ {
60
+ left: {
61
+ type: "forest",
62
+ crowns: 0
63
+ },
64
+ right: {
65
+ type: "forest",
66
+ crowns: 0
67
+ },
68
+ number: 6
307
69
  },
308
- right: {
309
- type: "water",
310
- crowns: 0
70
+ {
71
+ left: {
72
+ type: "sea",
73
+ crowns: 0
74
+ },
75
+ right: {
76
+ type: "sea",
77
+ crowns: 0
78
+ },
79
+ number: 7
311
80
  },
312
- number: 28
313
- },
314
- {
315
- left: {
316
- type: "forest",
317
- crowns: 1
81
+ {
82
+ left: {
83
+ type: "sea",
84
+ crowns: 0
85
+ },
86
+ right: {
87
+ type: "sea",
88
+ crowns: 0
89
+ },
90
+ number: 8
318
91
  },
319
- right: {
320
- type: "grass",
321
- crowns: 0
92
+ {
93
+ left: {
94
+ type: "sea",
95
+ crowns: 0
96
+ },
97
+ right: {
98
+ type: "sea",
99
+ crowns: 0
100
+ },
101
+ number: 9
322
102
  },
323
- number: 29
324
- },
325
- {
326
- left: {
327
- type: "water",
328
- crowns: 1
103
+ {
104
+ left: {
105
+ type: "plain",
106
+ crowns: 0
107
+ },
108
+ right: {
109
+ type: "plain",
110
+ crowns: 0
111
+ },
112
+ number: 10
329
113
  },
330
- right: {
331
- type: "wheat",
332
- crowns: 0
114
+ {
115
+ left: {
116
+ type: "plain",
117
+ crowns: 0
118
+ },
119
+ right: {
120
+ type: "plain",
121
+ crowns: 0
122
+ },
123
+ number: 11
333
124
  },
334
- number: 30
335
- },
336
- {
337
- left: {
338
- type: "water",
339
- crowns: 1
125
+ {
126
+ left: {
127
+ type: "swamp",
128
+ crowns: 0
129
+ },
130
+ right: {
131
+ type: "swamp",
132
+ crowns: 0
133
+ },
134
+ number: 12
340
135
  },
341
- right: {
342
- type: "wheat",
343
- crowns: 0
136
+ {
137
+ left: {
138
+ type: "wheat",
139
+ crowns: 0
140
+ },
141
+ right: {
142
+ type: "forest",
143
+ crowns: 0
144
+ },
145
+ number: 13
344
146
  },
345
- number: 31
346
- },
347
- {
348
- left: {
349
- type: "water",
350
- crowns: 1
147
+ {
148
+ left: {
149
+ type: "wheat",
150
+ crowns: 0
151
+ },
152
+ right: {
153
+ type: "sea",
154
+ crowns: 0
155
+ },
156
+ number: 14
351
157
  },
352
- right: {
353
- type: "forest",
354
- crowns: 0
158
+ {
159
+ left: {
160
+ type: "wheat",
161
+ crowns: 0
162
+ },
163
+ right: {
164
+ type: "plain",
165
+ crowns: 0
166
+ },
167
+ number: 15
355
168
  },
356
- number: 32
357
- },
358
- {
359
- left: {
360
- type: "water",
361
- crowns: 1
169
+ {
170
+ left: {
171
+ type: "wheat",
172
+ crowns: 0
173
+ },
174
+ right: {
175
+ type: "swamp",
176
+ crowns: 0
177
+ },
178
+ number: 16
362
179
  },
363
- right: {
364
- type: "forest",
365
- crowns: 0
180
+ {
181
+ left: {
182
+ type: "forest",
183
+ crowns: 0
184
+ },
185
+ right: {
186
+ type: "sea",
187
+ crowns: 0
188
+ },
189
+ number: 17
366
190
  },
367
- number: 33
368
- },
369
- {
370
- left: {
371
- type: "water",
372
- crowns: 1
191
+ {
192
+ left: {
193
+ type: "forest",
194
+ crowns: 0
195
+ },
196
+ right: {
197
+ type: "plain",
198
+ crowns: 0
199
+ },
200
+ number: 18
373
201
  },
374
- right: {
375
- type: "forest",
376
- crowns: 0
202
+ {
203
+ left: {
204
+ type: "wheat",
205
+ crowns: 1
206
+ },
207
+ right: {
208
+ type: "forest",
209
+ crowns: 0
210
+ },
211
+ number: 19
377
212
  },
378
- number: 34
379
- },
380
- {
381
- left: {
382
- type: "water",
383
- crowns: 1
213
+ {
214
+ left: {
215
+ type: "wheat",
216
+ crowns: 1
217
+ },
218
+ right: {
219
+ type: "sea",
220
+ crowns: 0
221
+ },
222
+ number: 20
384
223
  },
385
- right: {
386
- type: "forest",
387
- crowns: 0
224
+ {
225
+ left: {
226
+ type: "wheat",
227
+ crowns: 1
228
+ },
229
+ right: {
230
+ type: "plain",
231
+ crowns: 0
232
+ },
233
+ number: 21
388
234
  },
389
- number: 35
390
- },
391
- {
392
- left: {
393
- type: "wheat",
394
- crowns: 0
235
+ {
236
+ left: {
237
+ type: "wheat",
238
+ crowns: 1
239
+ },
240
+ right: {
241
+ type: "swamp",
242
+ crowns: 0
243
+ },
244
+ number: 22
395
245
  },
396
- right: {
397
- type: "grass",
398
- crowns: 1
246
+ {
247
+ left: {
248
+ type: "wheat",
249
+ crowns: 1
250
+ },
251
+ right: {
252
+ type: "mine",
253
+ crowns: 0
254
+ },
255
+ number: 23
399
256
  },
400
- number: 36
401
- },
402
- {
403
- left: {
404
- type: "water",
405
- crowns: 0
257
+ {
258
+ left: {
259
+ type: "forest",
260
+ crowns: 1
261
+ },
262
+ right: {
263
+ type: "wheat",
264
+ crowns: 0
265
+ },
266
+ number: 24
406
267
  },
407
- right: {
408
- type: "grass",
409
- crowns: 1
268
+ {
269
+ left: {
270
+ type: "forest",
271
+ crowns: 1
272
+ },
273
+ right: {
274
+ type: "wheat",
275
+ crowns: 0
276
+ },
277
+ number: 25
410
278
  },
411
- number: 37
412
- },
413
- {
414
- left: {
415
- type: "wheat",
416
- crowns: 0
279
+ {
280
+ left: {
281
+ type: "forest",
282
+ crowns: 1
283
+ },
284
+ right: {
285
+ type: "wheat",
286
+ crowns: 0
287
+ },
288
+ number: 26
417
289
  },
418
- right: {
419
- type: "swamp",
420
- crowns: 1
290
+ {
291
+ left: {
292
+ type: "forest",
293
+ crowns: 1
294
+ },
295
+ right: {
296
+ type: "wheat",
297
+ crowns: 0
298
+ },
299
+ number: 27
421
300
  },
422
- number: 38
423
- },
424
- {
425
- left: {
426
- type: "grass",
427
- crowns: 0
301
+ {
302
+ left: {
303
+ type: "forest",
304
+ crowns: 1
305
+ },
306
+ right: {
307
+ type: "sea",
308
+ crowns: 0
309
+ },
310
+ number: 28
428
311
  },
429
- right: {
430
- type: "swamp",
431
- crowns: 0
312
+ {
313
+ left: {
314
+ type: "forest",
315
+ crowns: 1
316
+ },
317
+ right: {
318
+ type: "plain",
319
+ crowns: 0
320
+ },
321
+ number: 29
432
322
  },
433
- number: 39
434
- },
435
- {
436
- left: {
437
- type: "mine",
438
- crowns: 1
323
+ {
324
+ left: {
325
+ type: "sea",
326
+ crowns: 1
327
+ },
328
+ right: {
329
+ type: "wheat",
330
+ crowns: 0
331
+ },
332
+ number: 30
439
333
  },
440
- right: {
441
- type: "wheat",
442
- crowns: 0
334
+ {
335
+ left: {
336
+ type: "sea",
337
+ crowns: 1
338
+ },
339
+ right: {
340
+ type: "wheat",
341
+ crowns: 0
342
+ },
343
+ number: 31
443
344
  },
444
- number: 40
445
- },
446
- {
447
- left: {
448
- type: "wheat",
449
- crowns: 0
345
+ {
346
+ left: {
347
+ type: "sea",
348
+ crowns: 1
349
+ },
350
+ right: {
351
+ type: "forest",
352
+ crowns: 0
353
+ },
354
+ number: 32
450
355
  },
451
- right: {
452
- type: "grass",
453
- crowns: 2
356
+ {
357
+ left: {
358
+ type: "sea",
359
+ crowns: 1
360
+ },
361
+ right: {
362
+ type: "forest",
363
+ crowns: 0
364
+ },
365
+ number: 33
454
366
  },
455
- number: 41
456
- },
457
- {
458
- left: {
459
- type: "water",
460
- crowns: 0
367
+ {
368
+ left: {
369
+ type: "sea",
370
+ crowns: 1
371
+ },
372
+ right: {
373
+ type: "forest",
374
+ crowns: 0
375
+ },
376
+ number: 34
461
377
  },
462
- right: {
463
- type: "grass",
464
- crowns: 2
378
+ {
379
+ left: {
380
+ type: "sea",
381
+ crowns: 1
382
+ },
383
+ right: {
384
+ type: "forest",
385
+ crowns: 0
386
+ },
387
+ number: 35
465
388
  },
466
- number: 42
467
- },
468
- {
469
- left: {
470
- type: "wheat",
471
- crowns: 0
389
+ {
390
+ left: {
391
+ type: "wheat",
392
+ crowns: 0
393
+ },
394
+ right: {
395
+ type: "plain",
396
+ crowns: 1
397
+ },
398
+ number: 36
472
399
  },
473
- right: {
474
- type: "swamp",
475
- crowns: 2
400
+ {
401
+ left: {
402
+ type: "sea",
403
+ crowns: 0
404
+ },
405
+ right: {
406
+ type: "plain",
407
+ crowns: 1
408
+ },
409
+ number: 37
476
410
  },
477
- number: 43
478
- },
479
- {
480
- left: {
481
- type: "grass",
482
- crowns: 0
411
+ {
412
+ left: {
413
+ type: "wheat",
414
+ crowns: 0
415
+ },
416
+ right: {
417
+ type: "swamp",
418
+ crowns: 1
419
+ },
420
+ number: 38
483
421
  },
484
- right: {
485
- type: "swamp",
486
- crowns: 2
422
+ {
423
+ left: {
424
+ type: "plain",
425
+ crowns: 0
426
+ },
427
+ right: {
428
+ type: "swamp",
429
+ crowns: 0
430
+ },
431
+ number: 39
487
432
  },
488
- number: 44
489
- },
490
- {
491
- left: {
492
- type: "mine",
493
- crowns: 2
433
+ {
434
+ left: {
435
+ type: "mine",
436
+ crowns: 1
437
+ },
438
+ right: {
439
+ type: "wheat",
440
+ crowns: 0
441
+ },
442
+ number: 40
494
443
  },
495
- right: {
496
- type: "wheat",
497
- crowns: 0
444
+ {
445
+ left: {
446
+ type: "wheat",
447
+ crowns: 0
448
+ },
449
+ right: {
450
+ type: "plain",
451
+ crowns: 2
452
+ },
453
+ number: 41
498
454
  },
499
- number: 45
500
- },
501
- {
502
- left: {
503
- type: "swamp",
504
- crowns: 0
455
+ {
456
+ left: {
457
+ type: "sea",
458
+ crowns: 0
459
+ },
460
+ right: {
461
+ type: "plain",
462
+ crowns: 2
463
+ },
464
+ number: 42
505
465
  },
506
- right: {
507
- type: "mine",
508
- crowns: 2
466
+ {
467
+ left: {
468
+ type: "wheat",
469
+ crowns: 0
470
+ },
471
+ right: {
472
+ type: "swamp",
473
+ crowns: 2
474
+ },
475
+ number: 43
509
476
  },
510
- number: 46
511
- },
512
- {
513
- left: {
514
- type: "swamp",
515
- crowns: 0
477
+ {
478
+ left: {
479
+ type: "plain",
480
+ crowns: 0
481
+ },
482
+ right: {
483
+ type: "swamp",
484
+ crowns: 2
485
+ },
486
+ number: 44
516
487
  },
517
- right: {
518
- type: "mine",
519
- crowns: 2
488
+ {
489
+ left: {
490
+ type: "mine",
491
+ crowns: 2
492
+ },
493
+ right: {
494
+ type: "wheat",
495
+ crowns: 0
496
+ },
497
+ number: 45
520
498
  },
521
- number: 47
522
- },
523
- {
524
- left: {
525
- type: "wheat",
526
- crowns: 0
499
+ {
500
+ left: {
501
+ type: "swamp",
502
+ crowns: 0
503
+ },
504
+ right: {
505
+ type: "mine",
506
+ crowns: 2
507
+ },
508
+ number: 46
527
509
  },
528
- right: {
529
- type: "mine",
530
- crowns: 3
510
+ {
511
+ left: {
512
+ type: "swamp",
513
+ crowns: 0
514
+ },
515
+ right: {
516
+ type: "mine",
517
+ crowns: 2
518
+ },
519
+ number: 47
531
520
  },
532
- number: 48
533
- }
534
- ];
535
-
536
- // src/adapters/driven/inMemoryDominoes.ts
537
- var inMemoryDominoes = () => {
538
- const dominoes = [];
539
- dominoes_default.forEach((domino) => {
540
- dominoes.push({
521
+ {
541
522
  left: {
542
- type: domino.left.type,
543
- crowns: domino.left.crowns
523
+ type: "wheat",
524
+ crowns: 0
544
525
  },
545
526
  right: {
546
- type: domino.right.type,
547
- crowns: domino.right.crowns
527
+ type: "mine",
528
+ crowns: 3
548
529
  },
549
- number: domino.number
530
+ number: 48
531
+ }
532
+ ]
533
+ };
534
+
535
+ // src/adapterServerside/jsonDominoes.ts
536
+ var jsonDominoes = () => {
537
+ const dominoes = {};
538
+ for (const [key, value] of Object.entries(dominoes_default)) {
539
+ const currentDominoes = [];
540
+ value.forEach((domino) => {
541
+ currentDominoes.push({
542
+ left: {
543
+ type: domino.left.type,
544
+ crowns: domino.left.crowns
545
+ },
546
+ right: {
547
+ type: domino.right.type,
548
+ crowns: domino.right.crowns
549
+ },
550
+ number: domino.number
551
+ });
552
+ });
553
+ dominoes[key] = currentDominoes;
554
+ }
555
+ return {
556
+ getForMode: (mode) => {
557
+ return dominoes[mode.name] || [];
558
+ }
559
+ };
560
+ };
561
+ var jsonDominoes_default = jsonDominoes;
562
+
563
+ // src/datasources/modes.json
564
+ var modes_default = [
565
+ {
566
+ name: "Classic",
567
+ description: "Original KingDomino rules"
568
+ }
569
+ ];
570
+
571
+ // src/adapterServerside/jsonModes.ts
572
+ var jsonModes = () => {
573
+ const modes = [];
574
+ modes_default.forEach((mode) => {
575
+ modes.push({
576
+ name: mode.name,
577
+ description: mode.description
578
+ });
579
+ });
580
+ return {
581
+ getAvailables: () => {
582
+ return modes;
583
+ }
584
+ };
585
+ };
586
+ var jsonModes_default = jsonModes;
587
+
588
+ // src/datasources/rules.json
589
+ var rules_default = {
590
+ commun: [
591
+ {
592
+ playersLimit: 2,
593
+ lordsPerPlayer: 2,
594
+ maxDominoes: 24,
595
+ dominoesPerTurn: 4,
596
+ maxTurns: 6
597
+ },
598
+ {
599
+ playersLimit: 3,
600
+ lordsPerPlayer: 1,
601
+ maxDominoes: 36,
602
+ dominoesPerTurn: 3,
603
+ maxTurns: 12
604
+ },
605
+ {
606
+ playersLimit: 4,
607
+ lordsPerPlayer: 1,
608
+ maxDominoes: 48,
609
+ dominoesPerTurn: 4,
610
+ maxTurns: 12
611
+ }
612
+ ],
613
+ extra: [
614
+ {
615
+ name: "The middle Kingdom",
616
+ description: "Gain 10 additional points if your castle is in the middle of the kingdom.",
617
+ mode: [{ name: "Classic", description: "King Domino classic mode" }]
618
+ },
619
+ {
620
+ name: "Harmony",
621
+ description: "Gain 5 additional points if your kingdom is complete (no discarded dominoes).",
622
+ mode: [{ name: "Classic", description: "King Domino classic mode" }]
623
+ }
624
+ ]
625
+ };
626
+
627
+ // src/adapterServerside/jsonRules.ts
628
+ var jsonRules = () => {
629
+ const rules = {
630
+ basic: {},
631
+ extraRules: []
632
+ };
633
+ const commonRules = rules_default.commun;
634
+ const extraRules = rules_default.extra;
635
+ commonRules.forEach((rule) => {
636
+ rules.basic[rule.playersLimit] = {
637
+ lords: rule.lordsPerPlayer,
638
+ maxDominoes: rule.maxDominoes,
639
+ dominoesPerTurn: rule.dominoesPerTurn,
640
+ maxTurns: rule.maxTurns
641
+ };
642
+ });
643
+ extraRules.forEach((rule) => {
644
+ rules.extraRules.push({
645
+ name: rule.name,
646
+ description: rule.description,
647
+ mode: rule.mode
550
648
  });
551
649
  });
552
650
  return {
553
651
  getAll: () => {
554
- return dominoes;
652
+ return rules;
653
+ },
654
+ getAllExtra: () => {
655
+ return rules.extraRules;
555
656
  }
556
657
  };
557
658
  };
558
- var inMemoryDominoes_default = inMemoryDominoes;
659
+ var jsonRules_default = jsonRules;
559
660
 
560
- // src/hexagon/internal/services/init.ts
561
- var init = (dependencies) => () => {
562
- const dominoes = dependencies.dominoesRepository.getAll();
563
- const id = dependencies.uuidMethod();
564
- const state = {
565
- id,
566
- dominoes,
567
- currentDominoes: [],
568
- players: [],
569
- lords: [],
570
- turn: 0,
571
- maxTurns: 0,
572
- maxDominoes: 0,
573
- dominoesPerTurn: 0,
574
- order: {}
661
+ // src/utils/result.ts
662
+ var ok = (value) => ({ tag: "Ok", value });
663
+ var err = (error) => ({ tag: "Err", error });
664
+ var isOk = (result) => result.tag === "Ok";
665
+ var isErr = (result) => result.tag === "Err";
666
+
667
+ // src/application/handlers/addExtraRulesHandler.ts
668
+ var addExtraRulesHandler = (useCase) => (command) => {
669
+ const { game, extraRules } = command;
670
+ if (game.nextAction.step !== "options") {
671
+ throw new Error("Invalid next action");
672
+ }
673
+ const result = useCase(game, extraRules);
674
+ if (isErr(result)) {
675
+ throw new Error(result.error);
676
+ }
677
+ return result.value;
678
+ };
679
+
680
+ // src/application/handlers/addPlayersHandler.ts
681
+ var addPlayersHandler = (useCase) => (command) => {
682
+ const { game, players } = command;
683
+ if (game.nextAction.step !== "addPlayers") {
684
+ throw new Error("Invalid next action");
685
+ }
686
+ const result = useCase(game, players);
687
+ if (isErr(result)) {
688
+ throw new Error(result.error);
689
+ }
690
+ return result.value;
691
+ };
692
+
693
+ // src/application/handlers/chooseDominoHandler.ts
694
+ var chooseDominoHandler = (useCase) => (command) => {
695
+ const { game, lordId, dominoPick } = command;
696
+ if (game.nextAction.nextAction !== "pickDomino") {
697
+ throw new Error("Invalid next action");
698
+ }
699
+ const result = useCase(game, lordId, dominoPick);
700
+ if (isErr(result)) {
701
+ throw new Error(result.error);
702
+ }
703
+ return result.value;
704
+ };
705
+
706
+ // src/application/handlers/createGameHandler.ts
707
+ var createGameHandler = (useCase) => (command) => {
708
+ const result = useCase(command.mode);
709
+ if (isErr(result)) {
710
+ throw new Error(result.error);
711
+ }
712
+ return result.value;
713
+ };
714
+
715
+ // src/core/domain/types/game.ts
716
+ var gameSteps = {
717
+ addPlayers: "addPlayers",
718
+ options: "options",
719
+ start: "start",
720
+ result: "result"
721
+ };
722
+ var isGameWithNextAction = (game) => {
723
+ return game.nextAction.type === "action";
724
+ };
725
+
726
+ // src/application/handlers/discardDominoHandler.ts
727
+ var discardDominoHandler = (useCase) => (command) => {
728
+ const { game, lordId } = command;
729
+ if (game.nextAction.nextAction !== "placeDomino") {
730
+ throw new Error("Invalid next action");
731
+ }
732
+ const result = useCase(game, lordId);
733
+ if (isErr(result)) {
734
+ throw new Error(result.error);
735
+ }
736
+ if (isGameWithNextAction(result.value)) {
737
+ return result.value;
738
+ }
739
+ return result.value;
740
+ };
741
+
742
+ // src/application/handlers/getExtraRulesHandler.ts
743
+ var getExtraRulesHandler = (getExtraRulesUseCase2) => (command) => {
744
+ const { mode, players } = command;
745
+ const result = getExtraRulesUseCase2(mode, players);
746
+ if (isErr(result)) {
747
+ throw new Error(result.error);
748
+ }
749
+ return result.value;
750
+ };
751
+
752
+ // src/application/handlers/getModesHandler.ts
753
+ var getModesHandler = (getModeUseCase) => (_command) => {
754
+ const result = getModeUseCase();
755
+ if (isErr(result)) {
756
+ throw new Error(result.error);
757
+ }
758
+ return result.value;
759
+ };
760
+
761
+ // src/application/handlers/getResultHandler.ts
762
+ var getResultHandler = (useCase) => (command) => {
763
+ const { game } = command;
764
+ if (game.nextAction.step !== "result") {
765
+ throw new Error("Invalid next step");
766
+ }
767
+ const result = useCase(game);
768
+ if (isErr(result)) {
769
+ throw new Error(result.error);
770
+ }
771
+ return result.value;
772
+ };
773
+
774
+ // src/application/handlers/placeDominoHandler.ts
775
+ var placeDominoHandler = (useCase) => (command) => {
776
+ const { game, lordId, position, orientation, rotation } = command;
777
+ if (game.nextAction.nextAction !== "placeDomino") {
778
+ throw new Error("Invalid next action");
779
+ }
780
+ const result = useCase(game, lordId, position, orientation, rotation);
781
+ if (isErr(result)) {
782
+ throw new Error(result.error);
783
+ }
784
+ if (isGameWithNextAction(result.value)) {
785
+ return result.value;
786
+ }
787
+ return result.value;
788
+ };
789
+
790
+ // src/application/handlers/startGameHandler.ts
791
+ var startGameHandler = (useCase) => (command) => {
792
+ const { game } = command;
793
+ if (game.nextAction.step !== "start") {
794
+ throw new Error("Invalid next action");
795
+ }
796
+ const result = useCase(game);
797
+ if (isErr(result)) {
798
+ throw new Error(result.error);
799
+ }
800
+ return result.value;
801
+ };
802
+
803
+ // src/core/domain/types/kingdom.ts
804
+ var GRIDSIZE = 9;
805
+
806
+ // src/core/domain/types/domino.ts
807
+ var GROUND = [
808
+ "castle",
809
+ "wheat",
810
+ "forest",
811
+ "sea",
812
+ "plain",
813
+ "swamp",
814
+ "mine"
815
+ ];
816
+
817
+ // src/core/domain/types/player.ts
818
+ var playerActions = {
819
+ placeDomino: "placeDomino",
820
+ pickDomino: "pickDomino",
821
+ pass: "pass"
822
+ };
823
+
824
+ // src/core/domain/entities/rule.ts
825
+ var getAvailablesExtraRules = (extraRules, mode, numberOfPlayers) => {
826
+ const availableExtraRules = extraRules.filter((rule) => {
827
+ return rule.mode.filter((m) => m.name === mode).length > 0 && (!rule.playersLimit || rule.playersLimit === numberOfPlayers);
828
+ });
829
+ if (availableExtraRules.length === 0) {
830
+ return err("No extra rules found");
831
+ }
832
+ return ok(availableExtraRules);
833
+ };
834
+ var toExtraRule = (rule, extraRules) => {
835
+ const foundRule = extraRules.find((r) => r.name === rule);
836
+ if (!foundRule) {
837
+ return err(`Rule not found: ${rule}`);
838
+ }
839
+ return ok(foundRule);
840
+ };
841
+
842
+ // src/core/useCases/addExtraRules.ts
843
+ var addExtraRulesUseCase = (deps) => (game, rules) => {
844
+ const { ruleRepository } = deps;
845
+ const availableExtraRules = ruleRepository.getAllExtra();
846
+ const newExtraRules = [];
847
+ for (const rule of rules) {
848
+ const result = toExtraRule(rule, availableExtraRules);
849
+ if (isErr(result)) {
850
+ return result;
851
+ }
852
+ newExtraRules.push(result.value);
853
+ }
854
+ const updatedRules = {
855
+ basic: game.rules.basic,
856
+ extra: newExtraRules
857
+ };
858
+ const next = {
859
+ type: "step",
860
+ step: gameSteps.start
861
+ };
862
+ const updatedGame = {
863
+ ...game,
864
+ rules: updatedRules,
865
+ nextAction: next
575
866
  };
576
- return state;
867
+ return ok(updatedGame);
577
868
  };
578
869
 
579
- // src/hexagon/internal/entities/kingdom.ts
870
+ // src/core/domain/entities/player.ts
871
+ var MINPLAYERSNAMELENGTH = 3;
872
+ var validatePlayer = (name) => {
873
+ if (!name || name.trim().length < MINPLAYERSNAMELENGTH) {
874
+ return err(`Invalid player name: ${name}`);
875
+ }
876
+ return ok(name);
877
+ };
878
+ var createPlayer = (playerName, id, kingdom) => {
879
+ const name = validatePlayer(playerName);
880
+ if (isErr(name)) {
881
+ return name;
882
+ }
883
+ return ok({
884
+ name: name.value,
885
+ id,
886
+ kingdom
887
+ });
888
+ };
889
+
890
+ // src/core/domain/entities/domino.ts
891
+ var isGround = (ground) => {
892
+ return GROUND.includes(ground);
893
+ };
894
+ var createTile = (ground, crowns = 0) => {
895
+ if (isGround(ground)) {
896
+ return { type: ground, crowns };
897
+ }
898
+ return { type: ground, crowns: 0 };
899
+ };
900
+
901
+ // src/core/domain/entities/kingdom.ts
580
902
  var createEmptyKingdom = () => {
581
- const gridSize = 9;
582
- const emptyTile = { type: "empty", crowns: 0 };
583
- return Array.from(
584
- { length: gridSize },
585
- () => Array.from({ length: gridSize }, () => emptyTile)
903
+ const emptyTile = createTile("empty");
904
+ const grid = Array.from(
905
+ { length: GRIDSIZE },
906
+ () => Array.from({ length: GRIDSIZE }, () => emptyTile)
586
907
  );
908
+ return grid;
587
909
  };
588
- var createKingdomWithCastle = () => {
589
- const kingdom2 = createEmptyKingdom();
590
- return placeTile(kingdom2, { x: 4, y: 4 }, { type: "castle", crowns: 0 });
591
- };
592
- var placeTile = (kingdom2, position, tile) => {
593
- const newRow = [...kingdom2[position.y]];
594
- newRow[position.x] = tile;
595
- return [
596
- ...kingdom2.slice(0, position.y),
597
- newRow,
598
- ...kingdom2.slice(position.y + 1)
599
- ];
910
+ var placeCastle = (kingdom) => {
911
+ const castle = createTile("castle");
912
+ const newKingdom = deepCopyKingdom(kingdom);
913
+ newKingdom[4][4] = castle;
914
+ return newKingdom;
915
+ };
916
+ var placeTile = (kingdom, position, tile) => {
917
+ const newKingdom = deepCopyKingdom(kingdom);
918
+ newKingdom[position.y][position.x] = tile;
919
+ return newKingdom;
600
920
  };
601
- var getTile = (grid, position) => {
602
- const tile = grid[position.y]?.[position.x];
603
- if (tile === void 0) {
604
- throw new Error("Invalid placement (not fit into the grid)");
921
+ var getTile = (kingdom, position) => {
922
+ const tile = kingdom[position.y]?.[position.x];
923
+ if (!tile) {
924
+ return err("Invalid placement (not fit into the grid)");
605
925
  }
606
- return tile;
926
+ return ok(tile);
607
927
  };
608
928
  var calculateDominoPosition = (position, orientation, rotation, domino) => {
609
929
  let firstTile;
@@ -675,51 +995,60 @@ var calculateDominoPosition = (position, orientation, rotation, domino) => {
675
995
  }
676
996
  return [firstTile, secondTile];
677
997
  };
678
- var placeDomino = (kingdom2, position, orientation, rotation, domino) => {
998
+ var placeDomino = (kingdom, position, orientation, rotation, domino) => {
679
999
  const [firstTile, secondTile] = calculateDominoPosition(
680
1000
  position,
681
1001
  orientation,
682
1002
  rotation,
683
1003
  domino
684
1004
  );
685
- if (!isFreePlace(kingdom2, firstTile.position, secondTile.position)) {
686
- throw new Error("Invalid placement (not free place)");
687
- }
688
- if (!isFitIntoTheGrid(kingdom2, [firstTile, secondTile])) {
689
- throw new Error("Invalid placement (not fit into the grid)");
1005
+ const isFreePlaceResult = isFreePlace(
1006
+ kingdom,
1007
+ firstTile.position,
1008
+ secondTile.position
1009
+ );
1010
+ if (isErr(isFreePlaceResult)) {
1011
+ return isFreePlaceResult;
690
1012
  }
691
1013
  const adjacentTiles = isAdjacent(
692
- kingdom2,
1014
+ kingdom,
693
1015
  firstTile.position,
694
1016
  secondTile.position
695
1017
  );
696
1018
  if (adjacentTiles.length === 0) {
697
- throw new Error("Invalid placement (no adjacent)");
1019
+ return err("Invalid placement (not adjacent)");
698
1020
  }
699
1021
  const hasValidAdjacentTiles = hasValidAdjacent(adjacentTiles, [
700
1022
  firstTile.tile,
701
1023
  secondTile.tile
702
1024
  ]);
703
1025
  if (!hasValidAdjacentTiles) {
704
- throw new Error("Invalid placement (no valid adjacent)");
1026
+ return err("Invalid placement (not valid adjacent)");
705
1027
  }
706
- return placeTiles(kingdom2, [firstTile, secondTile]);
1028
+ return ok(placeTiles(kingdom, [firstTile, secondTile]));
707
1029
  };
708
- var placeTiles = (kingdom2, tiles) => {
709
- return tiles.reduce(
710
- (newKingdom, { tile, position }) => placeTile(newKingdom, position, tile),
711
- kingdom2
712
- );
1030
+ var placeTiles = (kingdom, tiles) => {
1031
+ let newKingdom = deepCopyKingdom(kingdom);
1032
+ for (const { tile, position } of tiles) {
1033
+ newKingdom = placeTile(newKingdom, position, tile);
1034
+ }
1035
+ return newKingdom;
713
1036
  };
714
- var isFreePlace = (kingdom2, firstPosition, secondPosition) => {
715
- const firstTile = getTile(kingdom2, firstPosition);
716
- const secondTile = getTile(kingdom2, secondPosition);
717
- if (firstTile.type !== "empty" || secondTile.type !== "empty") {
718
- return false;
1037
+ var isFreePlace = (kingdom, firstPosition, secondPosition) => {
1038
+ const firstTile = getTile(kingdom, firstPosition);
1039
+ const secondTile = getTile(kingdom, secondPosition);
1040
+ if (isErr(firstTile)) {
1041
+ return firstTile;
1042
+ }
1043
+ if (isErr(secondTile)) {
1044
+ return secondTile;
719
1045
  }
720
- return true;
1046
+ if (firstTile.value.type !== "empty" || secondTile.value.type !== "empty") {
1047
+ return err("Invalid placement (not empty)");
1048
+ }
1049
+ return ok(true);
721
1050
  };
722
- var isAdjacent = (kingdom2, firstPosition, secondPosition) => {
1051
+ var isAdjacent = (kingdom, firstPosition, secondPosition) => {
723
1052
  const xFirstPosition = firstPosition.x;
724
1053
  const yFirstPosition = firstPosition.y;
725
1054
  const xSecondPosition = secondPosition.x;
@@ -748,9 +1077,11 @@ var isAdjacent = (kingdom2, firstPosition, secondPosition) => {
748
1077
  1
749
1078
  );
750
1079
  adjacentTilesKeys.forEach((key) => {
751
- const tile = getTile(kingdom2, key);
752
- if (tile) {
753
- adjacentTiles.push(tile);
1080
+ const tile = getTile(kingdom, key);
1081
+ if (isOk(tile)) {
1082
+ if (tile.value.type !== "empty") {
1083
+ adjacentTiles.push(tile.value);
1084
+ }
754
1085
  }
755
1086
  });
756
1087
  return adjacentTiles;
@@ -762,675 +1093,722 @@ var hasValidAdjacent = (adjacentTiles, tiles) => {
762
1093
  });
763
1094
  });
764
1095
  };
765
- var isFitIntoTheGrid = (grid, positions) => {
766
- const maxSize = 5;
767
- const simulateNewGrid = [...grid];
768
- simulateNewGrid[positions[0].position.y][positions[0].position.x] = positions[0].tile;
769
- simulateNewGrid[positions[1].position.y][positions[1].position.x] = positions[1].tile;
770
- const lines = simulateNewGrid.map(
771
- (line) => line.filter((tile) => tile.type !== "empty")
772
- );
773
- const columns = simulateNewGrid[0].map(
774
- (_, index) => simulateNewGrid.map((line) => line[index]).filter((tile) => tile?.type !== "empty")
775
- );
776
- const linesLength = lines.map((line) => line.length);
777
- const columnsLength = columns.map((line) => line.length);
778
- const maxLineLength = Math.max(...linesLength);
779
- const maxColumnLength = Math.max(...columnsLength);
780
- if (maxLineLength > maxSize || maxColumnLength > maxSize) {
781
- return false;
782
- }
783
- return true;
784
- };
785
- var kingdom = {
786
- createEmptyKingdom,
787
- createKingdomWithCastle,
788
- getTile,
789
- placeDomino
790
- };
791
- var kingdom_default = kingdom;
792
-
793
- // src/hexagon/internal/services/setup.ts
794
- var setup = (dependencies) => (payload) => {
795
- const { state, players } = payload;
796
- if (!players) {
797
- throw new Error("There must be at least 2 players");
798
- }
799
- if (players.length > 4) {
800
- throw new Error("There must be no more than 4 players");
801
- }
802
- if (players.length < 2) {
803
- throw new Error("There must be at least 2 players");
804
- }
805
- const { dominoes } = state;
806
- const { shuffleMethod: shuffleMethod2, uuidMethod: uuidMethod2 } = dependencies;
807
- const { maxDominoes, dominoesPerTurn, maxTurns } = rules[players.length];
808
- const shuffledDominoes = shuffleMethod2(dominoes);
809
- shuffledDominoes.splice(maxDominoes);
810
- const newPlayers = players.map((player) => {
811
- return {
812
- ...player,
813
- kingdom: kingdom_default.createKingdomWithCastle(),
814
- id: uuidMethod2()
815
- };
816
- });
817
- let newLords;
818
- if (newPlayers.length === 2) {
819
- newLords = [
820
- {
821
- id: uuidMethod2(),
822
- playerId: newPlayers[0].id,
823
- order: 1,
824
- turnEnded: false,
825
- hasPick: false,
826
- hasPlace: false
827
- },
828
- {
829
- id: uuidMethod2(),
830
- playerId: newPlayers[0].id,
831
- order: 2,
832
- turnEnded: false,
833
- hasPick: false,
834
- hasPlace: false
835
- },
836
- {
837
- id: uuidMethod2(),
838
- playerId: newPlayers[1].id,
839
- order: 3,
840
- turnEnded: false,
841
- hasPick: false,
842
- hasPlace: false
843
- },
844
- {
845
- id: uuidMethod2(),
846
- playerId: newPlayers[1].id,
847
- order: 4,
848
- turnEnded: false,
849
- hasPick: false,
850
- hasPlace: false
851
- }
852
- ];
853
- } else {
854
- newLords = newPlayers.map((player, index) => {
855
- return {
856
- id: uuidMethod2(),
857
- playerId: player.id,
858
- order: index + 1,
859
- turnEnded: false,
860
- hasPick: false,
861
- hasPlace: false
862
- };
863
- });
864
- }
865
- const lordsWithOrder = shuffleMethod2(newLords);
866
- lordsWithOrder.forEach((lord, index) => {
867
- lord.order = index + 1;
868
- });
869
- lordsWithOrder.sort((a, b) => a.order - b.order);
870
- const newState = {
871
- ...state,
872
- dominoes: shuffledDominoes,
873
- players: newPlayers,
874
- lords: lordsWithOrder,
875
- maxTurns,
876
- maxDominoes,
877
- dominoesPerTurn,
878
- turn: 0
879
- };
880
- return newState;
881
- };
882
-
883
- // src/hexagon/internal/services/startTurn.ts
884
- var startTurn = (payload) => {
885
- const { state } = payload;
886
- const turn = state.turn + 1;
887
- const lords = state.lords;
888
- lords.forEach((lord) => {
889
- lord.turnEnded = false;
890
- lord.hasPick = false;
891
- lord.hasPlace = false;
892
- });
893
- const updatedState = {
894
- ...state,
895
- lords,
896
- turn
897
- };
898
- return { game: updatedState };
1096
+ var checkCastleIsInMiddle = (kingdom) => {
1097
+ const castlePosition = kingdom.map((row) => row.findIndex((tile) => tile.type === "castle")).find((index) => index !== -1);
1098
+ const leftTiles = castlePosition !== void 0 ? kingdom[castlePosition].slice(0, castlePosition) : [];
1099
+ const leftTilesCount = leftTiles.filter(
1100
+ (tile) => tile.type !== "empty"
1101
+ ).length;
1102
+ const rightTiles = castlePosition !== void 0 ? kingdom[castlePosition].slice(castlePosition + 1) : [];
1103
+ const rightTilesCount = rightTiles.filter(
1104
+ (tile) => tile.type !== "empty"
1105
+ ).length;
1106
+ const topTiles = castlePosition !== void 0 ? kingdom[castlePosition].slice(0, castlePosition) : [];
1107
+ const topTilesCount = topTiles.filter((tile) => tile.type !== "empty").length;
1108
+ const bottomTiles = castlePosition != void 0 ? kingdom[castlePosition].slice(castlePosition + 1) : [];
1109
+ const bottomTilesCount = bottomTiles.filter(
1110
+ (tile) => tile.type !== "empty"
1111
+ ).length;
1112
+ return leftTilesCount === rightTilesCount && topTilesCount === bottomTilesCount && leftTilesCount === topTilesCount;
1113
+ };
1114
+ var countDominoes = (kingdom) => {
1115
+ const notEmpties = kingdom.flat().filter((tile) => tile.type !== "empty");
1116
+ const totalDominoes = (notEmpties.length - 1) / 2;
1117
+ return totalDominoes;
1118
+ };
1119
+ var deepCopyKingdom = (kingdom) => {
1120
+ return kingdom.map((line) => line.map((tile) => ({ ...tile })));
899
1121
  };
900
1122
 
901
- // src/hexagon/internal/services/pick.ts
902
- var pick = (payload) => {
903
- const { lordId, data } = payload;
904
- const { state, dominoPick } = data;
905
- const { currentDominoes, lords } = state;
906
- if (!isLordTurn(state, lordId)) {
907
- throw new Error("It is not your turn");
908
- }
909
- const lord = lords.find((lord2) => lord2.id === lordId);
910
- if (lord?.hasPick) {
911
- throw new Error("You have already picked");
912
- }
913
- const domino = checkValidityDomino(state, dominoPick);
914
- const isError = (domino2) => {
915
- return domino2.error !== void 0;
916
- };
917
- if (isError(domino)) {
918
- throw new Error(domino.error);
1123
+ // src/core/useCases/addPlayers.ts
1124
+ var addPlayersUseCase = (deps) => (game, players) => {
1125
+ const { uuidMethod: uuidMethod2, shuffleMethod: shuffleMethod2, ruleRepository } = deps;
1126
+ if (!players || players.length < 2 || players.length > 4) {
1127
+ return err("Invalid number of players");
919
1128
  }
920
- const updatedCurrentDominoes = currentDominoes.map((domino2) => {
921
- if (domino2.domino.number === dominoPick) {
922
- domino2.picked = true;
923
- domino2.lordId = lordId;
924
- }
925
- return domino2;
926
- });
927
- const updatedLords = lords.map((lord2) => {
928
- if (lord2.id === lordId) {
929
- lord2.hasPick = true;
930
- lord2.turnEnded = true;
931
- lord2.dominoPicked = domino.domino;
1129
+ const newPlayers = [];
1130
+ for (const player of players) {
1131
+ let kingdom = createEmptyKingdom();
1132
+ kingdom = placeCastle(kingdom);
1133
+ let id = uuidMethod2();
1134
+ const newPlayer = createPlayer(player, id, kingdom);
1135
+ if (isErr(newPlayer)) {
1136
+ return newPlayer;
932
1137
  }
933
- return lord2;
934
- });
935
- const updatedState = {
936
- ...state,
937
- currentDominoes: updatedCurrentDominoes,
938
- lords: updatedLords
939
- };
940
- return updatedState;
941
- };
942
-
943
- // src/hexagon/internal/services/place.ts
944
- var place = (payload) => {
945
- const { lordId, data } = payload;
946
- const { state, position, orientation, rotation } = data;
947
- const currentLord = state.lords.find((lord) => lord.id === lordId);
948
- const currentPlayer = state.players.find(
949
- (player) => player.id === currentLord?.playerId
950
- );
951
- const currentKingdom = currentPlayer?.kingdom;
952
- if (!currentKingdom) {
953
- throw new Error("Kingdom not found");
1138
+ newPlayers.push(newPlayer.value);
954
1139
  }
955
- const domino = currentLord?.dominoPicked;
956
- if (!domino) {
957
- throw new Error("Domino not found");
1140
+ const rules = ruleRepository.getAll();
1141
+ const basicRules = rules.basic[newPlayers.length];
1142
+ if (!basicRules) {
1143
+ return err("No base rules found");
958
1144
  }
959
- kingdom_default.placeDomino(currentKingdom, position, orientation, rotation, domino);
960
- currentPlayer.kingdom = currentKingdom;
961
- currentLord.hasPlace = true;
962
- const newState = {
963
- ...state,
964
- lords: state.lords.map((lord) => {
965
- if (lord.id === lordId) {
966
- return currentLord;
967
- }
968
- return lord;
969
- })
1145
+ const dominoes = game.dominoes;
1146
+ const { maxDominoes } = basicRules;
1147
+ const shuffledDominoes = shuffleMethod2(dominoes);
1148
+ const splicedDominoes = shuffledDominoes.slice(0, maxDominoes);
1149
+ const next = {
1150
+ type: "step",
1151
+ step: "options"
1152
+ };
1153
+ const updatedGame = {
1154
+ ...game,
1155
+ players: newPlayers,
1156
+ dominoes: splicedDominoes,
1157
+ rules: {
1158
+ ...game.rules,
1159
+ basic: basicRules
1160
+ },
1161
+ nextAction: next
970
1162
  };
971
- return newState;
1163
+ return ok(updatedGame);
972
1164
  };
973
1165
 
974
- // src/hexagon/internal/services/order.ts
975
- var definePlayerOrder = (payload) => {
976
- const { state } = payload;
977
- const { lords, currentDominoes } = state;
978
- const allLordsHavePlayed = lords.every((lord) => lord.turnEnded);
979
- if (!allLordsHavePlayed) {
980
- throw new Error("Not all lords have played");
981
- }
982
- const updatedLords = lords.map((lord) => {
983
- return {
984
- ...lord,
985
- order: currentDominoes.find((domino) => domino.lordId === lord.id)?.position || 0
986
- };
1166
+ // src/core/domain/entities/lord.ts
1167
+ var createLord = (id, playerId) => {
1168
+ return {
1169
+ id,
1170
+ playerId,
1171
+ turnEnded: false,
1172
+ hasPick: false,
1173
+ hasPlace: true
1174
+ };
1175
+ };
1176
+ var hasPick = (lord) => lord.hasPick;
1177
+ var hasPlace = (lord) => lord.hasPlace;
1178
+ var hasTurnEnded = (lord) => lord.turnEnded;
1179
+ var canPass = (lord) => {
1180
+ return !hasPick(lord) && !hasPlace(lord) && !hasTurnEnded(lord);
1181
+ };
1182
+ var canPick = (lord) => {
1183
+ return !hasPick(lord) && hasPlace(lord) && !hasTurnEnded(lord);
1184
+ };
1185
+ var canPlaceAndDominoPickedIsDefined = (lord) => {
1186
+ return !hasPick(lord) && !hasPlace(lord) && !hasTurnEnded(lord) && lord.dominoPicked !== void 0;
1187
+ };
1188
+ var updateLordOrder = (lords) => {
1189
+ return lords.sort((a2, b2) => {
1190
+ return a2.dominoPicked.number - b2.dominoPicked.number;
987
1191
  });
988
- const order = updatedLords.reduce((acc, lord) => {
989
- return {
990
- ...acc,
991
- [lord.order]: lord.id
992
- };
993
- }, {});
994
- const newState = {
995
- ...state,
996
- lords: updatedLords,
997
- order
1192
+ };
1193
+ var resetLordsActions = (lord) => {
1194
+ const lordsCopy = [...lord];
1195
+ for (const lord2 of lordsCopy) {
1196
+ lord2.turnEnded = false;
1197
+ lord2.hasPick = false;
1198
+ lord2.hasPlace = false;
1199
+ }
1200
+ return lordsCopy;
1201
+ };
1202
+ var nextLordWithAction = (lords) => {
1203
+ const nextLord = findNextLord(lords);
1204
+ return {
1205
+ type: "action",
1206
+ nextLord: nextLord.id,
1207
+ nextAction: hasPlace(nextLord) ? playerActions.pickDomino : playerActions.placeDomino
998
1208
  };
999
- return newState;
1209
+ };
1210
+ var findNextLord = (lords) => {
1211
+ const lord = lords.find((lord2) => !hasTurnEnded(lord2));
1212
+ if (!lord) {
1213
+ return lords[0];
1214
+ }
1215
+ return lord;
1216
+ };
1217
+ var allLordsHavePlayed = (lords) => {
1218
+ return lords.every((lord) => lord.turnEnded);
1000
1219
  };
1001
1220
 
1002
- // src/hexagon/internal/services/draw.ts
1003
- var draw = (payload) => {
1004
- const { state } = payload;
1005
- const dominoesCopy = [...state.dominoes];
1006
- const dominoesDrawn = dominoesCopy.splice(0, state.dominoesPerTurn);
1007
- dominoesDrawn.sort((a, b) => a.number - b.number);
1008
- const newState = {
1009
- ...state,
1010
- dominoes: dominoesCopy,
1011
- currentDominoes: dominoesDrawn.map((domino, index) => {
1221
+ // src/core/useCases/chooseDomino.ts
1222
+ var chooseDominoUseCase = (game, lordId, dominoPick) => {
1223
+ const currentLord = game.lords.find(
1224
+ (lord) => lord.id === game.nextAction.nextLord
1225
+ );
1226
+ if (!currentLord) {
1227
+ return err("Lord not found");
1228
+ }
1229
+ if (currentLord.id !== lordId) {
1230
+ return err("Not your turn");
1231
+ }
1232
+ if (!canPick(currentLord)) {
1233
+ return err("Lord can't pick");
1234
+ }
1235
+ const selectedDomino = game.currentDominoes.find(
1236
+ (domino) => domino.domino.number === dominoPick
1237
+ );
1238
+ if (!selectedDomino) {
1239
+ return err("Domino not found");
1240
+ }
1241
+ if (selectedDomino.picked) {
1242
+ return err("Domino already picked");
1243
+ }
1244
+ const updatedCurrentDominoes = game.currentDominoes.map((domino) => {
1245
+ if (domino.domino.number === dominoPick) {
1246
+ domino.picked = true;
1247
+ domino.lordId = currentLord.id;
1248
+ }
1249
+ return domino;
1250
+ });
1251
+ const updatedLords = game.lords.map((lord) => {
1252
+ if (lord.id === currentLord.id) {
1253
+ lord.hasPick = true;
1254
+ lord.turnEnded = true;
1255
+ lord.dominoPicked = selectedDomino.domino;
1256
+ }
1257
+ return lord;
1258
+ });
1259
+ const turnEnded = allLordsHavePlayed(updatedLords);
1260
+ if (turnEnded) {
1261
+ const lords = resetLordsActions(updateLordOrder(updatedLords));
1262
+ const updatedTurn = game.turn + 1;
1263
+ const next2 = nextLordWithAction(lords);
1264
+ const dominoesCopy = [...game.dominoes];
1265
+ const dominoesDrawn = dominoesCopy.splice(
1266
+ 0,
1267
+ game.rules.basic.dominoesPerTurn
1268
+ );
1269
+ dominoesDrawn.sort((a2, b2) => a2.number - b2.number);
1270
+ const updatedCurrentDominoes2 = dominoesDrawn.map((domino, index) => {
1012
1271
  return {
1013
1272
  domino,
1014
1273
  picked: false,
1015
1274
  lordId: null,
1016
1275
  position: index + 1
1017
1276
  };
1018
- })
1277
+ });
1278
+ return ok({
1279
+ ...game,
1280
+ currentDominoes: updatedCurrentDominoes2,
1281
+ dominoes: dominoesCopy,
1282
+ lords,
1283
+ turn: updatedTurn,
1284
+ nextAction: next2
1285
+ });
1286
+ }
1287
+ const next = nextLordWithAction(updatedLords);
1288
+ const updatedState = {
1289
+ ...game,
1290
+ currentDominoes: updatedCurrentDominoes,
1291
+ lords: updatedLords,
1292
+ nextAction: next
1019
1293
  };
1020
- return newState;
1294
+ return ok(updatedState);
1021
1295
  };
1022
1296
 
1023
- // src/hexagon/internal/services/scoring.ts
1024
- var calculateScore = (kingdom2) => {
1025
- const visited = kingdom2.map((row) => row.map(() => false));
1026
- const properties = [];
1027
- const directions = [
1028
- [-1, 0],
1029
- [1, 0],
1030
- [0, -1],
1031
- [0, 1]
1032
- ];
1033
- const markZone = (x, y, type, crowns) => {
1034
- if (x < 0 || y < 0 || x >= kingdom2[0].length || y >= kingdom2.length || visited[y][x] || kingdom2[y][x].type !== type || kingdom2[y][x].type === "empty" || kingdom2[y][x].type === "castle") {
1035
- return;
1036
- }
1037
- visited[y][x] = true;
1038
- const currentZone = properties.find(
1039
- (property) => property.type === type && property.tiles.some(([tx, ty]) => {
1040
- for (let [dx, dy] of directions) {
1041
- if (tx + dx === x && ty + dy === y) {
1042
- return true;
1043
- }
1044
- }
1045
- return false;
1046
- })
1047
- );
1048
- if (currentZone) {
1049
- currentZone.crowns += crowns;
1050
- currentZone.size++;
1051
- currentZone.tiles.push([x, y]);
1052
- } else {
1053
- properties.push({ type, crowns, size: 1, tiles: [[x, y]] });
1054
- }
1055
- directions.forEach(([dx, dy]) => {
1056
- const nx = x + dx;
1057
- const ny = y + dy;
1058
- if (nx >= 0 && ny >= 0 && nx < kingdom2[0].length && ny < kingdom2.length && kingdom2[ny][nx].type === type) {
1059
- markZone(nx, ny, kingdom2[ny][nx].type, kingdom2[ny][nx].crowns);
1060
- }
1061
- });
1297
+ // src/core/domain/entities/game.ts
1298
+ var create = (payload) => {
1299
+ const { id, mode, dominoes } = payload;
1300
+ return {
1301
+ id,
1302
+ dominoes,
1303
+ currentDominoes: [],
1304
+ players: [],
1305
+ lords: [],
1306
+ turn: 0,
1307
+ nextAction: {
1308
+ type: "step",
1309
+ step: gameSteps.addPlayers
1310
+ },
1311
+ rules: {
1312
+ basic: {
1313
+ lords: 0,
1314
+ maxDominoes: 0,
1315
+ dominoesPerTurn: 0,
1316
+ maxTurns: 0
1317
+ },
1318
+ extra: []
1319
+ },
1320
+ mode
1062
1321
  };
1063
- kingdom2.forEach((row, y) => {
1064
- row.forEach((tile, x) => {
1065
- if (!visited[y][x]) {
1066
- markZone(x, y, tile.type, tile.crowns);
1067
- }
1068
- });
1069
- });
1070
- if (properties.length === 0) {
1071
- return {
1072
- score: 0,
1073
- maxPropertiesSize: 0,
1074
- totalCrowns: 0
1075
- };
1322
+ };
1323
+
1324
+ // src/core/domain/entities/mode.ts
1325
+ var findMode = (mode, availableMode) => {
1326
+ return availableMode.find((m) => m.name === mode);
1327
+ };
1328
+ var createMode = (mode, availableMode) => {
1329
+ const foundMode = findMode(mode, availableMode);
1330
+ if (foundMode) {
1331
+ return ok(foundMode);
1076
1332
  }
1077
- const score = properties.reduce(
1078
- (score2, property) => score2 + property.crowns * property.size,
1079
- 0
1080
- );
1081
- const maxPropertiesSize = Math.max(
1082
- ...properties.map((property) => property.size ?? 0)
1083
- );
1084
- const totalCrowns = properties.reduce(
1085
- (total, property) => total + property.crowns,
1086
- 0
1087
- );
1088
- return {
1089
- score,
1090
- maxPropertiesSize,
1091
- totalCrowns
1333
+ return err(`Invalid mode: ${mode}`);
1334
+ };
1335
+
1336
+ // src/core/useCases/createGame.ts
1337
+ var createGameUseCase = (deps) => (mode) => {
1338
+ const { modeRepository, dominoesRepository, uuidMethod: uuidMethod2 } = deps;
1339
+ const id = uuidMethod2();
1340
+ const availableMode = modeRepository.getAvailables();
1341
+ const newMode = createMode(mode, availableMode);
1342
+ if (isErr(newMode)) {
1343
+ return newMode;
1344
+ }
1345
+ const dominoes = dominoesRepository.getForMode(newMode.value);
1346
+ if (!dominoes || dominoes.length === 0) {
1347
+ return err(`No dominoes found for mode ${newMode.value.name}`);
1348
+ }
1349
+ const payload = {
1350
+ id,
1351
+ mode: newMode.value,
1352
+ dominoes
1092
1353
  };
1354
+ const newGame = create(payload);
1355
+ return ok(newGame);
1093
1356
  };
1094
1357
 
1095
- // src/hexagon/internal/services/pass.ts
1096
- var pass = (payload) => {
1097
- const { lordId, data } = payload;
1098
- const { state } = data;
1099
- const currentLord = state.lords.find((lord) => lord.id === lordId);
1358
+ // src/core/useCases/discardDomino.ts
1359
+ var discardDominoUseCase = (game, lordId) => {
1360
+ const nextAction = game.nextAction;
1361
+ const currentLord = game.lords.find(
1362
+ (lord) => lord.id === nextAction.nextLord
1363
+ );
1100
1364
  if (!currentLord) {
1101
- throw new Error("Lord not found");
1365
+ return err("Lord not found");
1102
1366
  }
1103
- currentLord.hasPlace = true;
1104
- const newState = {
1105
- ...state,
1106
- lords: state.lords.map((lord) => {
1107
- if (lord.id === lordId) {
1108
- return currentLord;
1367
+ if (currentLord.id !== lordId) {
1368
+ return err("Not your turn");
1369
+ }
1370
+ if (!canPass(currentLord)) {
1371
+ return err("Lord can't pass");
1372
+ }
1373
+ const maxTurns = game.rules.basic.maxTurns;
1374
+ const currentTurn = game.turn;
1375
+ const isLastTurn = currentTurn === maxTurns;
1376
+ const updatedLord = game.lords.map((lord) => {
1377
+ if (lord.id === currentLord.id) {
1378
+ if (isLastTurn) {
1379
+ return {
1380
+ ...lord,
1381
+ turnEnded: true,
1382
+ hasPlace: true
1383
+ };
1109
1384
  }
1110
- return lord;
1111
- })
1385
+ return {
1386
+ ...lord,
1387
+ hasPlace: true
1388
+ };
1389
+ }
1390
+ return lord;
1391
+ });
1392
+ let updatedGame;
1393
+ const resultStep = {
1394
+ type: "step",
1395
+ step: gameSteps.result
1112
1396
  };
1113
- return newState;
1397
+ if (isLastTurn && allLordsHavePlayed(updatedLord)) {
1398
+ updatedGame = {
1399
+ ...game,
1400
+ lords: updatedLord,
1401
+ nextAction: resultStep
1402
+ };
1403
+ } else {
1404
+ updatedGame = {
1405
+ ...game,
1406
+ lords: updatedLord,
1407
+ nextAction: nextLordWithAction(updatedLord)
1408
+ };
1409
+ }
1410
+ return ok(updatedGame);
1114
1411
  };
1115
1412
 
1116
- // src/hexagon/internal/services/game.ts
1117
- var gameStep = (dependencies) => {
1118
- return {
1119
- init: init(dependencies),
1120
- setup: setup(dependencies),
1121
- startTurn,
1122
- pick,
1123
- place,
1124
- pass,
1125
- definePlayerOrder,
1126
- draw,
1127
- calculateScore
1128
- };
1129
- };
1130
- var isLordTurn = (state, lordId) => {
1131
- const { lords, currentDominoes } = state;
1132
- const currentLordOrder = lords.find((lord) => lord.id === lordId)?.order;
1133
- const pickedDominoes = currentDominoes.filter(
1134
- (currentDomino) => currentDomino.picked
1135
- );
1136
- if (currentLordOrder !== pickedDominoes.length + 1) {
1137
- return false;
1413
+ // src/core/useCases/getExtraRules.ts
1414
+ var getExtraRulesUseCase = (deps) => (mode, players) => {
1415
+ const { ruleRepository } = deps;
1416
+ const allExtraRules = ruleRepository.getAllExtra();
1417
+ if (!allExtraRules) {
1418
+ return err("No rules found");
1138
1419
  }
1139
- return true;
1420
+ return getAvailablesExtraRules(allExtraRules, mode, players);
1140
1421
  };
1141
- var checkValidityDomino = (state, dominoPick) => {
1142
- const { currentDominoes } = state;
1143
- const domino = currentDominoes.find(
1144
- (currentDomino) => currentDomino.domino.number === dominoPick
1145
- );
1146
- if (!domino) {
1147
- const error = {
1148
- error: "Domino not found"
1422
+
1423
+ // src/core/useCases/getModes.ts
1424
+ var getModesUseCase = (deps) => () => {
1425
+ const { modeRepository } = deps;
1426
+ return ok(modeRepository.getAvailables());
1427
+ };
1428
+
1429
+ // src/core/useCases/getResult.ts
1430
+ var getResultUseCase = (game) => {
1431
+ const { players, rules } = game;
1432
+ const { basic, extra } = rules;
1433
+ const scores = players.map((player) => {
1434
+ const { kingdom } = player;
1435
+ const visited = kingdom.map((row) => row.map(() => false));
1436
+ const properties = [];
1437
+ const directions = [
1438
+ [-1, 0],
1439
+ [1, 0],
1440
+ [0, -1],
1441
+ [0, 1]
1442
+ ];
1443
+ const markZone = (x, y, type, crowns) => {
1444
+ if (x < 0 || y < 0 || x >= kingdom[0].length || y >= kingdom.length || visited[y][x] || kingdom[y][x].type !== type || kingdom[y][x].type === "empty" || kingdom[y][x].type === "castle") {
1445
+ return;
1446
+ }
1447
+ visited[y][x] = true;
1448
+ const currentZone = properties.find(
1449
+ (property) => property.type === type && property.tiles.some(([tx, ty]) => {
1450
+ for (let [dx, dy] of directions) {
1451
+ if (tx + dx === x && ty + dy === y) {
1452
+ return true;
1453
+ }
1454
+ }
1455
+ return false;
1456
+ })
1457
+ );
1458
+ if (currentZone) {
1459
+ currentZone.size += 1;
1460
+ currentZone.tiles.push([x, y]);
1461
+ currentZone.crowns += crowns;
1462
+ } else {
1463
+ properties.push({
1464
+ type,
1465
+ crowns,
1466
+ size: 1,
1467
+ tiles: [[x, y]]
1468
+ });
1469
+ }
1470
+ directions.forEach(([dx, dy]) => {
1471
+ const nx = x + dx;
1472
+ const ny = y + dy;
1473
+ if (nx >= 0 && ny >= 0 && nx < kingdom[0].length && ny < kingdom.length && kingdom[ny][nx].type === type) {
1474
+ markZone(nx, ny, kingdom[ny][nx].type, kingdom[ny][nx].crowns);
1475
+ }
1476
+ });
1149
1477
  };
1150
- return error;
1151
- }
1152
- if (domino.picked) {
1153
- const error = {
1154
- error: "Domino already picked"
1478
+ kingdom.forEach((row, y) => {
1479
+ row.forEach((tile, x) => {
1480
+ if (!visited[y][x]) {
1481
+ markZone(x, y, tile.type, tile.crowns);
1482
+ }
1483
+ });
1484
+ });
1485
+ if (properties.length === 0) {
1486
+ return {
1487
+ playerId: player.id,
1488
+ playerName: player.name,
1489
+ details: {
1490
+ points: 0,
1491
+ maxPropertiesSize: 0,
1492
+ totalCrowns: 0
1493
+ }
1494
+ };
1495
+ }
1496
+ let points = properties.reduce(
1497
+ (score, property) => score + property.crowns * property.size,
1498
+ 0
1499
+ );
1500
+ const maxPropertiesSize = Math.max(
1501
+ ...properties.map((property) => property.size ?? 0)
1502
+ );
1503
+ const totalCrowns = properties.reduce(
1504
+ (total, property) => total + property.crowns,
1505
+ 0
1506
+ );
1507
+ if (extra.length > 0) {
1508
+ extra.forEach((extraRule) => {
1509
+ if (extraRule.name === "The middle Kingdom") {
1510
+ const castleIsInMiddle = checkCastleIsInMiddle(kingdom);
1511
+ if (castleIsInMiddle) {
1512
+ points += 10;
1513
+ }
1514
+ }
1515
+ if (extraRule.name === "Harmony") {
1516
+ const totalDominoes = countDominoes(kingdom);
1517
+ const dominoLimit = basic.maxDominoes;
1518
+ const totalPlayers = players.length;
1519
+ const dominoesPerPlayer = dominoLimit / totalPlayers;
1520
+ if (totalDominoes === dominoesPerPlayer) {
1521
+ points += 5;
1522
+ }
1523
+ }
1524
+ });
1525
+ }
1526
+ return {
1527
+ playerId: player.id,
1528
+ playerName: player.name,
1529
+ details: {
1530
+ points,
1531
+ maxPropertiesSize,
1532
+ totalCrowns
1533
+ }
1155
1534
  };
1156
- return error;
1157
- }
1158
- return domino;
1159
- };
1160
- var rules = {
1161
- 2: {
1162
- lords: 2,
1163
- maxDominoes: 24,
1164
- dominoesPerTurn: 4,
1165
- maxTurns: 6
1166
- },
1167
- 3: {
1168
- lords: 1,
1169
- maxDominoes: 36,
1170
- dominoesPerTurn: 3,
1171
- maxTurns: 12
1172
- },
1173
- 4: {
1174
- lords: 1,
1175
- maxDominoes: 48,
1176
- dominoesPerTurn: 4,
1177
- maxTurns: 12
1178
- }
1179
- };
1180
- var game_default = gameStep;
1181
-
1182
- // src/hexagon/internal/services/result.ts
1183
- var result = (scores) => {
1184
- scores.sort((a, b) => {
1185
- if (a.details.score !== b.details.score) {
1186
- return b.details.score - a.details.score;
1535
+ });
1536
+ scores.sort((a2, b2) => {
1537
+ if (a2.details.points !== b2.details.points) {
1538
+ return b2.details.points - a2.details.points;
1187
1539
  }
1188
- if (a.details.maxPropertiesSize !== b.details.maxPropertiesSize) {
1189
- return b.details.maxPropertiesSize - a.details.maxPropertiesSize;
1540
+ if (a2.details.maxPropertiesSize !== b2.details.maxPropertiesSize) {
1541
+ return b2.details.maxPropertiesSize - a2.details.maxPropertiesSize;
1190
1542
  }
1191
- return b.details.totalCrowns - a.details.totalCrowns;
1543
+ return b2.details.totalCrowns - a2.details.totalCrowns;
1192
1544
  });
1193
- const result2 = [];
1545
+ const result = [];
1194
1546
  let isTie = false;
1195
- result2.push({
1196
- ...scores[0],
1547
+ result.push({
1548
+ playerId: scores[0].playerId,
1549
+ playerName: scores[0].playerName,
1550
+ details: scores[0].details,
1197
1551
  position: 1
1198
1552
  });
1199
- for (let i = 1; i < scores.length; i++) {
1200
- const currentScore = scores[i];
1201
- const previousScore = scores[i - 1];
1202
- if (previousScore && currentScore && currentScore.details.score === previousScore.details.score && currentScore.details.maxPropertiesSize === previousScore.details.maxPropertiesSize && currentScore.details.totalCrowns === previousScore.details.totalCrowns) {
1553
+ for (let i2 = 1; i2 < scores.length; i2++) {
1554
+ const currentScore = scores[i2];
1555
+ const previousScore = scores[i2 - 1];
1556
+ if (previousScore && currentScore && currentScore.details.points === previousScore.details.points && currentScore.details.maxPropertiesSize === previousScore.details.maxPropertiesSize && currentScore.details.totalCrowns === previousScore.details.totalCrowns) {
1203
1557
  isTie = true;
1204
1558
  }
1205
1559
  if (isTie) {
1206
- result2.push({
1560
+ result.push({
1207
1561
  ...currentScore,
1208
- position: result2[i - 1].position
1562
+ position: result[i2 - 1].position
1209
1563
  });
1210
1564
  } else {
1211
- result2.push({
1565
+ result.push({
1212
1566
  ...currentScore,
1213
- position: i + 1
1567
+ position: i2 + 1
1214
1568
  });
1215
1569
  }
1216
1570
  isTie = false;
1217
1571
  }
1218
- return result2;
1219
- };
1220
-
1221
- // src/hexagon/internal/entities/mode.ts
1222
- var availableMode = ["Classic"];
1223
-
1224
- // src/adapters/driven/uuid.ts
1225
- import { randomUUID } from "crypto";
1226
- var uuidMethod = () => {
1227
- return randomUUID();
1572
+ return ok({
1573
+ ...game,
1574
+ result
1575
+ });
1228
1576
  };
1229
1577
 
1230
- // src/adapters/driven/shuffle.ts
1231
- var shuffleMethod = (array) => {
1232
- for (let i = array.length - 1; i > 0; i--) {
1233
- const j = Math.floor(Math.random() * (i + 1));
1234
- [array[i], array[j]] = [array[j], array[i]];
1578
+ // src/core/useCases/placeDomino.ts
1579
+ var placeDominoUseCase = (game, lordId, position, orientation, rotation) => {
1580
+ const nextAction = game.nextAction;
1581
+ const currentLord = game.lords.find(
1582
+ (lord) => lord.id === nextAction.nextLord
1583
+ );
1584
+ if (!currentLord) {
1585
+ return err("Lord not found");
1235
1586
  }
1236
- return array;
1237
- };
1238
-
1239
- // src/adapters/driver/index.ts
1240
- var gameEngine = () => {
1241
- let dependencies;
1242
- try {
1243
- loadEnvFile();
1244
- } catch (error) {
1245
- console.log("No .env file found. Using default configuration.");
1246
- }
1247
- if (process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") {
1248
- console.log("Game engine is running in development mode");
1249
- dependencies = {
1250
- dominoesRepository: inMemoryDominoes_default(),
1251
- uuidMethod: () => `uuid-${Math.random()}`,
1252
- shuffleMethod: (array) => array
1253
- };
1254
- } else {
1255
- console.log("Game engine is running in production mode");
1256
- dependencies = {
1257
- dominoesRepository: inMemoryDominoes_default(),
1258
- uuidMethod,
1259
- shuffleMethod
1260
- };
1587
+ if (currentLord.id !== lordId) {
1588
+ return err("Not your turn");
1261
1589
  }
1262
- const {
1263
- init: init2,
1264
- setup: setup2,
1265
- startTurn: startTurn2,
1266
- pick: pick2,
1267
- place: place2,
1268
- pass: pass2,
1269
- definePlayerOrder: definePlayerOrder2,
1270
- draw: draw2,
1271
- calculateScore: calculateScore2
1272
- } = game_default(dependencies);
1273
- const getMode = () => {
1274
- return availableMode;
1275
- };
1276
- const setMode = (mode, game) => {
1277
- return game;
1278
- };
1279
- const getRules = (mode) => {
1280
- return [];
1281
- };
1282
- const setRules = (rules2, game) => {
1283
- return game;
1284
- };
1285
- const start = (game, players) => {
1286
- const setupState = setup2({
1287
- state: game,
1288
- players
1289
- });
1290
- const drawState = draw2({ state: setupState });
1291
- return {
1292
- nextLord: drawState.lords[0].id,
1293
- nextAction: "pick",
1294
- game: drawState
1295
- };
1296
- };
1297
- const passTurn = (game, lordId) => {
1298
- const updatedGame = pass2({
1299
- lordId,
1300
- action: "pass",
1301
- data: {
1302
- state: game
1303
- }
1304
- });
1305
- const resp = defineNextAction(updatedGame, "pass", lordId);
1306
- return resp;
1307
- };
1308
- const placeDomino2 = (game, lordId, position, orientation, rotation) => {
1309
- const updatedGame = place2({
1310
- lordId,
1311
- action: "place",
1312
- data: {
1313
- state: game,
1314
- position,
1315
- orientation,
1316
- rotation
1317
- }
1318
- });
1319
- const resp = defineNextAction(updatedGame, "place", lordId);
1320
- return resp;
1321
- };
1322
- const pickDomino = (game, lordId, dominoPick) => {
1323
- const updatedGame = pick2({
1324
- lordId,
1325
- action: "pick",
1326
- data: {
1327
- state: game,
1328
- dominoPick
1329
- }
1330
- });
1331
- const resp = defineNextAction(updatedGame, "pick", lordId);
1332
- return resp;
1333
- };
1334
- const prepareNextTurn = (game) => {
1335
- const updatedOrder = definePlayerOrder2({ state: game });
1336
- const updateDraw = draw2({ state: updatedOrder });
1337
- const updateTurn = startTurn2({ state: updateDraw });
1338
- if (updateTurn.game.turn > updateTurn.game.maxTurns) {
1339
- throw new Error("Game is over");
1590
+ if (!canPlaceAndDominoPickedIsDefined(currentLord)) {
1591
+ return err("Lord can't place");
1592
+ }
1593
+ const domino = currentLord.dominoPicked;
1594
+ const currentPlayer = game.players.find(
1595
+ (player) => player.id === currentLord.playerId
1596
+ );
1597
+ if (!currentPlayer) {
1598
+ return err("Player not found");
1599
+ }
1600
+ const updatedKingdom = placeDomino(
1601
+ currentPlayer.kingdom,
1602
+ position,
1603
+ orientation,
1604
+ rotation,
1605
+ domino
1606
+ );
1607
+ if (isErr(updatedKingdom)) {
1608
+ return updatedKingdom;
1609
+ }
1610
+ const updatedPlayers = game.players.map((player) => {
1611
+ if (player.id === currentPlayer.id) {
1612
+ player.kingdom = updatedKingdom.value;
1340
1613
  }
1341
- return updateTurn.game;
1342
- };
1343
- const defineNextAction = (game, currentAction, currentLordId) => {
1344
- const { lords, turn } = game;
1345
- if (turn === 0) {
1346
- const nextLord2 = lords.find((lord) => !lord.hasPick);
1347
- if (!nextLord2) {
1348
- const newState = prepareNextTurn(game);
1614
+ return player;
1615
+ });
1616
+ const maxTurns = game.rules.basic.maxTurns;
1617
+ const currentTurn = game.turn;
1618
+ const isLastTurn = currentTurn === maxTurns;
1619
+ const updatedLords = game.lords.map((lord) => {
1620
+ if (lord.id === currentLord.id) {
1621
+ if (isLastTurn) {
1349
1622
  return {
1350
- nextLord: newState.lords[0].id,
1351
- nextAction: "place",
1352
- game: newState
1623
+ ...lord,
1624
+ turnEnded: true,
1625
+ hasPlace: true
1353
1626
  };
1354
1627
  }
1355
1628
  return {
1356
- nextLord: nextLord2.id,
1357
- nextAction: "pick",
1358
- game
1629
+ ...lord,
1630
+ hasPlace: true
1359
1631
  };
1360
1632
  }
1361
- if (currentAction === "place" || currentAction === "pass") {
1362
- if (game.turn === game.maxTurns) {
1363
- const nextLord2 = lords.find((lord) => !lord.hasPlace);
1364
- if (!nextLord2) {
1365
- return {
1366
- nextLord: "none",
1367
- nextAction: "end",
1368
- game
1369
- };
1370
- }
1371
- return {
1372
- nextLord: nextLord2.id,
1373
- nextAction: "place",
1374
- game
1375
- };
1376
- }
1377
- return {
1378
- nextLord: currentLordId,
1379
- nextAction: "pick",
1380
- game
1381
- };
1633
+ return lord;
1634
+ });
1635
+ let updatedGame;
1636
+ const resultStep = {
1637
+ type: "step",
1638
+ step: gameSteps.result
1639
+ };
1640
+ if (isLastTurn && allLordsHavePlayed(updatedLords)) {
1641
+ updatedGame = {
1642
+ ...game,
1643
+ lords: updatedLords,
1644
+ nextAction: resultStep
1645
+ };
1646
+ } else {
1647
+ updatedGame = {
1648
+ ...game,
1649
+ lords: updatedLords,
1650
+ nextAction: nextLordWithAction(updatedLords)
1651
+ };
1652
+ }
1653
+ return ok(updatedGame);
1654
+ };
1655
+
1656
+ // src/core/useCases/startGame.ts
1657
+ var startGameUseCase = (deps) => (game) => {
1658
+ const { uuidMethod: uuidMethod2, shuffleMethod: shuffleMethod2 } = deps;
1659
+ const {
1660
+ rules: {
1661
+ basic: { lords: maxLords, dominoesPerTurn }
1662
+ },
1663
+ players,
1664
+ dominoes
1665
+ } = game;
1666
+ const numberOfPlayers = players.length;
1667
+ const newLords = [];
1668
+ for (let i2 = 0; i2 < numberOfPlayers; i2++) {
1669
+ for (let j = 0; j < maxLords; j++) {
1670
+ const lord = createLord(uuidMethod2(), players[i2].id);
1671
+ newLords.push(lord);
1382
1672
  }
1383
- const allLordsHavePicked = lords.every((lord) => lord.hasPick);
1384
- if (allLordsHavePicked) {
1385
- const newState = prepareNextTurn(game);
1673
+ }
1674
+ const shuffledLords = shuffleMethod2(newLords);
1675
+ const dominoesCopy = [...dominoes];
1676
+ const dominoesDrawn = dominoesCopy.splice(0, dominoesPerTurn);
1677
+ dominoesDrawn.sort((a2, b2) => a2.number - b2.number);
1678
+ const nextAction = {
1679
+ type: "action",
1680
+ nextLord: shuffledLords[0].id,
1681
+ nextAction: playerActions.pickDomino
1682
+ };
1683
+ const newState = {
1684
+ ...game,
1685
+ lords: shuffledLords,
1686
+ nextAction,
1687
+ dominoes: dominoesCopy,
1688
+ currentDominoes: dominoesDrawn.map((domino, index) => {
1386
1689
  return {
1387
- nextLord: newState.order["1"],
1388
- nextAction: "place",
1389
- game: newState
1690
+ domino,
1691
+ picked: false,
1692
+ lordId: null,
1693
+ position: index + 1
1390
1694
  };
1391
- }
1392
- const nextLord = lords.find((lord) => !lord.hasPlace);
1393
- return {
1394
- nextLord: nextLord.id,
1395
- nextAction: "place",
1396
- game
1397
- };
1398
- };
1399
- const endGame = (game) => {
1400
- const players = game.players;
1401
- const scores = [];
1402
- for (let player of players) {
1403
- const score = calculateScore2(player.kingdom);
1404
- scores.push({
1405
- playerId: player.id,
1406
- playerName: player.name,
1407
- details: score
1408
- });
1409
- }
1410
- const finalResult = result(scores);
1411
- return {
1412
- result: finalResult,
1413
- game
1414
- };
1695
+ })
1415
1696
  };
1697
+ return ok(newState);
1698
+ };
1699
+
1700
+ // src/adapterServerside/shuffle.ts
1701
+ var shuffleMethod = (array) => {
1702
+ for (let i2 = array.length - 1; i2 > 0; i2--) {
1703
+ const j = Math.floor(Math.random() * (i2 + 1));
1704
+ [array[i2], array[j]] = [array[j], array[i2]];
1705
+ }
1706
+ return array;
1707
+ };
1708
+
1709
+ // src/adapterServerside/uuid.ts
1710
+ import { randomUUID } from "crypto";
1711
+ var uuidMethod = () => {
1712
+ return randomUUID();
1713
+ };
1714
+
1715
+ // src/config.ts
1716
+ var configureEngine = (config) => {
1717
+ const modeRepository = config.modeRepository || jsonModes_default();
1718
+ const dominoesRepository = config.dominoesRepository || jsonDominoes_default();
1719
+ const ruleRepository = config.ruleRepository || jsonRules_default();
1720
+ const uuid = config.uuidMethod || uuidMethod;
1721
+ const shuffle = config.shuffleMethod || shuffleMethod;
1416
1722
  return {
1417
- init: init2,
1418
- getMode,
1419
- setMode,
1420
- getRules,
1421
- setRules,
1422
- start,
1423
- pass: passTurn,
1424
- placeDomino: placeDomino2,
1425
- pickDomino,
1426
- endGame
1723
+ createGameHandler: createGameHandler(
1724
+ createGameUseCase({
1725
+ modeRepository,
1726
+ dominoesRepository,
1727
+ uuidMethod: uuid
1728
+ })
1729
+ ),
1730
+ getModesHandler: getModesHandler(getModesUseCase({ modeRepository })),
1731
+ getExtraRulesHandler: getExtraRulesHandler(
1732
+ getExtraRulesUseCase({ ruleRepository })
1733
+ ),
1734
+ addPlayersHandler: addPlayersHandler(
1735
+ addPlayersUseCase({
1736
+ uuidMethod: uuid,
1737
+ shuffleMethod: shuffle,
1738
+ ruleRepository
1739
+ })
1740
+ ),
1741
+ addExtraRulesHandler: addExtraRulesHandler(
1742
+ addExtraRulesUseCase({ ruleRepository })
1743
+ ),
1744
+ startGameHandler: startGameHandler(
1745
+ startGameUseCase({ uuidMethod: uuid, shuffleMethod: shuffle })
1746
+ ),
1747
+ chooseDominoHandler: chooseDominoHandler(chooseDominoUseCase),
1748
+ placeDominoHandler: placeDominoHandler(placeDominoUseCase),
1749
+ discardDominoHandler: discardDominoHandler(discardDominoUseCase),
1750
+ getResultHandler: getResultHandler(getResultUseCase)
1427
1751
  };
1428
1752
  };
1429
- var driver_default = gameEngine;
1430
1753
 
1431
1754
  // src/index.ts
1432
- var src_default = driver_default;
1755
+ var createGameEngine = (config) => {
1756
+ const {
1757
+ createGameHandler: createGameHandler2,
1758
+ getModesHandler: getModesHandler2,
1759
+ getExtraRulesHandler: getExtraRulesHandler2,
1760
+ addPlayersHandler: addPlayersHandler2,
1761
+ addExtraRulesHandler: addExtraRulesHandler2,
1762
+ startGameHandler: startGameHandler2,
1763
+ chooseDominoHandler: chooseDominoHandler2,
1764
+ placeDominoHandler: placeDominoHandler2,
1765
+ discardDominoHandler: discardDominoHandler2,
1766
+ getResultHandler: getResultHandler2
1767
+ } = configureEngine(config);
1768
+ return {
1769
+ getModes: (command) => getModesHandler2(command),
1770
+ getExtraRules: (command) => getExtraRulesHandler2(command),
1771
+ createGame: (command) => createGameHandler2(command),
1772
+ addPlayers: (command) => addPlayersHandler2(command),
1773
+ addExtraRules: (command) => addExtraRulesHandler2(command),
1774
+ startGame: (command) => startGameHandler2(command),
1775
+ chooseDomino: (command) => chooseDominoHandler2(command),
1776
+ placeDomino: (command) => placeDominoHandler2(command),
1777
+ discardDomino: (command) => discardDominoHandler2(command),
1778
+ getResults: (command) => getResultHandler2(command)
1779
+ };
1780
+ };
1781
+ var engine = createGameEngine({});
1782
+ var a = engine.createGame({ mode: "standard" });
1783
+ var b = engine.getModes({});
1784
+ var c = engine.getExtraRules({ mode: "standard", players: 2 });
1785
+ var d = engine.addPlayers({ game: a, players: ["player1"] });
1786
+ var e = engine.addExtraRules({ game: d, extraRules: ["rule1"] });
1787
+ var f = engine.startGame({ game: e });
1788
+ var g = engine.chooseDomino({
1789
+ game: f,
1790
+ lordId: "player1",
1791
+ dominoPick: 1
1792
+ });
1793
+ var h = engine.discardDomino({ game: g, lordId: "player1" });
1794
+ var i = engine.placeDomino({
1795
+ game: g,
1796
+ lordId: "player1",
1797
+ position: { x: 1, y: 1 },
1798
+ orientation: "horizontal",
1799
+ rotation: 0
1800
+ });
1801
+ if (isGameWithNextAction(i)) {
1802
+ const j = engine.chooseDomino({
1803
+ game: i,
1804
+ lordId: "player1",
1805
+ dominoPick: 1
1806
+ });
1807
+ }
1808
+ if (!isGameWithNextAction(i)) {
1809
+ const j = engine.getResults({ game: i });
1810
+ }
1433
1811
  export {
1434
- src_default as default
1812
+ createGameEngine
1435
1813
  };
1436
1814
  //# sourceMappingURL=index.js.map