diff --git a/docs/development/CENTRAL.md b/docs/development/CENTRAL.md deleted file mode 100644 index f136d17..0000000 --- a/docs/development/CENTRAL.md +++ /dev/null @@ -1,8 +0,0 @@ -# Development Status (Central) - -## Active Tasks -- [x] Enable Clear Session Button (2025-12-20) - -## Devlog Index -- [Enable Clear Session](./devlog/2025-12-20-014500_enable_clear_session.md) - Improved UI/UX for session clearing in CubeManager. -- [Bot Actions](./devlog/2025-12-22-114000_bot_actions.md) - Implemented simple bot AI for playing lands, casting creatures, and passing priority. diff --git a/docs/development/devlog/2025-12-20-014500_enable_clear_session.md b/docs/development/devlog/2025-12-20-014500_enable_clear_session.md deleted file mode 100644 index 32ddf3e..0000000 --- a/docs/development/devlog/2025-12-20-014500_enable_clear_session.md +++ /dev/null @@ -1,16 +0,0 @@ -# Enable Clear Session Button in Pack Generator - -## Object -Enable and improve the "Clear Session" button in the Cube Manager (Pack Generator) to allow users to restart the generation process from a clean state. - -## Changes -- Modified `CubeManager.tsx`: - - Updated `handleReset` logic (verified). - - enhanced "Clear Session" button styling to be more visible (red border/text) and indicate its destructive nature. - - Added `disabled={loading}` to prevent state conflicts during active operations. - - **Replaced `window.confirm` with a double-click UI confirmation pattern** to ensure reliability and better UX (fixed issue where native confirmation dialog was failing). - -## Status -- [x] Implementation complete. -- [x] Verified logic for `localStorage` clearing. -- [x] Verified interaction in browser (button changes state, clears data on second click). diff --git a/docs/development/devlog/2025-12-22-114000_bot_actions.md b/docs/development/devlog/2025-12-22-114000_bot_actions.md deleted file mode 100644 index 1495981..0000000 --- a/docs/development/devlog/2025-12-22-114000_bot_actions.md +++ /dev/null @@ -1,29 +0,0 @@ -# Bot Logic Implementation - -## Changes -- **Client/Server Types**: Added `isBot` to `PlayerState` interface. -- **GameManager**: - - Updated `createGame` to persist `isBot` flag from room players. - - Implemented `processBotActions` method: - - **Mulligan**: Always keeps hand. - - **Main Phase**: Plays a Land if available and not played yet. - - **Main Phase**: Casts first available Creature card from hand (simplified cost check). - - **Combat**: Attacks with all available creatures. - - **Default**: Passes priority. - - Added `triggerBotCheck` public method to manually trigger bot automation (e.g. at game start). - - Updated `handleStrictAction` to include a `while` loop that processes consecutive bot turns until a human receives priority. -- **Server Entry (index.ts)**: - - Injected `gameManager.triggerBotCheck(roomId)` at all game start points (Normal start, Solo test, Deck timeout, etc.) to ensure bots act immediately if they win the coin flip or during mulligan. - -## Bot Behavior -The bots are currently "Aggressive/Linear": -1. They essentially dump their hand (Lands -> Creatures). -2. They always attack with everything. -3. They never block. -4. They pass priority instantly if they can't do anything. - -## Future Improvements -- Implement mana cost checking (currently relying on loose engine rules or implicit valid state). -- Implement target selection logic (currently casting only if no targets needed or using empty array). -- Implement blocking logic. -- Implement "Smart" mulligans (currently always keep). diff --git a/docs/development/mtg-rulebook/MagicCompRules20251114.txt b/docs/mtg-rulebook/MagicCompRules20251114.txt similarity index 100% rename from docs/development/mtg-rulebook/MagicCompRules20251114.txt rename to docs/mtg-rulebook/MagicCompRules20251114.txt diff --git a/docs/development/mtg-rulebook/peasant-pack-generation-algorithm.md b/docs/mtg-rulebook/peasant-pack-generation-algorithm.md similarity index 100% rename from docs/development/mtg-rulebook/peasant-pack-generation-algorithm.md rename to docs/mtg-rulebook/peasant-pack-generation-algorithm.md diff --git a/docs/development/mtg-rulebook/standard-pack-generation-algorithm.md b/docs/mtg-rulebook/standard-pack-generation-algorithm.md similarity index 100% rename from docs/development/mtg-rulebook/standard-pack-generation-algorithm.md rename to docs/mtg-rulebook/standard-pack-generation-algorithm.md diff --git a/src/client/src/modules/game/GameView.tsx b/src/client/src/modules/game/GameView.tsx index f908774..571475d 100644 --- a/src/client/src/modules/game/GameView.tsx +++ b/src/client/src/modules/game/GameView.tsx @@ -675,7 +675,7 @@ export const GameView: React.FC = ({ gameState, currentPlayerId } {/* Opponent Battlefield */} -
+
= ({ gameState, currentPlayerId } transformOrigin: 'center bottom', }} > - {oppBattlefield.map(card => { - const isAttacking = card.attacking === currentPlayerId; // They are attacking ME - const isBlockedByMe = Array.from(proposedBlockers.values()).includes(card.instanceId); + {(() => { + // Organize Opponent Cards + const oppLands = oppBattlefield.filter(c => c.types?.includes('Land') && !c.types?.includes('Creature')); + const oppCreatures = oppBattlefield.filter(c => !c.types?.includes('Land') || c.types?.includes('Creature')); return ( -
- { }} - onClick={() => { }} - onMouseEnter={() => setHoveredCard(card)} - onMouseLeave={() => setHoveredCard(null)} - className={` - w-24 h-24 rounded shadow-sm - ${isAttacking ? "ring-4 ring-red-600 shadow-[0_0_20px_rgba(220,38,38,0.6)]" : ""} - ${isBlockedByMe ? "ring-4 ring-blue-500" : ""} - `} - /> - - {isAttacking && ( -
- ATTACKING -
- )} +
+ {/* Back Row: Lands (Top) */} +
+ {oppLands.map((card, idx) => ( +
+ { }} + onClick={() => { }} + onMouseEnter={() => setHoveredCard(card)} + onMouseLeave={() => setHoveredCard(null)} + /> +
+ ))} + {oppLands.length === 0 &&
} +
+ + {/* Front Row: Creatures (Bottom) */} +
+ {oppCreatures.map(card => { + const isAttacking = card.attacking === currentPlayerId; // They are attacking ME + const isBlockedByMe = Array.from(proposedBlockers.values()).includes(card.instanceId); + + return ( +
+ setHoveredCard(card)} + onMouseLeave={() => setHoveredCard(null)} + onDragStart={() => { }} + onClick={() => { }} + className={` + w-24 h-24 rounded shadow-sm + ${isAttacking ? "ring-4 ring-red-600 shadow-[0_0_20px_rgba(220,38,38,0.6)]" : ""} + ${isBlockedByMe ? "ring-4 ring-blue-500" : ""} + `} + /> + + + {isAttacking && ( +
+ ATTACKING +
+ )} +
+ ); + })} +
); - })} + })()}