Обеспечение синхронности в многоагентных системах

Пытаясь изучить как scala, так и akka, я пишу игру Battleship. На самом деле я еще не начал писать код, я просто думаю о том, как все будет работать.

У меня есть агенты для кораблей и флотов игроков, а также такие сообщения, как «выстрел», «попадание», «промах», «все корабли уничтожены». Мой первый камень преткновения заключается в том, что когда игрок 1 стреляет, это создает взрыв событий, и игрок 2 должен ждать, пока все не уляжется, прежде чем он сможет сыграть свой ход. Как я могу убедиться в этом? Я подумал, может быть, я всегда буду отправлять ответ, несмотря ни на что, а затем считать, что отправитель получает ровно столько ответов, сколько отправлено сообщений. Может быть Морской бой не лучшее приложение для агентов.

Это также ставит вопрос о том, как определить разницу между отсутствием ответа, потому что сообщение еще не было обработано, агент ничего не ответил или агент умер. Но я оставлю это на потом.


person janin    schedule 02.06.2012    source источник


Ответы (1)


Здесь есть несколько вещей, которые вы можете сделать:

  • Пусть первый субъект получает ответы на каждое свое сообщение, а затем отправляет сообщение ваша очередь второму субъекту.

  • Отправить сообщение второму актеру, указывающее, сколько событий в данном ходе должно быть получено

Это достигается следующим образом:

import akka.pattern._
(d1 ? m1) zip (d2 ? m2) pipeTo that

в приведенном выше примере d1/2 — это субъекты назначения, m1/2 — сообщения, которые нужно отправить. Ответы от этих акторов заархивированы вместе (в Tuple2) и перенаправлены второму актору (в примере that).

Второй механизм немного сложнее; Я писал подобные вещи, используя SyncPoints. Итак, что-то вроде этого:

case class SyncPoint(id: UUID, participants: ActorRef*)
object SyncPoint {
  def newFor(participants: ActorRef*) = SyncPoint(UUID.createRandomUUID, participants)
}

Затем создатель сообщения сначала отправляет SyncPoint конечному наблюдателю.

val sync = SyncPoint.newFor(d1, d2)
that ! sync

Теперь конечный получатель знает, что он ожидает сообщения об этом SyncPoint для каждого участника.

d1 ! SyncPart(m1, sync)
d2 ! SyncPart(m2, sync)

Где

case class SyncPart(msg: Any, sync: SyncPoint)

Актеры d1 и d2 переадресуют сообщение that, когда они обработают свою часть сообщения.

case class SyncPartial(sync: SyncPoint, participant: ActorRef)

Таким образом, that знает, что ожидает сообщения от нескольких участников, и может отслеживать, когда эти участники выполнили свою обработку.

person oxbow_lakes    schedule 02.06.2012
comment
Спасибо. Я думаю, что выберу первый подход, так как заранее не знаю, сколько событий будет сгенерировано. - person janin; 03.06.2012