@masonf539/egyptian-war 1.0.1-beta.1 → 1.0.1-beta.3
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/README.md +4 -4
- package/dist/definition.js +1 -1
- package/dist/engine.d.ts +3 -3
- package/dist/engine.js +4 -3
- package/docs/design.md +2 -2
- package/package.json +1 -1
- package/public/client.js +10 -5
- package/public/style.css +14 -13
package/README.md
CHANGED
|
@@ -52,10 +52,10 @@ Slap patterns are validated by the server and configured in the lobby. The
|
|
|
52
52
|
descending rank sequence, including Ace-low and Ace-high sequences. The
|
|
53
53
|
"Tens" pattern checks only two directly adjacent number cards that total ten;
|
|
54
54
|
an Ace counts as one. An active player who false-slaps forfeits the configured
|
|
55
|
-
number of cards, up to the number they hold.
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
be slapped and the eliminated player to re-enter immediately.
|
|
55
|
+
number of cards, up to the number they hold. A false slap by an eliminated
|
|
56
|
+
player, or one that forfeits a player's last card, prevents another slap on the
|
|
57
|
+
unchanged pile. The cooldown clears when the next card is played, allowing that
|
|
58
|
+
new card to be slapped and the eliminated player to re-enter immediately.
|
|
59
59
|
Invalid reentry attempts use the same visible one-hand slap animation as other
|
|
60
60
|
false slaps; additional attempts during the cooldown do not create extra hands.
|
|
61
61
|
|
package/dist/definition.js
CHANGED
|
@@ -124,7 +124,7 @@ exports.egyptianWar = {
|
|
|
124
124
|
};
|
|
125
125
|
exports.egyptianWarManifest = {
|
|
126
126
|
apiVersion: game_sdk_1.gameHubGameApiVersion,
|
|
127
|
-
packageVersion: "1.0.1-beta.
|
|
127
|
+
packageVersion: "1.0.1-beta.3",
|
|
128
128
|
definition: exports.egyptianWar,
|
|
129
129
|
client: {
|
|
130
130
|
delivery: "embedded",
|
package/dist/engine.d.ts
CHANGED
|
@@ -82,11 +82,11 @@ export declare function removeEgyptianWarPlayer(state: EgyptianWarState, playerI
|
|
|
82
82
|
export declare function isEgyptianWarPileSlappable(pile: readonly Card[], settings: EgyptianWarSettings): boolean;
|
|
83
83
|
export declare function isEgyptianWarStateSlappable(state: Pick<EgyptianWarState, "pile" | "penaltyPileCardCount" | "settings">): boolean;
|
|
84
84
|
export type EgyptianWarSlapCooldownStatus = "none" | "waiting";
|
|
85
|
-
/** Prevent
|
|
85
|
+
/** Prevent another slap until one more card has been played. */
|
|
86
86
|
export declare function startEgyptianWarSlapCooldown(state: EgyptianWarState, playerId: string): void;
|
|
87
87
|
/**
|
|
88
|
-
* Returns the status of
|
|
89
|
-
*
|
|
88
|
+
* Returns the status of a player's slap cooldown. Once another card has been
|
|
89
|
+
* played, the cooldown clears and that new card may be slapped.
|
|
90
90
|
*/
|
|
91
91
|
export declare function checkEgyptianWarSlapCooldown(state: EgyptianWarState, playerId: string): EgyptianWarSlapCooldownStatus;
|
|
92
92
|
export declare function applyEgyptianWarAction(state: EgyptianWarState, playerId: string, action: EgyptianWarAction): string;
|
package/dist/engine.js
CHANGED
|
@@ -471,7 +471,7 @@ function trackPileVersion(state, run) {
|
|
|
471
471
|
}
|
|
472
472
|
}
|
|
473
473
|
}
|
|
474
|
-
/** Prevent
|
|
474
|
+
/** Prevent another slap until one more card has been played. */
|
|
475
475
|
function startEgyptianWarSlapCooldown(state, playerId) {
|
|
476
476
|
const player = state.players.find((candidate) => candidate.id === playerId);
|
|
477
477
|
if (!player)
|
|
@@ -479,8 +479,8 @@ function startEgyptianWarSlapCooldown(state, playerId) {
|
|
|
479
479
|
player.slapCooldownUntilCardPlayCount = (state.cardsPlayedCount ?? 0) + 1;
|
|
480
480
|
}
|
|
481
481
|
/**
|
|
482
|
-
* Returns the status of
|
|
483
|
-
*
|
|
482
|
+
* Returns the status of a player's slap cooldown. Once another card has been
|
|
483
|
+
* played, the cooldown clears and that new card may be slapped.
|
|
484
484
|
*/
|
|
485
485
|
function checkEgyptianWarSlapCooldown(state, playerId) {
|
|
486
486
|
const player = state.players.find((candidate) => candidate.id === playerId);
|
|
@@ -529,6 +529,7 @@ function applyAction(state, playerId, action) {
|
|
|
529
529
|
state.penaltyPileCardCount += cardsForfeited.length;
|
|
530
530
|
if (player.cards.length === 0) {
|
|
531
531
|
player.isEliminated = true;
|
|
532
|
+
startEgyptianWarSlapCooldown(state, playerId);
|
|
532
533
|
if (endIfOnePlayerOwnsRemainingCards(state)) {
|
|
533
534
|
return state.activityMessage;
|
|
534
535
|
}
|
package/docs/design.md
CHANGED
|
@@ -60,7 +60,7 @@ Checked implementation items do not imply that every multiplayer interaction has
|
|
|
60
60
|
- [x] Keep face-down false-slap penalty cards out of slap-pattern validation so repeated penalties cannot manufacture a valid slap.
|
|
61
61
|
- [x] End the game when only one player has cards and the face-up pile offers no valid slap for an eliminated player to reenter.
|
|
62
62
|
- [x] Never let a challenger answer their own challenge: when nobody but the challenger can continue, the challenger wins the pile (or the slap window opens).
|
|
63
|
-
- [x] Prevent
|
|
63
|
+
- [x] Prevent a player who false-slaps while out, or false-slaps away their last card, from repeatedly slapping the unchanged pile; clear that cooldown when the next card is played so they can immediately slap back in.
|
|
64
64
|
- [x] Keep slap-pattern information off the wire: the public state carries a `pileVersion` but no slappable flag, and messages about a pending pile are neutral.
|
|
65
65
|
- [x] Have slaps carry the `pileVersion` the player last saw. A slap that lost a short race with a card play (previous version, previous pile slappable, under 350 ms) is ignored without a penalty.
|
|
66
66
|
- [x] Allow a player to leave voluntarily; their cards are held face-down and added to the next pile, just like a host removal. If removing a player leaves nobody holding cards, the remaining cards go to the next player in turn order immediately.
|
|
@@ -121,6 +121,6 @@ Checked implementation items do not imply that every multiplayer interaction has
|
|
|
121
121
|
- [x] Give the CSS table a layered casino-felt, wooden-rail, depth, and drop-shadow treatment while retaining its original oval shape.
|
|
122
122
|
- [x] Draw cards as accessible HTML/CSS playing-card faces; do not depend on external card image assets.
|
|
123
123
|
- [x] Render mirrored card corners, distinct face-card styling, and a Joker with vertical JOKER labels and a decorative center that is distinguishable from a Jack.
|
|
124
|
-
- [x] Render slap hands with
|
|
124
|
+
- [x] Render slap hands with the splayed-hand emoji on desktop and the backhand emoji on coarse-pointer/mobile devices, scale them and their stopping distance with the rendered card size, keep their shadows visually below the hand at every seat rotation, and layer later collected attempts above the official winner.
|
|
125
125
|
- [x] Keep the table, player seats, card motion, spectator area, and controls usable on narrow screens and with reduced-motion preferences.
|
|
126
126
|
- Offer chat per game rather than requiring it in every game; games that rely on secrecy or fast rounds can opt out, while social multiplayer games can enable it.
|
package/package.json
CHANGED
package/public/client.js
CHANGED
|
@@ -83,11 +83,16 @@ function createEgyptianWarSlapHand() {
|
|
|
83
83
|
const handGlyph = document.createElement("span");
|
|
84
84
|
handGlyph.className = "egyptian-war-flying-hand-glyph";
|
|
85
85
|
handGlyph.setAttribute("aria-hidden", "true");
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
86
|
+
|
|
87
|
+
const desktopHand = document.createElement("span");
|
|
88
|
+
desktopHand.className = "egyptian-war-slap-hand-desktop";
|
|
89
|
+
desktopHand.textContent = "\u{1F590}\uFE0F";
|
|
90
|
+
|
|
91
|
+
const mobileHand = document.createElement("span");
|
|
92
|
+
mobileHand.className = "egyptian-war-slap-hand-mobile";
|
|
93
|
+
mobileHand.textContent = "\u{1F91A}";
|
|
94
|
+
|
|
95
|
+
handGlyph.append(desktopHand, mobileHand);
|
|
91
96
|
return handGlyph;
|
|
92
97
|
}
|
|
93
98
|
function renderEgyptianWarSlapRules(settings) {
|
package/public/style.css
CHANGED
|
@@ -755,25 +755,26 @@ body:has([data-game-plugin-root="egyptian-war"]:not([hidden])) #gameplay-view {
|
|
|
755
755
|
animation-delay: inherit;
|
|
756
756
|
}
|
|
757
757
|
|
|
758
|
-
.egyptian-war-slap-hand-
|
|
758
|
+
.egyptian-war-slap-hand-desktop,
|
|
759
|
+
.egyptian-war-slap-hand-mobile {
|
|
759
760
|
display: block;
|
|
760
761
|
width: 1em;
|
|
761
|
-
height:
|
|
762
|
-
|
|
762
|
+
height: 1em;
|
|
763
|
+
line-height: 1;
|
|
763
764
|
}
|
|
764
765
|
|
|
765
|
-
.egyptian-war-slap-hand-
|
|
766
|
-
|
|
767
|
-
stroke: #aa6818;
|
|
768
|
-
stroke-width: 3;
|
|
769
|
-
stroke-linejoin: round;
|
|
766
|
+
.egyptian-war-slap-hand-mobile {
|
|
767
|
+
display: none;
|
|
770
768
|
}
|
|
771
769
|
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
770
|
+
@media (pointer: coarse) {
|
|
771
|
+
.egyptian-war-slap-hand-desktop {
|
|
772
|
+
display: none;
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
.egyptian-war-slap-hand-mobile {
|
|
776
|
+
display: block;
|
|
777
|
+
}
|
|
777
778
|
}
|
|
778
779
|
|
|
779
780
|
@keyframes egyptian-war-hand-travel {
|