Simulate a Game

Now we implement a small toy example for concurrency with three actors using only some classic actor primitives:

PrimitiveBrief description
spawncreate an actor from a behavior and return a link,
selfget the link of the current actor,
sendsend a message to an actor.

We simulate table-tennis where a player has a name and a capability. If he gets a ball with a difficulty exceeding his capability, he looses it. Players log to a print server actor.

using Actors, Printf, Random
import Actors: spawn

struct Player{S,T}
    name::S  # player's name 
    capa::T  # capabiity

struct Ball{T,S,L}
    diff::T  # difficulty
    name::S  # the server's name
    from::L  # the server's link

struct Serve{L}
    to::L    # the opponent's link

We implement Player as a function object which gets the prn print server link as additional acquaintance and knows two message types: Ball and Serve.

function (p::Player)(prn, b::Ball)
    if p.capa ≥ b.diff
        send(b.from, Ball(rand(),, self()))
        send(prn,*" serves "*
        send(prn,*" looses ball from "*
function (p::Player)(prn, s::Serve)
    send(, Ball(rand(),, self()))
    send(prn,*" serves ")

In order to get reproducible results we initialize our random generator on each thread and assign threads to players.

The print server prn gets an anonymous function as behavior. The two players ping and pong get the print server's link as acquaintance and - for illustration - are started on different threads. We start the game by sending ping a Serve message with the address of pong.

@threads for i in 1:nthreads()

prn = spawn(s->print(@sprintf("%s\n", s))) 
ping = spawn(Player("Ping", 0.8), prn, thrd=3)
pong = spawn(Player("Pong", 0.75), prn, thrd=4)

send(ping, Serve(pong))

To execute the program we include the file:

julia> include("examples/pingpong.jl");

Ping serves 
Pong serves Ping
Ping serves Pong
Pong serves Ping
Ping serves Pong
Pong looses ball from Ping

Actors are great for simulation.