222 lines
6.3 KiB
Scala
222 lines
6.3 KiB
Scala
package fmon.stat
|
|
|
|
import scala.collection.mutable.{Map => MutMap}
|
|
import scala.reflect.runtime.universe._
|
|
import scala.tools.reflect.ToolBox
|
|
import scala.util.Random
|
|
|
|
import scala.io.Source
|
|
|
|
import fmon.util._
|
|
import EffectType.Volatile
|
|
|
|
object EffectType extends Enumeration {
|
|
|
|
val NonVolatile, Volatile, AbilityEffect, MoveEffect, ItemEffect, Field, Weather = Value
|
|
|
|
def parse(s : String, default : EffectType) = s match {
|
|
case "ability" => AbilityEffect
|
|
case "item" => ItemEffect
|
|
case "move" => MoveEffect
|
|
case "status" => NonVolatile
|
|
case "volatile" => Volatile
|
|
case "weather" => Weather
|
|
case _ => default
|
|
}
|
|
}
|
|
|
|
trait Effect {
|
|
def name: String
|
|
def effectType: EffectType
|
|
|
|
def isItem = effectType == EffectType.ItemEffect
|
|
def isMove = effectType == EffectType.MoveEffect
|
|
def isAbility = effectType == EffectType.AbilityEffect
|
|
}
|
|
|
|
case class EffectSource(mon: Monster, effect: Effect) {
|
|
def isItem = effect.isItem
|
|
def isMove = effect.isMove
|
|
def isAbility = effect.isAbility
|
|
|
|
def triggerMsg = s"[${mon}'s ${effect}]"
|
|
}
|
|
|
|
|
|
class Status(template: StatusTemplate) extends Effect {
|
|
def name = template.name
|
|
// val id
|
|
def effectType = template.effectType
|
|
def onStart(mon: Monster, source: EffectSource)(implicit rng: Random) = template.onStart(this, mon, source, rng)
|
|
def onEnd(mon: Monster) = template.onEnd(this, mon)
|
|
def onModifyStat(mon: Monster, stat: Stat) = template.onModifyStat(this, mon, stat)
|
|
// val onBeforeMovePriority : Int
|
|
def onBeforeMove(mon: Monster, move: MoveTurn, target: Monster)(implicit rng: Random) = template.onBeforeMove(this, mon, move, target, rng)
|
|
// val onModifyMove
|
|
// val onHit
|
|
def onResidualOrder = template.onResidualOrder
|
|
def onResidual(mon: Monster) = template.onResidual(this, mon)
|
|
// val onSwitchIn
|
|
|
|
val intData: MutMap[String, Int] = MutMap[String, Int]()
|
|
val stringData = MutMap[String, String]()
|
|
|
|
override def toString = name
|
|
}
|
|
|
|
abstract class StatusTemplate {
|
|
val name: String
|
|
// val id
|
|
val effectType: EffectType
|
|
val onStart: (Status, Monster, EffectSource, Random) => Unit
|
|
val onEnd: (Status, Monster) => Unit
|
|
val onModifyStat: (Status, Monster, Stat) => Fraction
|
|
// val onBeforeMovePriority : Int
|
|
val onBeforeMove: (Status, Monster, MoveTurn, Monster, Random) => Boolean
|
|
// val onModifyMove
|
|
// val onHit
|
|
val onResidualOrder: Int
|
|
val onResidual: (Status, Monster) => Unit
|
|
// val onSwitchIn
|
|
|
|
def build = new Status(this)
|
|
|
|
override def toString = name
|
|
}
|
|
|
|
case class StatusToken(
|
|
val name: String,
|
|
val effectType: String,
|
|
val onStart: String,
|
|
val onEnd: String,
|
|
val onBeforeMove: String,
|
|
val onModifyStat: String,
|
|
val onResidualOrder: Int,
|
|
val onResidual: String) {
|
|
def instantiate() = {
|
|
val self = this
|
|
new StatusTemplate {
|
|
val name = self.name
|
|
val effectType = EffectType.parse(self.effectType, Volatile)
|
|
val onStart = Status.compileOnStart(self.onStart)
|
|
val onEnd = Status.compileOnEnd(self.onEnd)
|
|
val onBeforeMove = Status.compileOnBeforeMove(self.onBeforeMove)
|
|
val onModifyStat = Status.compileOnModifyStat(self.onModifyStat)
|
|
val onResidualOrder = self.onResidualOrder
|
|
val onResidual = Status.compileOnResidual(self.onResidual)
|
|
}
|
|
}
|
|
}
|
|
|
|
object Status {
|
|
private var statuses = Map[String, StatusTemplate]()
|
|
val tokens = YamlHelper.extractMap[StatusToken](Source.fromInputStream(Status.getClass.getResourceAsStream("data/statuses.yaml")))
|
|
|
|
def apply(name: String): StatusTemplate = {
|
|
if (!statuses.contains(name)) {
|
|
statuses = statuses.updated(name, tokens(name).instantiate())
|
|
}
|
|
statuses(name)
|
|
}
|
|
|
|
private val tb = runtimeMirror(getClass.getClassLoader).mkToolBox()
|
|
private val header = """
|
|
import scala.util.Random
|
|
import fmon.stat._
|
|
import fmon.stat.MoveType._
|
|
import fmon.stat.Statistic._
|
|
import fmon.util._
|
|
"""
|
|
|
|
def compileOnStart(code: String): (Status, Monster, EffectSource, Random ) => Unit = {
|
|
if (code == null) {
|
|
(_, _, _, _) => ()
|
|
} else {
|
|
val tree = tb.parse(
|
|
s"""
|
|
|$header
|
|
|def onStart(self:Status, mon: Monster, source: EffectSource, rng: Random) = {
|
|
| $code
|
|
|}
|
|
|onStart _
|
|
""".stripMargin)
|
|
val f = tb.compile(tree)
|
|
val wrapper = f()
|
|
wrapper.asInstanceOf[(Status, Monster, EffectSource, Random) => Unit]
|
|
}
|
|
}
|
|
|
|
def compileOnEnd(code: String): (Status, Monster) => Unit = {
|
|
if (code == null) {
|
|
(_, _) => ()
|
|
} else {
|
|
val tree = tb.parse(
|
|
s"""
|
|
|$header
|
|
|def onStart(self:Status, mon: Monster) = {
|
|
| $code
|
|
|}
|
|
onStart _
|
|
""".stripMargin)
|
|
val f = tb.compile(tree)
|
|
val wrapper = f()
|
|
wrapper.asInstanceOf[(Status, Monster) => Unit]
|
|
}
|
|
}
|
|
|
|
def compileOnBeforeMove(code: String): (Status, Monster, MoveTurn, Monster, Random) => Boolean = {
|
|
if (code == null) {
|
|
(_, _, _, _, _) => true
|
|
} else {
|
|
val tree = tb.parse(
|
|
s"""
|
|
$header
|
|
def onBeforeMove(self: Status, mon: Monster, move: MoveTurn, target: Monster, rng: Random): Boolean = {
|
|
$code
|
|
}
|
|
onBeforeMove _
|
|
""")
|
|
|
|
val f = tb.compile(tree)
|
|
val wrapper = f()
|
|
wrapper.asInstanceOf[(Status, Monster, MoveTurn, Monster, Random) => Boolean]
|
|
}
|
|
}
|
|
|
|
def compileOnModifyStat(code: String): (Status, Monster, Stat) => Fraction = {
|
|
if (code == null) {
|
|
(_, _, _) => 1.frac
|
|
} else {
|
|
val tree = tb.parse(
|
|
s"""
|
|
$header
|
|
def onModifyStat(self: Status, mon: Monster, stat: Stat): Fraction = {
|
|
$code
|
|
}
|
|
onModifyStat _
|
|
""")
|
|
val f = tb.compile(tree)
|
|
val wrapper = f()
|
|
wrapper.asInstanceOf[(Status, Monster, Stat) => Fraction]
|
|
}
|
|
}
|
|
|
|
def compileOnResidual(code: String): (Status, Monster) => Unit = {
|
|
if (code == null) {
|
|
(_, _) => ()
|
|
} else {
|
|
val tree = tb.parse(
|
|
s"""
|
|
|$header
|
|
|def onResidual(self: Status, mon: Monster) = {
|
|
| $code
|
|
|}
|
|
|onResidual _
|
|
""".stripMargin)
|
|
val f = tb.compile(tree)
|
|
val wrapper = f()
|
|
|
|
wrapper.asInstanceOf[(Status, Monster) => Unit]
|
|
}
|
|
}
|
|
} |