@hellacardgames/speed 0.14.1 → 0.14.2
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/manager/index.cjs +1 -1
- package/dist/manager/index.mjs +1 -1
- package/dist/{manager-C8wqbmrE.mjs → manager-BNAk0ZFh.mjs} +273 -189
- package/dist/manager-BNAk0ZFh.mjs.map +1 -0
- package/dist/{manager-DdpdgNfz.cjs → manager-Sw5jTzl2.cjs} +272 -188
- package/dist/manager-Sw5jTzl2.cjs.map +1 -0
- package/dist/server/index.cjs +1 -1
- package/dist/server/index.mjs +1 -1
- package/package.json +1 -1
- package/dist/manager-C8wqbmrE.mjs.map +0 -1
- package/dist/manager-DdpdgNfz.cjs.map +0 -1
package/dist/manager/index.cjs
CHANGED
package/dist/manager/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as createManager } from "../manager-
|
|
1
|
+
import { t as createManager } from "../manager-BNAk0ZFh.mjs";
|
|
2
2
|
export { createManager };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createManagerFactory, getClientStateAndClearEventsFactory, getEventsAndClearAcknowledged, sendChat } from "@hellacardgames/lib";
|
|
1
|
+
import { addItemToCollection, createManagerFactory, emitEvent, emitEventToPlayer, getClientStateAndClearEventsFactory, getEventsAndClearAcknowledged, removeItemFromCollection, requirePlayer, sendChat, shuffle, takeLastItemFromCollection, updatePlayer } from "@hellacardgames/lib";
|
|
2
2
|
//#region src/game/constants.ts
|
|
3
3
|
const EXPIRY_EXTENSION_MS = 3e5;
|
|
4
4
|
const CAN_PLAY_AT_DELAY_MS = 3e3;
|
|
@@ -286,29 +286,13 @@ function createGame(userId, username) {
|
|
|
286
286
|
createdAt,
|
|
287
287
|
expiresAt: createdAt + EXPIRY_EXTENSION_MS,
|
|
288
288
|
chatMessages: [],
|
|
289
|
-
players: [player]
|
|
289
|
+
players: [player],
|
|
290
|
+
canPlayAt: 0
|
|
290
291
|
},
|
|
291
292
|
playerId: player.id
|
|
292
293
|
};
|
|
293
294
|
}
|
|
294
295
|
//#endregion
|
|
295
|
-
//#region src/game/lib/emitEvent.ts
|
|
296
|
-
function emitEvent(game, data) {
|
|
297
|
-
const event = {
|
|
298
|
-
...data,
|
|
299
|
-
id: crypto.randomUUID()
|
|
300
|
-
};
|
|
301
|
-
for (const p of game.players) p.events.push(event);
|
|
302
|
-
}
|
|
303
|
-
//#endregion
|
|
304
|
-
//#region src/game/lib/emitEventToPlayer.ts
|
|
305
|
-
function emitEventToPlayer(player, data) {
|
|
306
|
-
player.events.push({
|
|
307
|
-
...data,
|
|
308
|
-
id: crypto.randomUUID()
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
//#endregion
|
|
312
296
|
//#region src/game/actions/drawCard.ts
|
|
313
297
|
function drawCard(game, playerId) {
|
|
314
298
|
const player = game.players.find((p) => p.id === playerId);
|
|
@@ -332,18 +316,25 @@ function drawCard(game, playerId) {
|
|
|
332
316
|
success: false,
|
|
333
317
|
error: "drawPileEmpty"
|
|
334
318
|
};
|
|
335
|
-
game
|
|
336
|
-
|
|
319
|
+
game = {
|
|
320
|
+
...game,
|
|
321
|
+
expiresAt: Date.now() + EXPIRY_EXTENSION_MS
|
|
322
|
+
};
|
|
323
|
+
game = emitEvent(game, {
|
|
337
324
|
type: "expirationUpdated",
|
|
338
325
|
expiresAt: game.expiresAt
|
|
339
326
|
});
|
|
340
|
-
const card = player.drawPile
|
|
341
|
-
player.
|
|
342
|
-
|
|
327
|
+
const { collection: newDrawPile, item: card } = takeLastItemFromCollection(player.drawPile);
|
|
328
|
+
game = updatePlayer(game, player.id, (p) => ({
|
|
329
|
+
...p,
|
|
330
|
+
drawPile: newDrawPile,
|
|
331
|
+
hand: addItemToCollection(p.hand, card)
|
|
332
|
+
}));
|
|
333
|
+
game = emitEventToPlayer(game, player.id, {
|
|
343
334
|
type: "drewCard",
|
|
344
335
|
card
|
|
345
336
|
});
|
|
346
|
-
emitEvent(game, {
|
|
337
|
+
game = emitEvent(game, {
|
|
347
338
|
type: "playerDrewCard",
|
|
348
339
|
username: player.username
|
|
349
340
|
});
|
|
@@ -397,8 +388,11 @@ function joinGame(game, userId, username) {
|
|
|
397
388
|
centerPile: [],
|
|
398
389
|
hasNoPlayableCards: false
|
|
399
390
|
};
|
|
400
|
-
game
|
|
401
|
-
|
|
391
|
+
game = {
|
|
392
|
+
...game,
|
|
393
|
+
players: addItemToCollection(game.players, player)
|
|
394
|
+
};
|
|
395
|
+
game = emitEvent(game, {
|
|
402
396
|
type: "playerJoined",
|
|
403
397
|
username
|
|
404
398
|
});
|
|
@@ -409,34 +403,47 @@ function joinGame(game, userId, username) {
|
|
|
409
403
|
};
|
|
410
404
|
}
|
|
411
405
|
//#endregion
|
|
406
|
+
//#region src/game/lib/removePlayerFromGame.ts
|
|
407
|
+
function removePlayerFromGame(game, playerId) {
|
|
408
|
+
const { player } = requirePlayer(game, playerId);
|
|
409
|
+
game = {
|
|
410
|
+
...game,
|
|
411
|
+
players: removeItemFromCollection(game.players, player)
|
|
412
|
+
};
|
|
413
|
+
return game;
|
|
414
|
+
}
|
|
415
|
+
//#endregion
|
|
416
|
+
//#region src/game/lib/transitionGameToForfeited.ts
|
|
417
|
+
function transitionGameToForfeited(game) {
|
|
418
|
+
return {
|
|
419
|
+
...game,
|
|
420
|
+
status: "forfeited"
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
//#endregion
|
|
412
424
|
//#region src/game/actions/leaveGame.ts
|
|
413
425
|
function leaveGame(game, playerId) {
|
|
414
|
-
const
|
|
415
|
-
if (
|
|
426
|
+
const player = game.players.find((p) => p.id === playerId);
|
|
427
|
+
if (!player) return {
|
|
416
428
|
success: false,
|
|
417
429
|
error: "playerNotFound"
|
|
418
430
|
};
|
|
419
|
-
|
|
420
|
-
emitEvent(game, {
|
|
431
|
+
game = emitEvent(game, {
|
|
421
432
|
type: "playerLeft",
|
|
422
433
|
username: player.username
|
|
423
434
|
});
|
|
424
|
-
game
|
|
435
|
+
game = removePlayerFromGame(game, player.id);
|
|
425
436
|
if (game.status === "started" && game.players.length < 2) {
|
|
426
|
-
|
|
437
|
+
game = transitionGameToForfeited(game);
|
|
438
|
+
game = {
|
|
427
439
|
...game,
|
|
428
|
-
status: "forfeited",
|
|
429
440
|
expiresAt: Date.now() + EXPIRY_EXTENSION_MS
|
|
430
441
|
};
|
|
431
|
-
emitEvent(
|
|
432
|
-
emitEvent(
|
|
442
|
+
game = emitEvent(game, { type: "gameForfeited" });
|
|
443
|
+
game = emitEvent(game, {
|
|
433
444
|
type: "expirationUpdated",
|
|
434
|
-
expiresAt:
|
|
445
|
+
expiresAt: game.expiresAt
|
|
435
446
|
});
|
|
436
|
-
return {
|
|
437
|
-
success: true,
|
|
438
|
-
game: forfeitedGame
|
|
439
|
-
};
|
|
440
447
|
}
|
|
441
448
|
return {
|
|
442
449
|
success: true,
|
|
@@ -450,15 +457,47 @@ function isCardPlayable(card, targetPile) {
|
|
|
450
457
|
return Math.abs(card.rank - targetCard.rank) % 11 === 1;
|
|
451
458
|
}
|
|
452
459
|
//#endregion
|
|
460
|
+
//#region src/game/lib/requireOtherPlayer.ts
|
|
461
|
+
function requireOtherPlayer(game, playerId) {
|
|
462
|
+
const otherPlayer = game.players.find((p) => p.id !== playerId);
|
|
463
|
+
if (!otherPlayer) throw new Error("Other player not found.");
|
|
464
|
+
return otherPlayer;
|
|
465
|
+
}
|
|
466
|
+
//#endregion
|
|
453
467
|
//#region src/game/lib/hasPlayableCard.ts
|
|
454
|
-
function hasPlayableCard(
|
|
455
|
-
const
|
|
468
|
+
function hasPlayableCard(game, playerId) {
|
|
469
|
+
const { player } = requirePlayer(game, playerId);
|
|
470
|
+
const otherPlayer = requireOtherPlayer(game, player.id);
|
|
456
471
|
const targetPile1 = player.centerPile;
|
|
457
472
|
const targetPile2 = otherPlayer.centerPile;
|
|
458
473
|
for (const card of player.hand) if (isCardPlayable(card, targetPile1) || isCardPlayable(card, targetPile2)) return true;
|
|
459
474
|
return false;
|
|
460
475
|
}
|
|
461
476
|
//#endregion
|
|
477
|
+
//#region src/game/lib/clearHasNoPlayableCardsIfNotApplicable.ts
|
|
478
|
+
function clearHasNoPlayableCardsIfNotApplicable(game, playerId) {
|
|
479
|
+
const { player } = requirePlayer(game, playerId);
|
|
480
|
+
if (player.hasNoPlayableCards && hasPlayableCard(game, player.id)) game = updatePlayer(game, player.id, (p) => ({
|
|
481
|
+
...p,
|
|
482
|
+
hasNoPlayableCards: false
|
|
483
|
+
}));
|
|
484
|
+
return game;
|
|
485
|
+
}
|
|
486
|
+
//#endregion
|
|
487
|
+
//#region src/game/lib/isOutOfCards.ts
|
|
488
|
+
function isOutOfCards(game, playerId) {
|
|
489
|
+
const { player } = requirePlayer(game, playerId);
|
|
490
|
+
return player.hand.length === 0 && player.drawPile.length === 0;
|
|
491
|
+
}
|
|
492
|
+
//#endregion
|
|
493
|
+
//#region src/game/lib/transitionGameToCompleted.ts
|
|
494
|
+
function transitionGameToCompleted(game) {
|
|
495
|
+
return {
|
|
496
|
+
...game,
|
|
497
|
+
status: "completed"
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
//#endregion
|
|
462
501
|
//#region src/game/actions/playCard.ts
|
|
463
502
|
function playCard(game, playerId, cardId, isForOtherPlayerPile) {
|
|
464
503
|
const player = game.players.find((p) => p.id === playerId);
|
|
@@ -474,41 +513,43 @@ function playCard(game, playerId, cardId, isForOtherPlayerPile) {
|
|
|
474
513
|
success: false,
|
|
475
514
|
error: "canPlayAtNotReached"
|
|
476
515
|
};
|
|
477
|
-
const
|
|
478
|
-
if (
|
|
516
|
+
const card = player.hand.find((c) => c.id === cardId);
|
|
517
|
+
if (!card) return {
|
|
479
518
|
success: false,
|
|
480
519
|
error: "cardNotFound"
|
|
481
520
|
};
|
|
482
|
-
const otherPlayer = game
|
|
483
|
-
const
|
|
484
|
-
|
|
485
|
-
if (!isCardPlayable(card, targetPile)) return {
|
|
521
|
+
const otherPlayer = requireOtherPlayer(game, player.id);
|
|
522
|
+
const targetPlayer = isForOtherPlayerPile ? otherPlayer : player;
|
|
523
|
+
if (!isCardPlayable(card, targetPlayer.centerPile)) return {
|
|
486
524
|
success: false,
|
|
487
525
|
error: "cardNotPlayable"
|
|
488
526
|
};
|
|
489
|
-
game
|
|
490
|
-
|
|
527
|
+
game = {
|
|
528
|
+
...game,
|
|
529
|
+
expiresAt: Date.now() + EXPIRY_EXTENSION_MS
|
|
530
|
+
};
|
|
531
|
+
game = emitEvent(game, {
|
|
491
532
|
type: "expirationUpdated",
|
|
492
533
|
expiresAt: game.expiresAt
|
|
493
534
|
});
|
|
494
|
-
player.
|
|
495
|
-
|
|
496
|
-
|
|
535
|
+
game = updatePlayer(game, player.id, (p) => ({
|
|
536
|
+
...p,
|
|
537
|
+
hand: removeItemFromCollection(p.hand, card)
|
|
538
|
+
}));
|
|
539
|
+
game = updatePlayer(game, targetPlayer.id, (p) => ({
|
|
540
|
+
...p,
|
|
541
|
+
centerPile: addItemToCollection(p.centerPile, card)
|
|
542
|
+
}));
|
|
543
|
+
game = emitEvent(game, {
|
|
497
544
|
type: "cardPlayed",
|
|
498
545
|
username: player.username,
|
|
499
546
|
card,
|
|
500
547
|
isForOtherPlayerPile
|
|
501
548
|
});
|
|
502
|
-
|
|
503
|
-
if (
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
success: true,
|
|
507
|
-
game: {
|
|
508
|
-
...game,
|
|
509
|
-
status: "completed"
|
|
510
|
-
}
|
|
511
|
-
};
|
|
549
|
+
game = clearHasNoPlayableCardsIfNotApplicable(game, otherPlayer.id);
|
|
550
|
+
if (isOutOfCards(game, player.id)) {
|
|
551
|
+
game = transitionGameToCompleted(game);
|
|
552
|
+
game = emitEvent(game, { type: "gameCompleted" });
|
|
512
553
|
}
|
|
513
554
|
return {
|
|
514
555
|
success: true,
|
|
@@ -516,12 +557,63 @@ function playCard(game, playerId, cardId, isForOtherPlayerPile) {
|
|
|
516
557
|
};
|
|
517
558
|
}
|
|
518
559
|
//#endregion
|
|
519
|
-
//#region src/game/lib/
|
|
520
|
-
function
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
560
|
+
//#region src/game/lib/drawCardFromSidePileToCenterPile.ts
|
|
561
|
+
function drawCardFromSidePileToCenterPile(game, playerId) {
|
|
562
|
+
const { player } = requirePlayer(game, playerId);
|
|
563
|
+
const { collection: newSidePile, item: card } = takeLastItemFromCollection(player.sidePile);
|
|
564
|
+
game = updatePlayer(game, player.id, (p) => ({
|
|
565
|
+
...p,
|
|
566
|
+
sidePile: newSidePile,
|
|
567
|
+
centerPile: addItemToCollection(p.centerPile, card)
|
|
568
|
+
}));
|
|
569
|
+
game = emitEvent(game, {
|
|
570
|
+
type: "cardDrawnFromSidePileToCenterPile",
|
|
571
|
+
username: player.username,
|
|
572
|
+
card
|
|
573
|
+
});
|
|
574
|
+
return game;
|
|
575
|
+
}
|
|
576
|
+
//#endregion
|
|
577
|
+
//#region src/game/lib/initializeCenterPile.ts
|
|
578
|
+
function initializeCenterPile(game, playerId, cards) {
|
|
579
|
+
const { player } = requirePlayer(game, playerId);
|
|
580
|
+
const card = cards[0];
|
|
581
|
+
if (!card) throw new Error("Not enough cards.");
|
|
582
|
+
cards = cards.slice(1);
|
|
583
|
+
game = updatePlayer(game, player.id, (p) => ({
|
|
584
|
+
...p,
|
|
585
|
+
centerPile: [card]
|
|
586
|
+
}));
|
|
587
|
+
game = emitEvent(game, {
|
|
588
|
+
type: "playerCenterPileInitialized",
|
|
589
|
+
username: player.username,
|
|
590
|
+
card
|
|
591
|
+
});
|
|
592
|
+
return {
|
|
593
|
+
game,
|
|
594
|
+
cards
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
//#endregion
|
|
598
|
+
//#region src/game/lib/initializeSidePile.ts
|
|
599
|
+
function initializeSidePile(game, playerId, cards) {
|
|
600
|
+
if (cards.length < 5) throw new Error("Not enough cards.");
|
|
601
|
+
const { player } = requirePlayer(game, playerId);
|
|
602
|
+
const sidePile = cards.slice(0, 5);
|
|
603
|
+
cards = cards.slice(5);
|
|
604
|
+
game = updatePlayer(game, player.id, (p) => ({
|
|
605
|
+
...p,
|
|
606
|
+
sidePile
|
|
607
|
+
}));
|
|
608
|
+
game = emitEvent(game, {
|
|
609
|
+
type: "playerSidePileInitialized",
|
|
610
|
+
username: player.username,
|
|
611
|
+
numCards: sidePile.length
|
|
612
|
+
});
|
|
613
|
+
return {
|
|
614
|
+
game,
|
|
615
|
+
cards
|
|
616
|
+
};
|
|
525
617
|
}
|
|
526
618
|
//#endregion
|
|
527
619
|
//#region src/game/actions/reportNoPlayableCards.ts
|
|
@@ -543,7 +635,7 @@ function reportNoPlayableCards(game, playerId) {
|
|
|
543
635
|
success: false,
|
|
544
636
|
error: "alreadyReported"
|
|
545
637
|
};
|
|
546
|
-
if (hasPlayableCard(
|
|
638
|
+
if (hasPlayableCard(game, player.id)) return {
|
|
547
639
|
success: false,
|
|
548
640
|
error: "hasPlayableCard"
|
|
549
641
|
};
|
|
@@ -551,61 +643,44 @@ function reportNoPlayableCards(game, playerId) {
|
|
|
551
643
|
success: false,
|
|
552
644
|
error: "canDraw"
|
|
553
645
|
};
|
|
554
|
-
game
|
|
555
|
-
|
|
646
|
+
game = {
|
|
647
|
+
...game,
|
|
648
|
+
expiresAt: Date.now() + EXPIRY_EXTENSION_MS
|
|
649
|
+
};
|
|
650
|
+
game = emitEvent(game, {
|
|
556
651
|
type: "expirationUpdated",
|
|
557
652
|
expiresAt: game.expiresAt
|
|
558
653
|
});
|
|
559
|
-
player.
|
|
560
|
-
|
|
654
|
+
game = updatePlayer(game, player.id, (p) => ({
|
|
655
|
+
...p,
|
|
656
|
+
hasNoPlayableCards: true
|
|
657
|
+
}));
|
|
658
|
+
const otherPlayer = requireOtherPlayer(game, player.id);
|
|
561
659
|
if (otherPlayer.hasNoPlayableCards) {
|
|
562
660
|
if (player.sidePile.length === 0 && otherPlayer.sidePile.length === 0) {
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
numCards: player.sidePile.length
|
|
570
|
-
});
|
|
571
|
-
player.centerPile.push(...cards.splice(0, 1));
|
|
572
|
-
emitEvent(game, {
|
|
573
|
-
type: "playerCenterPileInitialized",
|
|
574
|
-
username: player.username,
|
|
575
|
-
card: player.centerPile[player.centerPile.length - 1]
|
|
576
|
-
});
|
|
577
|
-
otherPlayer.centerPile.push(...cards.splice(0, 1));
|
|
578
|
-
emitEvent(game, {
|
|
579
|
-
type: "playerCenterPileInitialized",
|
|
580
|
-
username: otherPlayer.username,
|
|
581
|
-
card: otherPlayer.centerPile[otherPlayer.centerPile.length - 1]
|
|
582
|
-
});
|
|
583
|
-
otherPlayer.sidePile.push(...cards.splice(0, 5));
|
|
584
|
-
emitEvent(game, {
|
|
585
|
-
type: "playerSidePileInitialized",
|
|
586
|
-
username: otherPlayer.username,
|
|
587
|
-
numCards: otherPlayer.sidePile.length
|
|
588
|
-
});
|
|
661
|
+
let cards = [...player.centerPile, ...otherPlayer.centerPile];
|
|
662
|
+
cards = shuffle(cards);
|
|
663
|
+
({game, cards} = initializeSidePile(game, player.id, cards));
|
|
664
|
+
({game, cards} = initializeCenterPile(game, player.id, cards));
|
|
665
|
+
({game, cards} = initializeCenterPile(game, otherPlayer.id, cards));
|
|
666
|
+
({game} = initializeSidePile(game, otherPlayer.id, cards));
|
|
589
667
|
} else {
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
emitEvent(game, {
|
|
593
|
-
type: "cardDrawnFromSidePileToCenterPile",
|
|
594
|
-
username: player.username,
|
|
595
|
-
card: playerSidePileCard
|
|
596
|
-
});
|
|
597
|
-
const otherPlayerSidePileCard = otherPlayer.sidePile.pop();
|
|
598
|
-
otherPlayer.centerPile.push(otherPlayerSidePileCard);
|
|
599
|
-
emitEvent(game, {
|
|
600
|
-
type: "cardDrawnFromSidePileToCenterPile",
|
|
601
|
-
username: otherPlayer.username,
|
|
602
|
-
card: otherPlayerSidePileCard
|
|
603
|
-
});
|
|
668
|
+
game = drawCardFromSidePileToCenterPile(game, player.id);
|
|
669
|
+
game = drawCardFromSidePileToCenterPile(game, otherPlayer.id);
|
|
604
670
|
}
|
|
605
|
-
player.
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
671
|
+
game = updatePlayer(game, player.id, (p) => ({
|
|
672
|
+
...p,
|
|
673
|
+
hasNoPlayableCards: false
|
|
674
|
+
}));
|
|
675
|
+
game = updatePlayer(game, otherPlayer.id, (p) => ({
|
|
676
|
+
...p,
|
|
677
|
+
hasNoPlayableCards: false
|
|
678
|
+
}));
|
|
679
|
+
game = {
|
|
680
|
+
...game,
|
|
681
|
+
canPlayAt: Date.now() + CAN_PLAY_AT_DELAY_MS
|
|
682
|
+
};
|
|
683
|
+
game = emitEvent(game, {
|
|
609
684
|
type: "canPlayAtUpdated",
|
|
610
685
|
canPlayAt: game.canPlayAt
|
|
611
686
|
});
|
|
@@ -616,6 +691,60 @@ function reportNoPlayableCards(game, playerId) {
|
|
|
616
691
|
};
|
|
617
692
|
}
|
|
618
693
|
//#endregion
|
|
694
|
+
//#region src/game/lib/initializeDrawPile.ts
|
|
695
|
+
function initializeDrawPile(game, playerId, cards) {
|
|
696
|
+
if (cards.length < 15) throw new Error("Not enough cards.");
|
|
697
|
+
const { player } = requirePlayer(game, playerId);
|
|
698
|
+
const drawPile = cards.slice(0, 15);
|
|
699
|
+
cards = cards.slice(15);
|
|
700
|
+
game = updatePlayer(game, player.id, (p) => ({
|
|
701
|
+
...p,
|
|
702
|
+
drawPile
|
|
703
|
+
}));
|
|
704
|
+
game = emitEvent(game, {
|
|
705
|
+
type: "playerDrawPileInitialized",
|
|
706
|
+
username: player.username,
|
|
707
|
+
numCards: drawPile.length
|
|
708
|
+
});
|
|
709
|
+
return {
|
|
710
|
+
game,
|
|
711
|
+
cards
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
//#endregion
|
|
715
|
+
//#region src/game/lib/initializeHand.ts
|
|
716
|
+
function initializeHand(game, playerId, cards) {
|
|
717
|
+
if (cards.length < 5) throw new Error("Not enough cards.");
|
|
718
|
+
const { player } = requirePlayer(game, playerId);
|
|
719
|
+
const hand = cards.slice(0, 5);
|
|
720
|
+
cards = cards.slice(5);
|
|
721
|
+
game = updatePlayer(game, player.id, (p) => ({
|
|
722
|
+
...p,
|
|
723
|
+
hand
|
|
724
|
+
}));
|
|
725
|
+
game = emitEventToPlayer(game, player.id, {
|
|
726
|
+
type: "handInitialized",
|
|
727
|
+
cards: hand
|
|
728
|
+
});
|
|
729
|
+
game = emitEvent(game, {
|
|
730
|
+
type: "playerHandInitialized",
|
|
731
|
+
username: player.username,
|
|
732
|
+
numCards: hand.length
|
|
733
|
+
});
|
|
734
|
+
return {
|
|
735
|
+
game,
|
|
736
|
+
cards
|
|
737
|
+
};
|
|
738
|
+
}
|
|
739
|
+
//#endregion
|
|
740
|
+
//#region src/game/lib/transitionGameToStarted.ts
|
|
741
|
+
function transitionGameToStarted(game) {
|
|
742
|
+
return {
|
|
743
|
+
...game,
|
|
744
|
+
status: "started"
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
//#endregion
|
|
619
748
|
//#region src/game/actions/startGame.ts
|
|
620
749
|
function startGame(game, playerId) {
|
|
621
750
|
const player = game.players.find((p) => p.id === playerId);
|
|
@@ -635,83 +764,38 @@ function startGame(game, playerId) {
|
|
|
635
764
|
success: false,
|
|
636
765
|
error: "minPlayersNotReached"
|
|
637
766
|
};
|
|
638
|
-
|
|
639
|
-
const
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
});
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
card: player.centerPile[player.centerPile.length - 1]
|
|
652
|
-
});
|
|
653
|
-
otherPlayer.centerPile.push(...cards.splice(0, 1));
|
|
654
|
-
emitEvent(game, {
|
|
655
|
-
type: "playerCenterPileInitialized",
|
|
656
|
-
username: otherPlayer.username,
|
|
657
|
-
card: otherPlayer.centerPile[otherPlayer.centerPile.length - 1]
|
|
658
|
-
});
|
|
659
|
-
otherPlayer.sidePile.push(...cards.splice(0, 5));
|
|
660
|
-
emitEvent(game, {
|
|
661
|
-
type: "playerSidePileInitialized",
|
|
662
|
-
username: otherPlayer.username,
|
|
663
|
-
numCards: otherPlayer.sidePile.length
|
|
664
|
-
});
|
|
665
|
-
player.drawPile.push(...cards.splice(0, 15));
|
|
666
|
-
emitEvent(game, {
|
|
667
|
-
type: "playerDrawPileInitialized",
|
|
668
|
-
username: player.username,
|
|
669
|
-
numCards: player.drawPile.length
|
|
670
|
-
});
|
|
671
|
-
player.hand.push(...cards.splice(0, 5));
|
|
672
|
-
emitEventToPlayer(player, {
|
|
673
|
-
type: "handInitialized",
|
|
674
|
-
cards: player.hand
|
|
675
|
-
});
|
|
676
|
-
emitEvent(game, {
|
|
677
|
-
type: "playerHandInitialized",
|
|
678
|
-
username: player.username,
|
|
679
|
-
numCards: player.hand.length
|
|
680
|
-
});
|
|
681
|
-
otherPlayer.drawPile.push(...cards.splice(0, 15));
|
|
682
|
-
emitEvent(game, {
|
|
683
|
-
type: "playerDrawPileInitialized",
|
|
684
|
-
username: otherPlayer.username,
|
|
685
|
-
numCards: otherPlayer.drawPile.length
|
|
686
|
-
});
|
|
687
|
-
otherPlayer.hand.push(...cards.splice(0, 5));
|
|
688
|
-
emitEventToPlayer(otherPlayer, {
|
|
689
|
-
type: "handInitialized",
|
|
690
|
-
cards: otherPlayer.hand
|
|
691
|
-
});
|
|
692
|
-
emitEvent(game, {
|
|
693
|
-
type: "playerHandInitialized",
|
|
694
|
-
username: otherPlayer.username,
|
|
695
|
-
numCards: otherPlayer.hand.length
|
|
696
|
-
});
|
|
697
|
-
const startedGame = {
|
|
767
|
+
game = transitionGameToStarted(game);
|
|
768
|
+
const otherPlayer = requireOtherPlayer(game, player.id);
|
|
769
|
+
let cards = [...CARDS];
|
|
770
|
+
cards = shuffle(cards);
|
|
771
|
+
({game, cards} = initializeSidePile(game, player.id, cards));
|
|
772
|
+
({game, cards} = initializeCenterPile(game, player.id, cards));
|
|
773
|
+
({game, cards} = initializeCenterPile(game, otherPlayer.id, cards));
|
|
774
|
+
({game, cards} = initializeSidePile(game, otherPlayer.id, cards));
|
|
775
|
+
({game, cards} = initializeDrawPile(game, player.id, cards));
|
|
776
|
+
({game, cards} = initializeHand(game, player.id, cards));
|
|
777
|
+
({game, cards} = initializeDrawPile(game, otherPlayer.id, cards));
|
|
778
|
+
({game} = initializeHand(game, otherPlayer.id, cards));
|
|
779
|
+
game = {
|
|
698
780
|
...game,
|
|
699
|
-
|
|
700
|
-
expiresAt: Date.now() + EXPIRY_EXTENSION_MS,
|
|
701
|
-
canPlayAt: Date.now() + CAN_PLAY_AT_DELAY_MS
|
|
781
|
+
expiresAt: Date.now() + EXPIRY_EXTENSION_MS
|
|
702
782
|
};
|
|
703
|
-
emitEvent(
|
|
704
|
-
emitEvent(startedGame, {
|
|
783
|
+
game = emitEvent(game, {
|
|
705
784
|
type: "expirationUpdated",
|
|
706
|
-
expiresAt:
|
|
785
|
+
expiresAt: game.expiresAt
|
|
707
786
|
});
|
|
708
|
-
|
|
787
|
+
game = {
|
|
788
|
+
...game,
|
|
789
|
+
canPlayAt: Date.now() + CAN_PLAY_AT_DELAY_MS
|
|
790
|
+
};
|
|
791
|
+
game = emitEvent(game, {
|
|
709
792
|
type: "canPlayAtUpdated",
|
|
710
|
-
canPlayAt:
|
|
793
|
+
canPlayAt: game.canPlayAt
|
|
711
794
|
});
|
|
795
|
+
game = emitEvent(game, { type: "gameStarted" });
|
|
712
796
|
return {
|
|
713
797
|
success: true,
|
|
714
|
-
game
|
|
798
|
+
game
|
|
715
799
|
};
|
|
716
800
|
}
|
|
717
801
|
//#endregion
|
|
@@ -734,4 +818,4 @@ const createManager = createManagerFactory({
|
|
|
734
818
|
//#endregion
|
|
735
819
|
export { createManager as t };
|
|
736
820
|
|
|
737
|
-
//# sourceMappingURL=manager-
|
|
821
|
+
//# sourceMappingURL=manager-BNAk0ZFh.mjs.map
|