Skip to content

Add deterministic power-ups, inventory, and server-side activation for Battle Tanks - #63

Merged
bashmohandes merged 2 commits into
masterfrom
codex/implement-power-up-catalog-and-mechanics
Aug 16, 2026
Merged

bashmohandes merged 2 commits into
masterfrom
codex/implement-power-up-catalog-and-mechanics

Conversation

@bashmohandes

Copy link
Copy Markdown
Owner

Motivation

  • Introduce a data-driven, reproducible power-up system so pickups behave deterministically in local and online matches and clients cannot influence spawn placement or type.
  • Track match-local pickup state, per-player inventory/equipped weapons, and time/turn-based effects so activations and expirations are authoritative and testable.
  • Provide explicit, pure transition functions for spawning, collection, activation, and effect progression to keep game logic simple and server-authoritative.

Description

  • Added a stable, metadata-driven power-up catalog named POWER_UP_CATALOG with IDs such as health-pack, shield, invisibility, weapon pickups (weapon-heavy-shell, weapon-wide-blast), and modifiers (damage-boost, blast-radius-boost) including consumesTurn and effect metadata in battle-tanks/scripts/game.js.
  • Implemented match-state collections and fields: pickups, inventories, equippedWeapons, activeEffects, spawnSerial, and completedTurns, and exported utility/transition functions spawnPickup, collectPickup, activatePowerUp, beginTurnEffects, expireEffects, and advancePickupSchedule in battle-tanks/scripts/game.js.
  • Enforced placement and collection semantics: pickups spawn on valid exposed terrain using the match-seeded RNG and bounded schedule, avoid tanks/barrier/craters/map edges, and are collected when a tank’s bounds overlap during moveTank (collection caps at INVENTORY_LIMIT and healing is capped at STARTING_HEALTH).
  • Applied effects to weapons and explosions (equipped weapon payloads, damage/blast multipliers, shield absorption tracked as remaining absorbed damage rather than wall-clock time) and made activation semantics explicit (consumesTurn influences turn advancement).
  • Added server-side handling for validated inventory commands activate and equip and ensured the server performs spawning/collection/expiration and serializes pickup/inventory/effect state to clients in server/battle-tanks-rooms.js and allowed these message types in server/index.js.
  • Updated client UI and rendering in battle-tanks/index.html, battle-tanks/styles.css, and battle-tanks/scripts/app.js to show inventory, current weapon, shield visuals, active effects and durations, pickup rendering in the arena, and to disable controls when it is not the player’s turn.
  • Added tests covering spawning determinism and bounds, valid placement, collection and inventory limits, healing caps, activation timing and effect expiration, rematch cleanup, stale online commands, and synchronized pickup/effect state in tests/battle-tanks.test.js and tests/battle-tanks-rooms.test.js.

Testing

  • Ran unit and integration tests with npm test and focused tests (npm test -- --test-name-pattern='power-up|pickup|inventory|activation|rematch'), and all relevant tests passed (no failures).
  • Ran project checks with npm run check to ensure syntax and consistency across modified files, and the check completed without errors.
  • Exercise highlights: server-side validation tests for activate/equip, seeded spawning determinism, valid pickup placement, inventory/cap behavior, activation/expiration semantics, rematch cleanup, stale-command rejection, and synchronized state between players all passed.

Codex Task

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 31584ec3f9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

function beginTurn(state, player = state.activePlayer) { if (state.phase === 'game-over') return false; state.activePlayer = player; state.phase = 'aiming'; state.projectile = null; state.announcement = `Player ${player + 1}: adjust your shot.`; return true; }
function moveTank(state, direction, amount = 8) { if (state.phase !== 'aiming') return false; const tank = state.tanks[state.activePlayer], bounds = tankBounds(state, state.activePlayer); tank.x = clamp(tank.x + (direction === 'forward' ? (state.activePlayer ? -amount : amount) : (state.activePlayer ? amount : -amount)), bounds.min, bounds.max); tank.y = tankYAt(state, tank); return true; }
function beginTurn(state, player = state.activePlayer) { if (state.phase === 'game-over') return false; state.activePlayer = player; state.phase = 'aiming'; state.projectile = null; beginTurnEffects(state, player); state.announcement = `Player ${player + 1}: adjust your shot.`; return true; }
function moveTank(state, direction, amount = 8) { if (state.phase !== 'aiming') return false; const tank = state.tanks[state.activePlayer], bounds = tankBounds(state, state.activePlayer); tank.x = clamp(tank.x + (direction === 'forward' ? (state.activePlayer ? -amount : amount) : (state.activePlayer ? amount : -amount)), bounds.min, bounds.max); tank.y = tankYAt(state, tank); collectPickup(state, state.activePlayer); return true; }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Collect pickups during pointer-based movement

Pickup collection is only invoked by moveTank, but local touch/pointer movement in app.js changes tank.x and tank.y directly. Consequently, a player who follows the documented drag controls can drive across a pickup without collecting it; collection should also run from the drag path or all movement should go through a shared helper.

Useful? React with 👍 / 👎.

Comment thread battle-tanks/scripts/game.js Outdated
if (collected.length) state.announcement = `Player ${player + 1} collected ${POWER_UP_CATALOG[collected[0]].label}.`;
return collected;
}
function expireEffects(state, player) { state.activeEffects[player] = state.activeEffects[player].filter(effect => effect.remainingTurns === undefined || effect.remainingTurns > 0 || effect.remainingAbsorption > 0); return state.activeEffects[player]; }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove fully depleted shield effects

When a shield reaches zero absorption, this predicate still retains it because shield records have remainingTurns === undefined, making the first condition true regardless of remainingAbsorption. After the shield owner's next turn begins, the inventory panel therefore continues to report Shield 0 as an active effect for the rest of the match instead of returning to “No active effects.”

Useful? React with 👍 / 👎.

@bashmohandes
bashmohandes merged commit efb36e9 into master Aug 16, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant