Battleship is a strategy type guessing game for two players. It is played on ruled grids (paper or board) on which each player’s fleet of warships are marked. The locations of the fleets are concealed from the other player. Players alternate turns calling “shots” at the other player’s ships, and the objective of the game is to destroy the opposing player’s fleet. Ships cannot touch each other horizontally, vertically or diagonally.

Writing a game from scratch, including agents, seems like a pretty daunting task. Nevertheless we could start with a tiniest prototype implementation ever possible, simplifying everything that is not necessary at the moment.

Any tile in a grid could consist any ship part:

type Tile = Unit `ML` Unit
 
pattern Idle = This Unit
pattern Ship = That Unit

But from an oppononent point of view, we should include some information whether a damaged ship is sinking after shooting:

type Nail = Unit `ML` Unit
 
pattern Bang i = This i
pattern Sunk i = That i
 
type Shot = Nail `ML` Unit
 
pattern Nail i = This i
pattern Miss i = That i

Players need distinguish boards to arrange their ships and track opponent ones. For the sake of simplicity we start with one dimensional area:

type Board = Nonempty List
 
type Personal = Board Tile
type Opponent = Board Shot

We represent all ships as lists of units:

type Ship = Board Unit

Before players arrange their boards, they both should know a set of available ships.

type Fleet = Board Ship

Let’s say we have one 2-sized and one 3-sized ships:

fleet = Nonempty @List @Ship
 `ha_` Item `ha` Nonempty @List
  `ha` Item Unit `ha` Maybe `ha` Next
  `ha` Item Unit `ha` Maybe `ha` Next
  `ha` Item Unit `ha` Maybe `hv` Last
 `ha_` Maybe `ha_` Next
 `ha_` Item `ha` Nonempty @List
  `ha` Item Unit `ha` Maybe `ha` Next
  `ha` Item Unit `ha` Maybe `hv` Last
 `ha_` Maybe `hv_` Last

There is not so much we can do with it except print it out to console.

Printing a title is straightforward, we just need to specify exast datastructure behind a string literal:

title x = is @(List ASCII) x `yokl` Forth `ha` World `ha` output

Printing out ships is more tricky, we need first to traverse a list of ships, then ships themselves, making a space break after each one:

print x = x `yokl_` Forth `ha` World `ha___` is @Ship
 `ho__'yukl` Forth `ha` World `ha` output `ha` Glyph `ha` Symbol `ha` Punctuate `hv` by Hash
 `ho__'yuk` World `ha` output `ha` Caret `hv` by Space

Finally, putting it all together:

main = enter @World
 `yuk__` World `hv` title "SHIPS: "
 `yuk__` World `hv` print fleet

Here is the result:

SHIPS: ### ##

Having all this in mind, how the bot should understand where to hit? By calculating probabilities.

Full source code is available here.

Continue this tutorial