Battleship
Two-player Battleship in the browser, with room codes, a solo bot mode, and a server that keeps both players in sync.
Visit the live site ↗Battleship is a browser game I designed and developed with a Godot client and an authoritative multiplayer server. Two people can play by sharing a four-character room code, or one player can face a bot.
The work spans the board interface, game rules, multiplayer communication, and the match lifecycle: placing a fleet, taking turns, recovering a connection, and starting a rematch.
One source of truth for the match
The Godot client handles presentation and input; the server owns the rules and match state. They communicate over WebSocket. Ship placement is checked for board boundaries, straight contiguous cells, and overlap. Shots are checked against the current turn and board state rather than accepted as results from the player’s browser.
That division keeps the two clients working from the same decisions. It also means a bot match still needs the server: solo play uses the same game protocol, not a separate offline implementation. The bot has easy, normal, and hard difficulty settings.
Keeping the opponent’s fleet private
Synchronizing a game does not mean sending both players the entire board. The rules layer builds a view for each player, including their own fleet and shot history. During a match, the opponent’s ship positions are revealed only when those ships have been sunk. Both fleets become visible when the match ends.
This makes hidden information a server-side responsibility rather than merely hiding ships in the interface.
Reconnecting without restarting the clock
A disconnected player can resume during the server’s session grace period. The turn deadline stays in authoritative match state, so reconnecting does not grant extra time. The server enforces a 60-second shot timer by default; letting it expire forfeits the match.
After the result, both players can vote for a rematch in the existing room. Connection recovery, turn timing, and rematches are part of the same match lifecycle rather than isolated screens.
Making the board usable on smaller screens
The interface includes ship rotation, placement undo, and a random-fleet option. On portrait screens, combat offers a two-board overview and a separate Aim view for targeting. A fleet summary tracks remaining ships, and the result screen shows hits, misses, and sunk ships.
Testing across the match lifecycle
The repository includes rules tests and integration coverage for gameplay, reconnection, and screen flow, alongside a server-free UI regression gate. Mobile and physical-device checks have also been completed and signed off.
The central engineering challenge is consistency: keeping rules, private player views, and recovery behavior aligned across human opponents, bots, and different screen layouts.

