import scala.
annotation.
tailrec
def isAcceptState
: Boolean
}
trait FSM
[T
<: FSM
[T, A, S
], -A, +S
<: State
] { this: T
=>
}
@tailrec
def resumeUntilAcceptance
[T
<: FSM
[T, A, S
], A, S
<: State
](fsm
: T, inputs
: Iterator
[A
]): T
= { val newFSM
= fsm.
resume(input
) if (newFSM.
state.
isAcceptState) { newFSM
resumeUntilAcceptance[T, A, S](newFSM, inputs)
}
throw new Exception
("not enough inputs") }
}
}
enemyHealth: Int,
state: BattleState)
extends FSM
[Battle, BattleAlphabet, BattleState
] { val nextState
= if (enemyHealth
== 1) PlayerWon
else EnemyTurn
copy(enemyHealth = enemyHealth - 1, state = nextState)
copy(playerHealth = playerHealth + 1)
}
val nextState
= if (playerHealth
== 1) EnemyWon
else PlayerTurn
copy(playerHealth = playerHealth - 1, state = nextState)
copy(enemyHealth = enemyHealth + 1)
}
}
}
val battle
= Battle
(2,
2, PlayerTurn
) println(FSM.resumeUntilAcceptance[Battle, BattleAlphabet, BattleState](battle, List(Action, Bonus, Action, Action, Action).iterator))
}
aW1wb3J0IHNjYWxhLmFubm90YXRpb24udGFpbHJlYwoKdHJhaXQgU3RhdGUgewogIGRlZiBpc0FjY2VwdFN0YXRlOiBCb29sZWFuCn0KCnRyYWl0IEZTTVtUIDw6IEZTTVtULCBBLCBTXSwgLUEsICtTIDw6IFN0YXRlXSB7IHRoaXM6IFQgPT4KICBkZWYgc3RhdGU6IFMKCiAgZGVmIHJlc3VtZShpbnB1dDogQSk6IFQKfQoKb2JqZWN0IEZTTSB7CiAgQHRhaWxyZWMKICBkZWYgcmVzdW1lVW50aWxBY2NlcHRhbmNlW1QgPDogRlNNW1QsIEEsIFNdLCBBLCBTIDw6IFN0YXRlXShmc206IFQsIGlucHV0czogSXRlcmF0b3JbQV0pOiBUID0gewogIAlpZiAoaW5wdXRzLmhhc05leHQpIHsKICAgICAgdmFsIGlucHV0ID0gaW5wdXRzLm5leHQKICAgICAgdmFsIG5ld0ZTTSA9IGZzbS5yZXN1bWUoaW5wdXQpCiAgICAgIGlmIChuZXdGU00uc3RhdGUuaXNBY2NlcHRTdGF0ZSkgewogICAgICAgIG5ld0ZTTQogICAgICB9IGVsc2UgewogICAgICAgIHJlc3VtZVVudGlsQWNjZXB0YW5jZVtULCBBLCBTXShuZXdGU00sIGlucHV0cykKICAgICAgfQogIAl9IGVsc2UgewogIAkgIHRocm93IG5ldyBFeGNlcHRpb24oIm5vdCBlbm91Z2ggaW5wdXRzIikKICAJfQogIH0KfQoKc2VhbGVkIGFic3RyYWN0IGNsYXNzIEJhdHRsZUFscGhhYmV0CmNhc2Ugb2JqZWN0IEFjdGlvbiBleHRlbmRzIEJhdHRsZUFscGhhYmV0CmNhc2Ugb2JqZWN0IEJvbnVzIGV4dGVuZHMgQmF0dGxlQWxwaGFiZXQKCnNlYWxlZCBhYnN0cmFjdCBjbGFzcyBCYXR0bGVTdGF0ZSBleHRlbmRzIFN0YXRlCmNhc2Ugb2JqZWN0IFBsYXllclR1cm4gZXh0ZW5kcyBCYXR0bGVTdGF0ZSB7IG92ZXJyaWRlIGRlZiBpc0FjY2VwdFN0YXRlID0gZmFsc2UgfQpjYXNlIG9iamVjdCBFbmVteVR1cm4gZXh0ZW5kcyBCYXR0bGVTdGF0ZSB7IG92ZXJyaWRlIGRlZiBpc0FjY2VwdFN0YXRlID0gZmFsc2UgfQpjYXNlIG9iamVjdCBQbGF5ZXJXb24gZXh0ZW5kcyBCYXR0bGVTdGF0ZSB7IG92ZXJyaWRlIGRlZiBpc0FjY2VwdFN0YXRlID0gdHJ1ZSB9CmNhc2Ugb2JqZWN0IEVuZW15V29uIGV4dGVuZHMgQmF0dGxlU3RhdGUgeyBvdmVycmlkZSBkZWYgaXNBY2NlcHRTdGF0ZSA9IHRydWUgfQoKY2FzZSBjbGFzcyBCYXR0bGUocGxheWVySGVhbHRoOiBJbnQsCiAgICAgICAgICAgICAgICAgIGVuZW15SGVhbHRoOiBJbnQsCiAgICAgICAgICAgICAgICAgIHN0YXRlOiBCYXR0bGVTdGF0ZSkKICBleHRlbmRzIEZTTVtCYXR0bGUsIEJhdHRsZUFscGhhYmV0LCBCYXR0bGVTdGF0ZV0gewogIG92ZXJyaWRlIGRlZiByZXN1bWUoaW5wdXQ6IEJhdHRsZUFscGhhYmV0KSA9IHN0YXRlIG1hdGNoIHsKICAJY2FzZSBQbGF5ZXJUdXJuID0+CiAgCSAgaW5wdXQgbWF0Y2ggewogIAkgICAgY2FzZSBBY3Rpb24gPT4KICAJICAgICAgdmFsIG5leHRTdGF0ZSA9IGlmIChlbmVteUhlYWx0aCA9PSAxKSBQbGF5ZXJXb24gZWxzZSBFbmVteVR1cm4KICAJICAgICAgY29weShlbmVteUhlYWx0aCA9IGVuZW15SGVhbHRoIC0gMSwgc3RhdGUgPSBuZXh0U3RhdGUpCiAgCSAgICBjYXNlIEJvbnVzID0+CiAgCSAgICAgIGNvcHkocGxheWVySGVhbHRoID0gcGxheWVySGVhbHRoICsgMSkKICAJICB9CiAgCWNhc2UgRW5lbXlUdXJuID0+IAogIAkgIGlucHV0IG1hdGNoIHsKICAJICAgIGNhc2UgQWN0aW9uID0+CiAgCSAgICAgIHZhbCBuZXh0U3RhdGUgPSBpZiAocGxheWVySGVhbHRoID09IDEpIEVuZW15V29uIGVsc2UgUGxheWVyVHVybgogIAkgICAgICBjb3B5KHBsYXllckhlYWx0aCA9IHBsYXllckhlYWx0aCAtIDEsIHN0YXRlID0gbmV4dFN0YXRlKQogIAkgICAgY2FzZSBCb251cyA9PgogIAkgICAgICBjb3B5KGVuZW15SGVhbHRoID0gZW5lbXlIZWFsdGggKyAxKQogIAkgIH0KICAgIGNhc2UgUGxheWVyV29uID0+IHRoaXMKICAgIGNhc2UgRW5lbXlXb24gPT4gdGhpcwogIH0KfQoKb2JqZWN0IE1haW4gZXh0ZW5kcyBBcHAgewogIHZhbCBiYXR0bGUgPSBCYXR0bGUoMiwgMiwgUGxheWVyVHVybikKICBwcmludGxuKEZTTS5yZXN1bWVVbnRpbEFjY2VwdGFuY2VbQmF0dGxlLCBCYXR0bGVBbHBoYWJldCwgQmF0dGxlU3RhdGVdKGJhdHRsZSwgTGlzdChBY3Rpb24sIEJvbnVzLCBBY3Rpb24sIEFjdGlvbiwgQWN0aW9uKS5pdGVyYXRvcikpCn0K