# `Cauldron2D.Robot`
[🔗](https://github.com/jaman/cauldron/blob/v0.1.3/cauldron_2d/lib/cauldron_2d/robot.ex#L1)

A computer player: a process that joins a world as `{:robot, n}` and plays by its
view, deciding every few frames through a brain module the game supplies.

    defmodule MyGame.Brain do
      @behaviour Cauldron2D.Robot

      def init(opts), do: %{}
      def decide(view, memory, %{tick: tick, skill: skill}), do: {%{held: MapSet.new([:thrust]), aim: nil}, memory}
      def gone?(view), do: view.me == nil
    end

    Cauldron2D.Robot.start_link(brain: MyGame.Brain, world: world, number: 1)

`decide/3` is given the latest view, the brain's memory and `%{tick: n, skill: s}`, and
returns the input to hold — a `t:Cauldron2D.Input.state/0`, or `nil` to leave the input
as it is — with the memory to keep. The input is sent to the world only when it
differs from what was last sent. `gone?/1` says the robot has no place in the world
any more; it then leaves and stops. `init/1` is optional; without it the memory
starts as `nil`, and `gone?/1` without it is never true.

Every robot has a skill, drawn by `skill/0` between 0.3 and 1.0 unless given: it
sets how often the robot decides (`cadence/2`) and is passed to the brain for whatever
else the game makes of it.

## Options

  * `:brain` — the module. Required
  * `:world` — the world to join. Required
  * `:number` — the robot's number; its id is `{:robot, number}`. Required
  * `:brain_opts` — given to the brain's `init/1`. Default `[]`
  * `:props` — merged over `%{username: "Robot n", robot?: true}` for the join.
    Default `%{}`
  * `:skill` — 0.3 to 1.0. Default `skill/0`
  * `:cadence` — `{fastest, slowest}`, frames between decisions at full and least
    skill. Default `{3, 9}`

# `decide`

```elixir
@callback decide(view :: term(), memory :: term(), %{tick: pos_integer(), skill: float()}) ::
  {Cauldron2D.Input.state() | nil, term()}
```

# `gone?`
*optional* 

```elixir
@callback gone?(view :: term()) :: boolean()
```

# `init`
*optional* 

```elixir
@callback init(keyword()) :: term()
```

# `cadence`

```elixir
@spec cadence(float(), {pos_integer(), pos_integer()}) :: pos_integer()
```

Every how many frames a robot of `skill` decides: `fastest` at full skill, `slowest` at the least.

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `skill`

```elixir
@spec skill() :: float()
```

A skill drawn at random between 0.3 and 1.0.

# `start_link`

```elixir
@spec start_link(keyword()) :: GenServer.on_start()
```

Start a robot; see the module documentation for the options. A refused join is `{:error, reason}`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
