@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 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. An eliminated player has no cards
56
- to forfeit, so a false slap prevents them from slapping the unchanged pile
57
- again. The cooldown clears when the next card is played, allowing that card to
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
 
@@ -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.1",
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 repeated free slaps until one more card has been played. */
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 an eliminated player's slap cooldown. Once another
89
- * card has been played, the cooldown clears and that new card may be slapped.
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 repeated free slaps until one more card has been played. */
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 an eliminated player's slap cooldown. Once another
483
- * card has been played, the cooldown clears and that new card may be slapped.
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 an eliminated player who false-slaps from repeatedly slapping the unchanged pile; clear that cooldown when the next card is played so they can immediately slap back in.
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 a package-owned palm graphic for consistent mobile orientation, 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.
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@masonf539/egyptian-war",
3
- "version": "1.0.1-beta.1",
3
+ "version": "1.0.1-beta.3",
4
4
  "description": "Egyptian War game plugin for GameHub.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
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
- handGlyph.innerHTML = `
87
- <svg class="egyptian-war-slap-hand-svg" viewBox="0 0 100 120" focusable="false">
88
- <path class="egyptian-war-slap-hand-shape" d="M28 112c-11-7-17-20-17-35V58c0-5 4-9 9-9s9 4 9 9V28c0-6 4-10 9-10s9 4 9 10V17c0-6 4-10 9-10s9 4 9 10v7c1-5 5-8 10-8s9 4 9 10v42c0 27-14 45-38 47-7 1-13 0-18-3Z"/>
89
- <path class="egyptian-war-slap-hand-detail" d="M29 58v19m18-49v38m18-42v42m19-40v43M25 82c12-6 25-4 34 6m-26 8c8-5 17-5 25 1"/>
90
- </svg>`;
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-svg {
758
+ .egyptian-war-slap-hand-desktop,
759
+ .egyptian-war-slap-hand-mobile {
759
760
  display: block;
760
761
  width: 1em;
761
- height: 1.2em;
762
- overflow: visible;
762
+ height: 1em;
763
+ line-height: 1;
763
764
  }
764
765
 
765
- .egyptian-war-slap-hand-shape {
766
- fill: #ffc34d;
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
- .egyptian-war-slap-hand-detail {
773
- fill: none;
774
- stroke: #d78b25;
775
- stroke-width: 3;
776
- stroke-linecap: round;
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 {