2011年11月29日火曜日

Fantom でせんだみつおゲーム

Youtube 観てたら、古いテレビの録画で、せんだみつおゲームをやっていた。やっぱりプログラマだから書いてみたくなる。言語はこないだ見つけた、Fantom にしてみる。

こんな感じ

  • Actor を5つ生成して、5名の参加者に見立てる
  • メインのスレッドでは、無限ループしながら Actor にタイミングを出しつづける
  • Actor は、"SENDA", "MITSUO", "NAHANAHA"を出力しながら、ランダムに次の番のアクターを指名する

using concurrent

class SendaMitsuoGame {
  Void main() { play }

  Void play() {
    pool := ActorPool()
    Actor[] actors := (1..5).map { Player(pool, it) }

    actors[0].send("next1")
    actors.each { it.send(actors.toImmutable) }

    messages := ["senda", "mitsuo", "nahanaha"]
    while (true) {
      message := getHeadAndRotate(messages)
      actors.each { it.send(message) }

      Actor.sleep(1sec)
    }
  }
  Str getHeadAndRotate(Str[] m) { m.add(m.removeAt(0)).last }
}

const class Player : Actor {
  const Int number

  new make(ActorPool p, Int number) : super(p) {
    this.number = number }

  override Obj? receive(Obj? msg) {
    if (msg is List) { Actor.locals["all"] = msg }
    else if (msg == "senda") doSenda
    else if (msg == "mitsuo") doMitsuo
    else if (msg == "nahanaha") doNahanaha
    else if (0==((Str)msg).index("next")) {
        setMyTurn(((Str)msg)["next".size..-1].toInt)
    }
    return null
  }

  Bool isNext(Int n) {
    diff := (n - number).abs()
    return 1 == diff || 4 == diff
  }

  Bool isMyTurn() { Actor.locals["myTurn"] }

  Void setMyTurn(Int f) {
    Actor.locals["myTurn"] = (number == f)
    Actor.locals["nextOnesTurn"] = isNext(f) }

  Void doSenda()  { callAndAssign("SENDA") }

  Void doMitsuo() { callAndAssign("MITSUO") }

  Void doNahanaha() {
    if (Actor.locals["nextOnesTurn"])
        echo("" + number + ": NAHANAHA");
  }

  Void callAndAssign(Str call) {
    if (!isMyTurn()) return

    next := nextOne()
    echo("" + number + ": " + call + " -> " + next);

    ((Actor[])Actor.locals["all"]).each { it.send("next" + next) }
  }

  Int nextOne() {
    next := Int.random(1..4)
    if (next < number) return next
    return (++next < 6) ? next: 1
  }
}

出力はこんな感じになる。ミスる事も無く、延々とせんだみつおゲームを繰り返す。適当な確率でミスさせる事も、もちろんできるけど、割愛。

$ fan senda.fan 
1: SENDA -> 2
2: MITSUO -> 5
1: NAHANAHA
4: NAHANAHA
5: SENDA -> 1
1: MITSUO -> 3
4: NAHANAHA
2: NAHANAHA
3: SENDA -> 5
5: MITSUO -> 4
5: NAHANAHA
3: NAHANAHA
4: SENDA -> 3
3: MITSUO -> 1
5: NAHANAHA
2: NAHANAHA
1: SENDA -> 4
4: MITSUO -> 5
1: NAHANAHA
4: NAHANAHA
しかし夜遅くまで、俺、何書いてんだ・・・

0 件のコメント:

コメントを投稿