ExPilot.Duels (ExPilot v0.1.1)

Copy Markdown View Source

Challenges between two pilots: each is an arena of its own on a map both know, no robots, the two of them the only ones who may fly (anyone may watch), the first to a number of kills the winner; the arena closes ten seconds after. The challenged may decline and the challenger withdraw (cancel/2), and a duel nobody has flown for ten minutes expires; either way the arena goes.

{:ok, duel} = ExPilot.Duels.challenge("alice", "bob", :dogfight, first_to: 5)
:ok = ExPilot.Duels.cancel(duel.id, "bob")
ExPilot.Duels.list()

A duel is %{id, arena, base, challenger, challenged, first_to, winner, ended, at}: arena the id of its arena (:"duel_<n>", in the lobby like any other, kind duel), base the arena it borrows the map from, winner nil until decided, ended nil while it is on, else :won, :declined, :withdrawn or :expired. result/2 is what the ledger's recorder tells it when a duel ends; ExPilot.Web.PubSub topic "duels" carries {:duels, :changed} on every change. Ended duels stay listed for a minute.

Summary

Functions

End duel id before it is fought: the challenged declines it, the challenger withdraws it. {:error, :not_yours} for anyone else, {:error, :over} once it has ended, {:error, :unknown} for no such duel.

Challenge challenged on arena base: {:ok, duel}, or {:error, :unknown_arena | :yourself}. Options: :first_to (default 5), :duels (the server, default the module).

Returns a specification to start this module under a supervisor.

Every duel: open ones first, then the last minute's ended ones.

A result from a duel's arena, as the ledger's recorder saw it; a won one decides the duel.

Start the duels; :name (default the module, nil for none), :expire_after milliseconds a duel nobody flies lasts (default ten minutes).

Types

duel()

@type duel() :: %{
  id: pos_integer(),
  arena: atom(),
  base: atom(),
  challenger: String.t(),
  challenged: String.t(),
  first_to: pos_integer(),
  winner: String.t() | nil,
  ended: nil | :won | :declined | :withdrawn | :expired,
  at: DateTime.t()
}

Functions

cancel(id, by, opts \\ [])

@spec cancel(pos_integer(), String.t(), keyword()) ::
  :ok | {:error, :not_yours | :over | :unknown}

End duel id before it is fought: the challenged declines it, the challenger withdraws it. {:error, :not_yours} for anyone else, {:error, :over} once it has ended, {:error, :unknown} for no such duel.

challenge(challenger, challenged, base, opts \\ [])

@spec challenge(String.t(), String.t(), atom(), keyword()) ::
  {:ok, duel()} | {:error, term()}

Challenge challenged on arena base: {:ok, duel}, or {:error, :unknown_arena | :yourself}. Options: :first_to (default 5), :duels (the server, default the module).

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

list(duels \\ __MODULE__)

@spec list(GenServer.server()) :: [duel()]

Every duel: open ones first, then the last minute's ended ones.

result(duels \\ __MODULE__, arena, row)

@spec result(GenServer.server(), atom(), map()) :: :ok

A result from a duel's arena, as the ledger's recorder saw it; a won one decides the duel.

start_link(opts \\ [])

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

Start the duels; :name (default the module, nil for none), :expire_after milliseconds a duel nobody flies lasts (default ten minutes).