75 lines
3.1 KiB
Markdown
75 lines
3.1 KiB
Markdown
# WOPR
|
|
|
|
Welcome to War Operation Plan Response, a United States military supercomputer
|
|
programmed to predict possible outcomes of nuclear war.
|
|
|
|
![WOPR](https://media.giphy.com/media/jjYGVvxgQSTsc/giphy.gif)
|
|
|
|
## Installation
|
|
|
|
1. Install Elixir of a version greater than 1.10.
|
|
2. Run `mix local.hex`
|
|
3. Clone [this repo](https://gitlab.com/jimsy/wopr): `git clone https://gitlab.com/jimsy/wopr`
|
|
4. Install the dependencies: `mix deps.get`
|
|
5. Compile the application: `mix compile`.
|
|
|
|
WOPR can be installed by [cloning this repo](https://gitlab.com/jimsy/wopr).
|
|
You need to have a recent version of Elixir installed.
|
|
|
|
## Usage
|
|
|
|
Run the `wopr` shell script in the repository directory. A heck of a lot easier
|
|
than war-dialing your way through all of Seattle.
|
|
|
|
You need to have at two instances of WOPR running either on the same machine or
|
|
local network to be able to play the game.
|
|
|
|
When you start WOPR you'll be greeted, asked for your name and then when another
|
|
player is found, the game will start. Luckily, we're not playing global
|
|
thermonuclear war.
|
|
|
|
## Technical information
|
|
|
|
The game uses [libcluster's gossip strategy][1] to locate other WOPR nodes on
|
|
the local network and [Syn][2] to distribute state across the cluster. Syn may
|
|
not be the best choice for this job, but it was very simple, requiring no setup
|
|
whatsoever.
|
|
|
|
The game is played by orchestrating three kinds of processes; `Game`, `Player` and `Shell`.
|
|
|
|
### The `Game` process
|
|
|
|
The game process holds the keys to the game board and is the only one allowed to
|
|
update the state of the board whenever a player takes a turn.
|
|
|
|
### The `Player` process
|
|
|
|
Simply used to allow players to register themselves in the cluster's registry and keep track of the player's name and score.
|
|
|
|
### The `Shell` process
|
|
|
|
I started off just writing the shell in a procedural style, but quickly realised
|
|
that it needed to behave more like a REPL - sometimes returning immediately,
|
|
sometimes waiting for something else to happen. It uses a process to keep track of the game and player state, and loops printing the appropriate message or requesting input.
|
|
|
|
## Known issues
|
|
|
|
1. I don't like that there's a process for the game. It was the fastest way to
|
|
make it work, but I think I would prefer that there was just a message
|
|
protocol for sending game states between players.
|
|
2. I don't like Syn's eventually-consistent nature for this use case - I would
|
|
prefer to use `gproc`, but couldn't immediately figure out how to enable
|
|
`gproc_dist` so gave up given the time constraints.
|
|
3. The various GenServer's know too much about their state. This should be
|
|
moved to the individual state modules - then the fact that the servers aren't
|
|
tested would be much less surprising.
|
|
4. There's a bug when you have an uneven number of players where they sometimes
|
|
try to start games with each other in a ring formation and fail. I ran out
|
|
of time to fix this, and it's a side effect of 1.
|
|
|
|
1: https://hexdocs.pm/libcluster/Cluster.Strategy.Gossip.html
|
|
2: https://hex.pm/packages/syn
|
|
|
|
## Documentation
|
|
|
|
The generated documentation for the main branch is available [here](https://jimsy.gitlab.io/wopr/)
|