9.3 Example: Battleships! 245
the fields belonging to each ship as an array of arrays. A copy of these arrays
is worked through successively in the variable game.ships.partsTodo during the
game and only contains ten empty arrays at the end of the game for the losing
player, because the relevant position is deleted for each hit.
With each newly placed ship, the label of the relevant button is updated as well,
showing how many ships of this type are still available. It disappears once all
ships of this type have been placed. Once all ships are placed, the entire form
disappears and a message is sent to the opponent: Ready to start the game!
if (game.ships.parts.length == 10) {
document.forms.digitize.style.display = 'none';
game.me.grid['1-1'].parentNode.style.pointerEvents =
'none';
wsMessage({
task : 'private',
request : 'ready',
client : game.you.id
});
game.me.ready = true;
}
Who comes first, goes first is the motto, so the player who is the quickest to place
all his ships can begin the game. The slower player has to bite the bullet and
suffer the first attack on his fleet. To allow each player to attack the opponent’s
ships, a second play area is displayed after both players have placed their ships.
The game logic for attacking and sinking ships is implemented fully on the cli-
ent side. The server only distributes the game moves as private messages to both
players involved. Each click on an active play field calls the reveal function:
this.reveal = function(evt) {
wsMessage({
task : 'private',
request : 'challenge',
field : evt.target.value,
client : game.you.id
});
};
The server transmits the message to the opponent’s side, which then checks
whether the field the other player clicked on contains part of a ship or not:
else if (msg.request == 'challenge') {
var destroyed = 0;
if (game.ships.isShip[msg.field]) {
game.me.grid[msg.field].setAttribute("class","hit");
Figure 9.5 shows the game in demo mode.