fun main() {
    mas {
        environment {
            actions {
                action("send", arity=3) {
                    val receiver: Atom by argument(0)
                    val type: Atom by argument(1)
                    val message: Stuct by argument(2)

                    when (type.value) {
                        "tell" -> dispatch(receiver, tell, message))
                        "achieve" -> dispatch(receiver, achieve, message))
                    }
                }
            }
        }

        executionStrategy = OneThreadPerMas()
        //executionStrategy = OneThreadPerAgent()

        agent("pinger") {
            beliefs {
                "turn"("me")
                "other"("ponger")
            }
            goals {
                achieve("send_ping")
            }
            plans {
                +achieve("send_ping") iff { "turn"("me") and "other"(R) } then {
                    +-"turn"("other")
                    achieve("sendMessageTo"("ball", R))
                }
                +"ball" iff { "turn"("other") and "other"(S) } then {
                    +-"turn"("me")
                    self."print"("Received ball from", S)
                    -"ball"
                    self."print"("done")
                }
                +achieve("sendMessageTo"(M, R)) {
                    self."print"("Sending ball to", R)
                    env."send"(R, "tell", M)
                }
            }
        }

        agent("ponger") {
            beliefs {
                "turn"("other")
                "other"("pinger")
            }
            plans {
                +achieve("handle_ping") then {
                    +-"turn"("other")
                    self."print"("done")
                }
                +"ball" iff { "turn"("other") & "other"(S) } then {
                    +-"turn"("me")
                    self."print"("Received ball from", S)
                    -"ball"
                    achieve("sendMessageTo"("ball", S))
                    achieve("handle_ping")
                }
                +achieve("sendMessageTo"(M, R)) {
                    self."print"("Sending ball to", R)
                    env."send"(R, "tell", M)
                }
            }
        }
    }
}
