diff --git a/FakeMon/src/mon/Game.scala b/FakeMon/src/fmon/Game.scala similarity index 88% rename from FakeMon/src/mon/Game.scala rename to FakeMon/src/fmon/Game.scala index 5867021..aa61187 100644 --- a/FakeMon/src/mon/Game.scala +++ b/FakeMon/src/fmon/Game.scala @@ -1,4 +1,4 @@ -package mon +package fmon import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.dataformat.yaml.YAMLFactory @@ -7,8 +7,8 @@ import com.fasterxml.jackson.module.scala.DefaultScalaModule import scala.reflect.runtime.universe._ import scala.tools.reflect.ToolBox -import mon.battle.BattleEngine -import mon.stat._ +import fmon.battle.BattleEngine +import fmon.stat._ case class Prop(url : Seq[String]) @@ -19,8 +19,8 @@ object Game { implicit val rng = new scala.util.Random() val form1 = Form("Diabolo") val form2 = Form("Chanilla") - val movepool1 = IndexedSeq(Move("Close Combat")) - val movepool2 = IndexedSeq(Move("Absorb")) + val movepool1 = IndexedSeq(Move("Ice Beam")) + val movepool2 = IndexedSeq(Move("Scald")) val p1 = TrainerID("Jaeda", Gender.Female, 0) val p2 = TrainerID("Wild Monster", Gender.Male, 0) val party1 = new Party(p1, new MonsterPtr(new Monster(new StorageMon("Allied Mon", 500, Gene.randomGene(null, form1), form1, Statistic.emptyEvs, movepool1))), IndexedSeq()) diff --git a/FakeMon/src/mon/battle/Action.scala b/FakeMon/src/fmon/battle/Action.scala similarity index 81% rename from FakeMon/src/mon/battle/Action.scala rename to FakeMon/src/fmon/battle/Action.scala index 04281e2..ae682c1 100644 --- a/FakeMon/src/mon/battle/Action.scala +++ b/FakeMon/src/fmon/battle/Action.scala @@ -1,7 +1,7 @@ -package mon.battle +package fmon.battle -import mon.stat._ -import mon.stat.Statistic.Speed +import fmon.stat._ +import fmon.stat.Statistic.Speed case class Action(user : MonsterPtr, move : MoveTurn, target : MonsterPtr) extends Comparable[Action] { override def compareTo(other : Action) = { diff --git a/FakeMon/src/mon/battle/BattleEngine.scala b/FakeMon/src/fmon/battle/BattleEngine.scala similarity index 82% rename from FakeMon/src/mon/battle/BattleEngine.scala rename to FakeMon/src/fmon/battle/BattleEngine.scala index fa64e1f..579c16e 100644 --- a/FakeMon/src/mon/battle/BattleEngine.scala +++ b/FakeMon/src/fmon/battle/BattleEngine.scala @@ -1,10 +1,10 @@ -package mon.battle +package fmon.battle import scala.util.Random -import mon.stat._ -import mon.stat.Statistic._ -import mon.util.Fraction +import fmon.stat._ +import fmon.stat.Statistic._ +import fmon.util.Fraction class BattleEngine(val player: Party, val enemy: Party)(implicit val rng: Random) { @@ -18,13 +18,12 @@ class BattleEngine(val player: Party, val enemy: Party)(implicit val rng: Random def playTurn() = { val playerAction = player.pollAction(enemy) val enemyAction = enemy.pollAction(player) - println(enemyAction) val actions = Seq(playerAction, enemyAction) val queue = rng.shuffle(actions).sorted // Shuffle to randomize in the event of a tie queue.foreach(useMove) val eotQueue = Seq(player.lead, enemy.lead).sortBy(_(Speed)) - eotQueue.foreach(mon => mon.status.map(_.onResidual.map(_(mon)))) + eotQueue.foreach(mon => mon.status.map(_.onResidual(mon))) if (!player.lead.isAlive) { if (player.canFight) { @@ -52,7 +51,9 @@ class BattleEngine(val player: Party, val enemy: Party)(implicit val rng: Random val move = action.move val target = action.target if (user.isAlive) { - move.useMove(user, target) + if (user.status.forall(_.onBeforeMove(user, move, target, rng))) { + move.useMove(user, target) + } } } } \ No newline at end of file diff --git a/FakeMon/src/mon/battle/package.scala b/FakeMon/src/fmon/battle/package.scala similarity index 67% rename from FakeMon/src/mon/battle/package.scala rename to FakeMon/src/fmon/battle/package.scala index 6573ba2..a5081b2 100644 --- a/FakeMon/src/mon/battle/package.scala +++ b/FakeMon/src/fmon/battle/package.scala @@ -1,9 +1,9 @@ -package mon +package fmon -import scala.languageFeature.implicitConversions +import scala.language.implicitConversions import scala.util.Random -import mon.util._ +import fmon.util._ package object battle { diff --git a/FakeMon/src/mon/stat/Element.scala b/FakeMon/src/fmon/stat/Element.scala similarity index 91% rename from FakeMon/src/mon/stat/Element.scala rename to FakeMon/src/fmon/stat/Element.scala index 2907a26..edbf909 100644 --- a/FakeMon/src/mon/stat/Element.scala +++ b/FakeMon/src/fmon/stat/Element.scala @@ -1,8 +1,8 @@ -package mon.stat +package fmon.stat import scala.io.Source -import mon.util.YamlHelper +import fmon.util.YamlHelper case class Element(val name : String, val effect : Map[String, Double]) { diff --git a/FakeMon/src/mon/stat/Form.scala b/FakeMon/src/fmon/stat/Form.scala similarity index 96% rename from FakeMon/src/mon/stat/Form.scala rename to FakeMon/src/fmon/stat/Form.scala index 6c31469..a167929 100644 --- a/FakeMon/src/mon/stat/Form.scala +++ b/FakeMon/src/fmon/stat/Form.scala @@ -1,4 +1,4 @@ -package mon.stat +package fmon.stat import scala.io.Source @@ -6,7 +6,7 @@ import com.fasterxml.jackson.module.scala.JsonScalaEnumeration import Statistic._ -import mon.util.YamlHelper +import fmon.util.YamlHelper abstract class Form { val name : String diff --git a/FakeMon/src/mon/stat/Gender.scala b/FakeMon/src/fmon/stat/Gender.scala similarity index 81% rename from FakeMon/src/mon/stat/Gender.scala rename to FakeMon/src/fmon/stat/Gender.scala index 5c24e16..7abcba0 100644 --- a/FakeMon/src/mon/stat/Gender.scala +++ b/FakeMon/src/fmon/stat/Gender.scala @@ -1,4 +1,4 @@ -package mon.stat +package fmon.stat object Gender extends Enumeration { val Male, Female, Fluid, Neuter = Value diff --git a/FakeMon/src/mon/stat/Gene.scala b/FakeMon/src/fmon/stat/Gene.scala similarity index 95% rename from FakeMon/src/mon/stat/Gene.scala rename to FakeMon/src/fmon/stat/Gene.scala index df7fbe1..deb01e8 100644 --- a/FakeMon/src/mon/stat/Gene.scala +++ b/FakeMon/src/fmon/stat/Gene.scala @@ -1,4 +1,4 @@ -package mon.stat +package fmon.stat import scala.util.Random diff --git a/FakeMon/src/mon/stat/Monster.scala b/FakeMon/src/fmon/stat/Monster.scala similarity index 88% rename from FakeMon/src/mon/stat/Monster.scala rename to FakeMon/src/fmon/stat/Monster.scala index 4b5155d..089a8cd 100644 --- a/FakeMon/src/mon/stat/Monster.scala +++ b/FakeMon/src/fmon/stat/Monster.scala @@ -1,8 +1,8 @@ -package mon.stat +package fmon.stat import scala.util._ -import mon.util.Fraction +import fmon.util._ import Monster._ import Statistic._ @@ -20,7 +20,7 @@ class Monster(val base : StorageMon) { def apply(s : Stat) = { val mod = boosts.getOrElse(s, 0) val mult = if (mod > 0) Fraction(2 + mod, 2) else Fraction(2, 2 - mod) - mult * stats(s) + status.foldLeft(1.frac)((m, sts) => m * sts.onModifyStat(this, s)) * mult * stats(s) } def elements = base.form.elements @@ -36,6 +36,11 @@ class Monster(val base : StorageMon) { hp = Math.min(stats(Hp), hp + healing) } + def cureStatus() { + status.map(_.onEnd(this)) + status = None + } + def applyBoost(s : Stat, boost : Int) { val modified = boosts.getOrElse(s, 0) + boost boosts = boosts.updated(s, Math.min(MaxBoost, Math.max(-MaxBoost, modified))) diff --git a/FakeMon/src/mon/stat/MonsterPtr.scala b/FakeMon/src/fmon/stat/MonsterPtr.scala similarity index 83% rename from FakeMon/src/mon/stat/MonsterPtr.scala rename to FakeMon/src/fmon/stat/MonsterPtr.scala index ca81d34..c555429 100644 --- a/FakeMon/src/mon/stat/MonsterPtr.scala +++ b/FakeMon/src/fmon/stat/MonsterPtr.scala @@ -1,4 +1,4 @@ -package mon.stat +package fmon.stat class MonsterPtr(var mon : Monster) { diff --git a/FakeMon/src/mon/stat/Move.scala b/FakeMon/src/fmon/stat/Move.scala similarity index 95% rename from FakeMon/src/mon/stat/Move.scala rename to FakeMon/src/fmon/stat/Move.scala index e0fd421..bc3493e 100644 --- a/FakeMon/src/mon/stat/Move.scala +++ b/FakeMon/src/fmon/stat/Move.scala @@ -1,4 +1,4 @@ -package mon.stat +package fmon.stat import scala.reflect.runtime.universe._ import scala.tools.reflect.ToolBox @@ -9,7 +9,7 @@ import scala.io.Source import scala.util.Random import Statistic._ -import mon.util._ +import fmon.util._ object MoveType extends Enumeration { val Physical, Special, Status = Value @@ -23,6 +23,7 @@ class TargetType extends TypeReference[Target.type] trait MoveTurn { def name: String + def flags: Set[String] def prior: Int def target: Target def useMove(user: Monster, target: Monster)(implicit rng: Random): Unit @@ -30,6 +31,7 @@ trait MoveTurn { class SwitchOut(val party: Party, val replacement: Monster) extends MoveTurn { def name = "Swap" + def flags = Set() def prior = +6 def target = Target.Self @@ -134,14 +136,14 @@ abstract class Move extends MoveTurn { println("It's not very effective.") } val maxDmg = (baseDmg * multiplier).toInt - val minDmg = (17 \ 20) * maxDmg + val minDmg = (17 \\ 20) * maxDmg rng.nextInt(minDmg, maxDmg) } def critMultiplier(user: Monster, target: Monster)(implicit rng: Random) = { // Percentage chance is different from Pokemon val stage = crit - val chance = (1 << stage) \ 16 // Doubles per stage + val chance = (1 << stage) \\ 16 // Doubles per stage if (rng.chance(chance)) { println("A critical hit!") 1.5 @@ -156,11 +158,13 @@ abstract class Move extends MoveTurn { } def applyStatus(target: Monster, status: Status) { - if (target.isAlive) { - if (status != null && target.status == None) { + if (target.isAlive && status != null) { + if (target.status == None) { // apply status target.status = Some(status) - status.onStart.map(_(target)) + status.onStart(target) + } else { + println("But it failed!") } } } @@ -222,7 +226,7 @@ case class MoveToken( val boosts = if (token.boosts != null) token.boosts.map { case (s, i) => (Statistic(s), i) } else Map() val crit = token.critRatio val status = if (token.status != null) Status(token.status) else null - val drain = if (token.drain != null) token.drain else if (token.recoil != null) -token.recoil else 0 \ 1 + val drain = if (token.drain != null) token.drain else if (token.recoil != null) -token.recoil else 0.frac val selfEffect = if (token.self != null) token.self.instantiate() else null val secondary = if (token.secondary != null) token.secondary.instantiate() else null } diff --git a/FakeMon/src/mon/stat/Nature.scala b/FakeMon/src/fmon/stat/Nature.scala similarity index 98% rename from FakeMon/src/mon/stat/Nature.scala rename to FakeMon/src/fmon/stat/Nature.scala index b71b3e0..0c12690 100644 --- a/FakeMon/src/mon/stat/Nature.scala +++ b/FakeMon/src/fmon/stat/Nature.scala @@ -1,4 +1,4 @@ -package mon.stat +package fmon.stat import scala.util.Random diff --git a/FakeMon/src/mon/stat/Party.scala b/FakeMon/src/fmon/stat/Party.scala similarity index 93% rename from FakeMon/src/mon/stat/Party.scala rename to FakeMon/src/fmon/stat/Party.scala index 6196d82..6bd1911 100644 --- a/FakeMon/src/mon/stat/Party.scala +++ b/FakeMon/src/fmon/stat/Party.scala @@ -1,9 +1,9 @@ -package mon.stat +package fmon.stat import scala.util.Random -import mon.battle.Action -import mon.stat.Target._ +import fmon.battle.Action +import fmon.stat.Target._ class Party(val trainer: TrainerID, val lead: MonsterPtr, var sideboard: IndexedSeq[Monster]) { def pollAction(them: Party)(implicit rng: Random): Action = { @@ -38,7 +38,7 @@ class Party(val trainer: TrainerID, val lead: MonsterPtr, var sideboard: Indexed } def shouldSwitch(them: Party)(implicit rng: Random): Boolean = { - true + false } def canFight: Boolean = { diff --git a/FakeMon/src/mon/stat/Secondary.scala b/FakeMon/src/fmon/stat/Secondary.scala similarity index 97% rename from FakeMon/src/mon/stat/Secondary.scala rename to FakeMon/src/fmon/stat/Secondary.scala index 1d92b0c..4a1f212 100644 --- a/FakeMon/src/mon/stat/Secondary.scala +++ b/FakeMon/src/fmon/stat/Secondary.scala @@ -1,4 +1,4 @@ -package mon.stat +package fmon.stat abstract class Secondary { val chance : Int diff --git a/FakeMon/src/mon/stat/Species.scala b/FakeMon/src/fmon/stat/Species.scala similarity index 89% rename from FakeMon/src/mon/stat/Species.scala rename to FakeMon/src/fmon/stat/Species.scala index 96ed9bf..39e8788 100644 --- a/FakeMon/src/mon/stat/Species.scala +++ b/FakeMon/src/fmon/stat/Species.scala @@ -1,4 +1,4 @@ -package mon.stat +package fmon.stat class Species { // name diff --git a/FakeMon/src/mon/stat/Statistic.scala b/FakeMon/src/fmon/stat/Statistic.scala similarity index 97% rename from FakeMon/src/mon/stat/Statistic.scala rename to FakeMon/src/fmon/stat/Statistic.scala index 4b57a01..69da86a 100644 --- a/FakeMon/src/mon/stat/Statistic.scala +++ b/FakeMon/src/fmon/stat/Statistic.scala @@ -1,4 +1,4 @@ -package mon.stat +package fmon.stat object Statistic extends Enumeration { val Hp = Value("Hp") diff --git a/FakeMon/src/fmon/stat/Status.scala b/FakeMon/src/fmon/stat/Status.scala new file mode 100644 index 0000000..b4002f6 --- /dev/null +++ b/FakeMon/src/fmon/stat/Status.scala @@ -0,0 +1,142 @@ +package fmon.stat + +import scala.reflect.runtime.universe._ +import scala.tools.reflect.ToolBox +import scala.util.Random + +import scala.io.Source + +import fmon.util._ + +abstract class Status { + val name: String + // val id + // val effectType + val onStart: Monster => Unit + val onEnd: Monster => Unit + val onModifyStat: (Monster, Stat) => Fraction + // val onBeforeMovePriority : Int + val onBeforeMove: (Monster, MoveTurn, Monster, Random) => Boolean + // val onModifyMove + // val onHit + val onResidualOrder: Int + val onResidual: Monster => Unit + // val onSwitchIn + + override def toString = name +} + +case class StatusToken( + val name: 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 Status { + val name = self.name + val onStart = Status.compileOnStart(self.onStart) + val onEnd = Status.compileOnStart(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, Status]() + val tokens = YamlHelper.extractSeq[StatusToken](Source.fromInputStream(Move.getClass.getResourceAsStream("data/statuses.yaml"))).map(t => (t.name, t)).toMap + + def apply(name: String) = { + if (!statuses.contains(name)) { + statuses = statuses.updated(name, tokens(name).instantiate()) + } + statuses(name) + } + + private val tb = runtimeMirror(getClass.getClassLoader).mkToolBox() + + def compileOnStart(code: String): (Monster /*, source, source effect */ ) => Unit = { + if (code == null) { + _ => () + } else { + val tree = tb.parse( + s""" + |import fmon.stat._ + |import fmon.stat.Statistic._ + |def onStart(mon : Monster) = { + | $code + |} + |onStart _ + """.stripMargin) + val f = tb.compile(tree) + val wrapper = f() + wrapper.asInstanceOf[Monster => Unit] + } + } + + def compileOnBeforeMove(code: String): (Monster, MoveTurn, Monster, Random) => Boolean = { + if (code == null) { + (_, _, _, _) => true + } else { + val tree = tb.parse( + s""" + import scala.util.Random + import fmon.stat._ + import fmon.stat.Statistic._ + def onBeforeMove(mon: Monster, move: MoveTurn, target: Monster, rng: Random): Boolean = { + $code + } + onBeforeMove _ + """) + val f = tb.compile(tree) + val wrapper = f() + wrapper.asInstanceOf[(Monster, MoveTurn, Monster, Random) => Boolean] + } + } + + def compileOnModifyStat(code: String): (Monster, Stat) => Fraction = { + if (code == null) { + (_, _) => 1.frac + } else { + val tree = tb.parse( + s""" + import fmon.stat._ + import fmon.stat.Statistic._ + import fmon.util._ + def onModifyStat(mon: Monster, stat: Stat): Fraction = { + $code + } + onModifyStat _ + """) + val f = tb.compile(tree) + val wrapper = f() + wrapper.asInstanceOf[(Monster, Stat) => Fraction] + } + } + + def compileOnResidual(code: String): Monster => Unit = { + if (code == null) { + _ => () + } else { + val tree = tb.parse( + s""" + |import fmon.stat._ + |import fmon.stat.Statistic._ + |def onResidual(mon : Monster) = { + | $code + |} + |onResidual _ + """.stripMargin) + val f = tb.compile(tree) + val wrapper = f() + + wrapper.asInstanceOf[Monster => Unit] + } + } +} \ No newline at end of file diff --git a/FakeMon/src/mon/stat/StorageMon.scala b/FakeMon/src/fmon/stat/StorageMon.scala similarity index 90% rename from FakeMon/src/mon/stat/StorageMon.scala rename to FakeMon/src/fmon/stat/StorageMon.scala index ad35a7f..4993173 100644 --- a/FakeMon/src/mon/stat/StorageMon.scala +++ b/FakeMon/src/fmon/stat/StorageMon.scala @@ -1,4 +1,4 @@ -package mon.stat +package fmon.stat class StorageMon(val nickname : String, val xp: Int, val gene : Gene, val form : Form, val evs : Map[Stat, Int], val moves : IndexedSeq[Move]) { def level = form.xpCurve(xp) diff --git a/FakeMon/src/mon/stat/TrainerID.scala b/FakeMon/src/fmon/stat/TrainerID.scala similarity index 86% rename from FakeMon/src/mon/stat/TrainerID.scala rename to FakeMon/src/fmon/stat/TrainerID.scala index e0349a0..eda9dbd 100644 --- a/FakeMon/src/mon/stat/TrainerID.scala +++ b/FakeMon/src/fmon/stat/TrainerID.scala @@ -1,4 +1,4 @@ -package mon.stat +package fmon.stat case class TrainerID(name : String, gender : Gender, id : Long) { diff --git a/FakeMon/src/mon/stat/XpCurve.scala b/FakeMon/src/fmon/stat/XpCurve.scala similarity index 89% rename from FakeMon/src/mon/stat/XpCurve.scala rename to FakeMon/src/fmon/stat/XpCurve.scala index 4056107..06e9b9c 100644 --- a/FakeMon/src/mon/stat/XpCurve.scala +++ b/FakeMon/src/fmon/stat/XpCurve.scala @@ -1,6 +1,6 @@ -package mon.stat +package fmon.stat -import mon.util.TypeReference +import fmon.util.TypeReference object XpCurve extends Enumeration { case class Val protected(val curve: Int => Int) extends super.Val { diff --git a/FakeMon/src/mon/stat/data/elements.yaml b/FakeMon/src/fmon/stat/data/elements.yaml similarity index 100% rename from FakeMon/src/mon/stat/data/elements.yaml rename to FakeMon/src/fmon/stat/data/elements.yaml diff --git a/FakeMon/src/mon/stat/data/forms.yaml b/FakeMon/src/fmon/stat/data/forms.yaml similarity index 96% rename from FakeMon/src/mon/stat/data/forms.yaml rename to FakeMon/src/fmon/stat/data/forms.yaml index 8ea233a..f8e5fab 100644 --- a/FakeMon/src/mon/stat/data/forms.yaml +++ b/FakeMon/src/fmon/stat/data/forms.yaml @@ -8,7 +8,7 @@ pdef: 70 matk: 70 mdef: 70 - spd: 60 + spd: 75 xpCurve: MediumSlow - name: Diabolo diff --git a/FakeMon/src/mon/stat/data/moves.yaml b/FakeMon/src/fmon/stat/data/moves.yaml similarity index 77% rename from FakeMon/src/mon/stat/data/moves.yaml rename to FakeMon/src/fmon/stat/data/moves.yaml index 7de25df..a8d2fcc 100644 --- a/FakeMon/src/mon/stat/data/moves.yaml +++ b/FakeMon/src/fmon/stat/data/moves.yaml @@ -164,6 +164,28 @@ type: "Ice" zMovePower: 120 contestType: "Beautiful" + +- name: Ice Beam + accuracy: 100 + basePower: 90 + category: Special + contestType: Beautiful + desc: Has a 10% chance to freeze the target. + flags: + mirror: 1 + protect: 1 + id: icebeam + isViable: true + num: 58 + pp: 10 + priority: 0 + secondary: + chance: 10 + status: frz + shortDesc: 10% chance to freeze the target. + target: Normal + type: Ice + zMovePower: 175 - name: "Poison Gas" num: 139 @@ -207,6 +229,30 @@ type: "Poison" zMovePower: 100 contestType: "Clever" + +- name: Scald + accuracy: 100 + basePower: 80 + category: Special + contestType: Tough + desc: Has a 30% chance to burn the target. The target thaws out if it is frozen. + flags: + defrost: 1 + mirror: 1 + protect: 1 + thaws: 1 + id: scald + isViable: true + num: 503 + pp: 15 + priority: 0 + secondary: + chance: 30 + status: brn + shortDesc: 30% chance to burn the target. Thaws target. + target: Normal + type: Water + zMovePower: 160 - name: "Snarl" num: 555 @@ -251,6 +297,30 @@ zMovePower: 100 contestType: Tough +- name: Thunder Wave + accuracy: 90 + basePower: 0 + category: Status + contestType: Cool + desc: Paralyzes the target. This move does not ignore type immunity. + flags: + mirror: 1 + protect: 1 + reflectable: 1 + id: thunderwave + ignoreImmunity: false + isViable: true + num: 86 + pp: 20 + priority: 0 + secondary: null + shortDesc: Paralyzes the target. + status: par + target: Normal + type: Electric + zMoveBoost: + MDef: 1 + - name: "Volt Tackle" num: 344 accuracy: 100 @@ -265,9 +335,32 @@ flags: {contact: 1, protect: 1, mirror: 1} recoil: {num: 33, denom: 100} secondary: - chance: 10 - xstatus: 'par' + chance: 100 + status: 'par' target: "Normal" type: "Electric" zMovePower: 190 contestType: "Cool" + +- name: Will-O-Wisp + accuracy: 85 + basePower: 0 + category: Status + contestType: Beautiful + desc: Burns the target. + flags: + mirror: 1 + protect: 1 + reflectable: 1 + id: willowisp + isViable: true + num: 261 + pp: 15 + priority: 0 + secondary: null + shortDesc: Burns the target. + status: brn + target: Normal + type: Fire + zMoveBoost: + PAtk: 1 diff --git a/FakeMon/src/mon/stat/data/statuses.yaml b/FakeMon/src/fmon/stat/data/statuses.yaml similarity index 64% rename from FakeMon/src/mon/stat/data/statuses.yaml rename to FakeMon/src/fmon/stat/data/statuses.yaml index 77c1485..f58eacc 100644 --- a/FakeMon/src/mon/stat/data/statuses.yaml +++ b/FakeMon/src/fmon/stat/data/statuses.yaml @@ -2,38 +2,57 @@ id: 'brn' num: 0 effectType: 'Status' - onStart: | - if (sourceEffect && sourceEffect.id === 'flameorb') { - this.add('-status', target, 'brn', '[from] item: Flame Orb'); - } else if (sourceEffect && sourceEffect.effectType === 'Ability') { - this.add('-status', target, 'brn', '[from] ability: ' + sourceEffect.name, '[of] ' + source); + onModifyStat: | + if (stat == PAtk) { + 1 \\ 2 } else { - this.add('-status', target, 'brn'); + 1.frac } - // Damage reduction is handled directly in the sim/battle.js damage function + onStart: | + println(s"${mon} was burned!") + /* + if (sourceEffect && sourceEffect.id === 'flameorb') { + target.status = Status('brn', '[from] 'item': Flame Orb'); + } else if (sourceEffect && sourceEffect.effectType === 'Ability') { + target.status = Status('brn', '[from] 'ability': ' + sourceEffect.name, '[of] ' + source); + } else { + target.status = Status('brn'); + }*/ + onEnd: | + println(s"${mon} was healed of its burn.") onResidualOrder: 9 onResidual: | - this.damage(pokemon.maxhp / 16); + mon.takeDamage(mon(Hp) / 16); + println(s"${mon} was hurt by its burn!") - name: 'par' id: 'par' num: 0 effectType: 'Status' onStart: | + println(s"${mon} was paralyzed!") + /* if (sourceEffect && sourceEffect.effectType === 'Ability') { this.add('-status', target, 'par', '[from] ability: ' + sourceEffect.name, '[of] ' + source); } else { this.add('-status', target, 'par'); } - onModifySpe: | - if (!pokemon.hasAbility('quickfeet')) { - return this.chainModify(0.5); + */ + onEnd: | + println(s"${mon} is no longer paralyzed!") + onModifyStat: | + if (stat == Speed /* && !mon.hasAbility('quickfeet') */) { + 1 \\ 2 + } else { + 1.frac } onBeforeMovePriority: 1 onBeforeMove: | - if (this.randomChance(1, 4)) { - this.add('cant', pokemon, 'par'); - return false; + if (rng.chance(1, 4)) { + println(s"${mon} is fully paralyzed!") + false + } else { + true } - name: 'slp' @@ -51,52 +70,62 @@ // 1-3 turns this.effectData.startTime = this.random(2, 5); this.effectData.time = this.effectData.startTime; + onEnd: | + println(s"${mon} woke up!") onBeforeMovePriority: 10 onBeforeMove: | + /* if (pokemon.hasAbility('earlybird')) { pokemon.statusData.time--; } + */ pokemon.statusData.time--; if (pokemon.statusData.time <= 0) { pokemon.cureStatus(); return; } + /* this.add('cant', pokemon, 'slp'); if (move.sleepUsable) { return; } + */ return false; - name: 'frz' - id: 'frz' + effectType: Status + id: frz num: 0 - effectType: 'Status' - onStart: | - if (sourceEffect && sourceEffect.effectType === 'Ability') { - this.add('-status', target, 'frz', '[from] ability: ' + sourceEffect.name, '[of] ' + source); + onBeforeMove: |- + if (move.flags("defrost") || rng.chance(1, 5)) { + mon.cureStatus() + true } else { - this.add('-status', target, 'frz'); - } - if (target.template.species === 'Shaymin-Sky' && target.baseTemplate.baseSpecies === 'Shaymin') { - target.formeChange('Shaymin', this.effect, true); + println(s"${mon} is completely frozen!") + false } onBeforeMovePriority: 10 - onBeforeMove: | - if (move.flags['defrost']) return; - if (this.randomChance(1, 5)) { - pokemon.cureStatus(); - return; + onHit: |- + if (move.flags("thaws") || move.element === 'Fire' && move.category !== MoveType.Status) { + target.cureStatus() } - this.add('cant', pokemon, 'frz'); - return false; + onStart: |- + println(s"${mon} was frozen solid!") + /* + if (sourceEffect && sourceEffect.effectType === 'Ability') { + target.status = Status('frz', '[from] 'ability': ' + sourceEffect.name, '[of] ' + source); + } else { + target.status = Status('frz'); + } + if (target.template.species === 'Shaymin-Sky' && target.baseTemplate.baseSpecies === 'Shaymin') { + target.formeChange('Shaymin', this.effect, true); + } + */ + onEnd: |- + println(s"${mon} thawed out.") onModifyMove: | - if (move.flags['defrost']) { - this.add('-curestatus', pokemon, 'frz', '[from] move: ' + move); - pokemon.setStatus(''); - } - onHit: | - if (move.thawsTarget || move.type === 'Fire' && move.category !== 'Status') { - target.cureStatus(); + if (move.flags("defrost")) { + mon.cureStatus() } - name: 'psn' @@ -112,6 +141,8 @@ this.add('-status', target, 'psn'); } */ + oneEnd: | + println(s"${mon} was cured of its poison.") onResidualOrder: 9 onResidual: | mon.takeDamage(mon(Hp) / 8); diff --git a/FakeMon/src/mon/stat/package.scala b/FakeMon/src/fmon/stat/package.scala similarity index 87% rename from FakeMon/src/mon/stat/package.scala rename to FakeMon/src/fmon/stat/package.scala index 88fe6a0..20c40aa 100644 --- a/FakeMon/src/mon/stat/package.scala +++ b/FakeMon/src/fmon/stat/package.scala @@ -1,11 +1,13 @@ -package mon +package fmon + +import scala.language.implicitConversions import org.json4s.DefaultFormats import org.json4s.ext.EnumNameSerializer import scala.util.Random -import mon.util.Dice +import fmon.util.Dice package object stat { type Stat = Statistic.Value diff --git a/FakeMon/src/mon/util/Dice.scala b/FakeMon/src/fmon/util/Dice.scala similarity index 57% rename from FakeMon/src/mon/util/Dice.scala rename to FakeMon/src/fmon/util/Dice.scala index 58391ca..ae84a84 100644 --- a/FakeMon/src/mon/util/Dice.scala +++ b/FakeMon/src/fmon/util/Dice.scala @@ -1,4 +1,4 @@ -package mon.util +package fmon.util import scala.util.Random @@ -7,5 +7,6 @@ class Dice(val rng : Random) extends AnyVal { def pick[T](seq : IndexedSeq[T]) : T = seq(rng.nextInt(seq.size)) - def chance(frac : Fraction) = rng.nextInt(frac.denom) < frac.num + def chance(frac : Fraction) :Boolean = chance(frac.num, frac.denom) + def chance(num : Int, denom : Int) : Boolean = rng.nextInt(denom) < num } \ No newline at end of file diff --git a/FakeMon/src/mon/util/Fraction.scala b/FakeMon/src/fmon/util/Fraction.scala similarity index 87% rename from FakeMon/src/mon/util/Fraction.scala rename to FakeMon/src/fmon/util/Fraction.scala index 315b8d3..e0c22c9 100644 --- a/FakeMon/src/mon/util/Fraction.scala +++ b/FakeMon/src/fmon/util/Fraction.scala @@ -1,4 +1,4 @@ -package mon.util +package fmon.util case class Fraction(val num : Int, val denom : Int) extends Ordered[Fraction] { def *(f : Fraction) = Fraction(num * f.num, denom * f.denom) @@ -13,6 +13,6 @@ case class Fraction(val num : Int, val denom : Int) extends Ordered[Fraction] { class IntFraction(val x : Int) extends AnyVal { def %% = Fraction(x, 100) - def \ (denom : Int) = Fraction(x, denom) + def \\ (denom : Int) = Fraction(x, denom) def frac = Fraction(x, 1) } \ No newline at end of file diff --git a/FakeMon/src/mon/util/JsonHelper.scala b/FakeMon/src/fmon/util/JsonHelper.scala similarity index 95% rename from FakeMon/src/mon/util/JsonHelper.scala rename to FakeMon/src/fmon/util/JsonHelper.scala index 1f823ea..1bb716c 100644 --- a/FakeMon/src/mon/util/JsonHelper.scala +++ b/FakeMon/src/fmon/util/JsonHelper.scala @@ -1,4 +1,4 @@ -package mon.util +package fmon.util import org.json4s._ import org.json4s.jackson.JsonMethods._ @@ -12,7 +12,7 @@ object JsonHelper { // Maybe Look at Jackson-YAML & Jackson-Scala - implicit val formats = mon.stat.formats + implicit val formats = fmon.stat.formats def extract[T](text : String)(implicit mf : Manifest[T]) : T = { val json = parse(text) diff --git a/FakeMon/src/mon/util/YamlHelper.scala b/FakeMon/src/fmon/util/YamlHelper.scala similarity index 97% rename from FakeMon/src/mon/util/YamlHelper.scala rename to FakeMon/src/fmon/util/YamlHelper.scala index 83d2187..4cee02c 100644 --- a/FakeMon/src/mon/util/YamlHelper.scala +++ b/FakeMon/src/fmon/util/YamlHelper.scala @@ -1,4 +1,4 @@ -package mon.util +package fmon.util import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.databind.ObjectMapper @@ -10,7 +10,7 @@ import java.io.InputStream import scala.io.Source -import mon.util._ +import fmon.util._ object YamlHelper { val mapper = new ObjectMapper(new YAMLFactory()) with ScalaObjectMapper diff --git a/FakeMon/src/mon/util/package.scala b/FakeMon/src/fmon/util/package.scala similarity index 98% rename from FakeMon/src/mon/util/package.scala rename to FakeMon/src/fmon/util/package.scala index a0284a6..ddf6cd9 100644 --- a/FakeMon/src/mon/util/package.scala +++ b/FakeMon/src/fmon/util/package.scala @@ -1,4 +1,4 @@ -package mon +package fmon import java.io._ diff --git a/FakeMon/src/mon/stat/Status.scala b/FakeMon/src/mon/stat/Status.scala deleted file mode 100644 index dbea548..0000000 --- a/FakeMon/src/mon/stat/Status.scala +++ /dev/null @@ -1,96 +0,0 @@ -package mon.stat - -import scala.reflect.runtime.universe._ -import scala.tools.reflect.ToolBox - -import scala.io.Source - -import mon.util.YamlHelper - -abstract class Status { - val name : String - // val id - // val effectType - val onStart : Option[Monster => Unit] - // val onModifyStat - // val onBeforeMovePriority : Int - // val onBeforeMove - // val onModifyMove - // val onHit - val onResidualOrder : Int - val onResidual : Option[Monster => Unit] - // val onSwitchIn - - override def toString = name -} - -case class StatusToken( - val name : String, - val onStart : String, - val onResidualOrder : Int, - val onResidual : String - ) { - def instantiate() = { - val self = this - new Status{ - val name = self.name - val onStart = Status.compileOnStart(self.onStart) - val onResidualOrder = self.onResidualOrder - val onResidual = Status.compileOnResidual(self.onResidual) - } - } -} - -object Status { - private var statuses = Map[String, Status]() - val tokens = YamlHelper.extractSeq[StatusToken](Source.fromInputStream(Move.getClass.getResourceAsStream("data/statuses.yaml"))).map(t => (t.name, t)).toMap - - def apply(name : String) = { - if (!statuses.contains(name)) { - statuses = statuses.updated(name, tokens(name).instantiate()) - } - statuses(name) - } - - private val tb = runtimeMirror(getClass.getClassLoader).mkToolBox() - - def compileOnStart(code : String) : Option[(Monster /*, source, source effect */) => Unit] = { - if (code == null) { - None - } else { - val tree = tb.parse( - s""" - |import mon.stat.Monster - |import mon.stat.Statistic._ - |def onStart(mon : Monster) = { - | $code - |} - |onStart _ - """.stripMargin) - val f = tb.compile(tree) - val wrapper = f() - - Some(wrapper.asInstanceOf[Monster => Unit]) - } - } - - def compileOnResidual(code : String) : Option[Monster => Unit] = { - if (code == null) { - None - } else { - val tree = tb.parse( - s""" - |import mon.stat.Monster - |import mon.stat.Statistic._ - |def onResidual(mon : Monster) = { - | $code - |} - |onResidual _ - """.stripMargin) - val f = tb.compile(tree) - val wrapper = f() - - Some(wrapper.asInstanceOf[Monster => Unit]) - } - } -} \ No newline at end of file