import scala.
annotation.
tailrec
def isAcceptState
: Boolean
}
trait FSM
[T
<: FSM
[T, A, S
], -A, +S
<: State
] { this: T
=>
def transition
(input
: A
): T
}
@tailrec
def transitionUntilAcceptance
[T
<: FSM
[T, A, S
], A, S
<: State
](fsm
: FSM
[T, A, S
], inputs
: Iterator
[A
]): T
= { val newFSM
= fsm.
transition(input
) if (newFSM.
state.
isAcceptState) { newFSM
transitionUntilAcceptance(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.transitionUntilAcceptance(battle, List(Action, Bonus, Action, Action, Action).iterator))
}
aW1wb3J0IHNjYWxhLmFubm90YXRpb24udGFpbHJlYwoKdHJhaXQgU3RhdGUgewogIGRlZiBpc0FjY2VwdFN0YXRlOiBCb29sZWFuCn0KCnRyYWl0IEZTTVtUIDw6IEZTTVtULCBBLCBTXSwgLUEsICtTIDw6IFN0YXRlXSB7IHRoaXM6IFQgPT4KICBkZWYgc3RhdGU6IFMKCiAgZGVmIHRyYW5zaXRpb24oaW5wdXQ6IEEpOiBUCn0KCm9iamVjdCBGU00gewogIEB0YWlscmVjCiAgZGVmIHRyYW5zaXRpb25VbnRpbEFjY2VwdGFuY2VbVCA8OiBGU01bVCwgQSwgU10sIEEsIFMgPDogU3RhdGVdKGZzbTogRlNNW1QsIEEsIFNdLCBpbnB1dHM6IEl0ZXJhdG9yW0FdKTogVCA9IHsKICAJaWYgKGlucHV0cy5oYXNOZXh0KSB7CiAgICAgIHZhbCBpbnB1dCA9IGlucHV0cy5uZXh0CiAgICAgIHZhbCBuZXdGU00gPSBmc20udHJhbnNpdGlvbihpbnB1dCkKICAgICAgaWYgKG5ld0ZTTS5zdGF0ZS5pc0FjY2VwdFN0YXRlKSB7CiAgICAgICAgbmV3RlNNCiAgICAgIH0gZWxzZSB7CiAgICAgICAgdHJhbnNpdGlvblVudGlsQWNjZXB0YW5jZShuZXdGU00sIGlucHV0cykKICAgICAgfQogIAl9IGVsc2UgewogIAkgIHRocm93IG5ldyBFeGNlcHRpb24oIm5vdCBlbm91Z2ggaW5wdXRzIikKICAJfQogIH0KfQoKc2VhbGVkIGFic3RyYWN0IGNsYXNzIEJhdHRsZUFscGhhYmV0CmNhc2Ugb2JqZWN0IEFjdGlvbiBleHRlbmRzIEJhdHRsZUFscGhhYmV0CmNhc2Ugb2JqZWN0IEJvbnVzIGV4dGVuZHMgQmF0dGxlQWxwaGFiZXQKCnNlYWxlZCBhYnN0cmFjdCBjbGFzcyBCYXR0bGVTdGF0ZSBleHRlbmRzIFN0YXRlCmNhc2Ugb2JqZWN0IFBsYXllclR1cm4gZXh0ZW5kcyBCYXR0bGVTdGF0ZSB7IG92ZXJyaWRlIGRlZiBpc0FjY2VwdFN0YXRlID0gZmFsc2UgfQpjYXNlIG9iamVjdCBFbmVteVR1cm4gZXh0ZW5kcyBCYXR0bGVTdGF0ZSB7IG92ZXJyaWRlIGRlZiBpc0FjY2VwdFN0YXRlID0gZmFsc2UgfQpjYXNlIG9iamVjdCBQbGF5ZXJXb24gZXh0ZW5kcyBCYXR0bGVTdGF0ZSB7IG92ZXJyaWRlIGRlZiBpc0FjY2VwdFN0YXRlID0gdHJ1ZSB9CmNhc2Ugb2JqZWN0IEVuZW15V29uIGV4dGVuZHMgQmF0dGxlU3RhdGUgeyBvdmVycmlkZSBkZWYgaXNBY2NlcHRTdGF0ZSA9IHRydWUgfQoKY2FzZSBjbGFzcyBCYXR0bGUocGxheWVySGVhbHRoOiBJbnQsCiAgICAgICAgICAgICAgICAgIGVuZW15SGVhbHRoOiBJbnQsCiAgICAgICAgICAgICAgICAgIHN0YXRlOiBCYXR0bGVTdGF0ZSkKICBleHRlbmRzIEZTTVtCYXR0bGUsIEJhdHRsZUFscGhhYmV0LCBCYXR0bGVTdGF0ZV0gewogIG92ZXJyaWRlIGRlZiB0cmFuc2l0aW9uKGlucHV0OiBCYXR0bGVBbHBoYWJldCkgPSBzdGF0ZSBtYXRjaCB7CiAgCWNhc2UgUGxheWVyVHVybiA9PgogIAkgIGlucHV0IG1hdGNoIHsKICAJICAgIGNhc2UgQWN0aW9uID0+CiAgCSAgICAgIHZhbCBuZXh0U3RhdGUgPSBpZiAoZW5lbXlIZWFsdGggPT0gMSkgUGxheWVyV29uIGVsc2UgRW5lbXlUdXJuCiAgCSAgICAgIGNvcHkoZW5lbXlIZWFsdGggPSBlbmVteUhlYWx0aCAtIDEsIHN0YXRlID0gbmV4dFN0YXRlKQogIAkgICAgY2FzZSBCb251cyA9PgogIAkgICAgICBjb3B5KHBsYXllckhlYWx0aCA9IHBsYXllckhlYWx0aCArIDEpCiAgCSAgfQogIAljYXNlIEVuZW15VHVybiA9PiAKICAJICBpbnB1dCBtYXRjaCB7CiAgCSAgICBjYXNlIEFjdGlvbiA9PgogIAkgICAgICB2YWwgbmV4dFN0YXRlID0gaWYgKHBsYXllckhlYWx0aCA9PSAxKSBFbmVteVdvbiBlbHNlIFBsYXllclR1cm4KICAJICAgICAgY29weShwbGF5ZXJIZWFsdGggPSBwbGF5ZXJIZWFsdGggLSAxLCBzdGF0ZSA9IG5leHRTdGF0ZSkKICAJICAgIGNhc2UgQm9udXMgPT4KICAJICAgICAgY29weShlbmVteUhlYWx0aCA9IGVuZW15SGVhbHRoICsgMSkKICAJICB9CiAgICBjYXNlIFBsYXllcldvbiA9PiB0aGlzCiAgICBjYXNlIEVuZW15V29uID0+IHRoaXMKICB9Cn0KCm9iamVjdCBNYWluIGV4dGVuZHMgQXBwIHsKICB2YWwgYmF0dGxlID0gQmF0dGxlKDIsIDIsIFBsYXllclR1cm4pCiAgcHJpbnRsbihGU00udHJhbnNpdGlvblVudGlsQWNjZXB0YW5jZShiYXR0bGUsIExpc3QoQWN0aW9uLCBCb251cywgQWN0aW9uLCBBY3Rpb24sIEFjdGlvbikuaXRlcmF0b3IpKQp9Cg==