Moved forced skills into creature
This commit is contained in:
		@@ -1,12 +1,10 @@
 | 
			
		||||
package me.msoucy.ptures.controller
 | 
			
		||||
 | 
			
		||||
import me.msoucy.ptures.model.Creature
 | 
			
		||||
import me.msoucy.ptures.model.KnockedOut
 | 
			
		||||
import me.msoucy.ptures.model.Skill
 | 
			
		||||
import me.msoucy.ptures.model.*
 | 
			
		||||
import me.msoucy.ptures.model.Target
 | 
			
		||||
import me.msoucy.ptures.model.Team
 | 
			
		||||
import me.msoucy.ptures.view.BattleView
 | 
			
		||||
import me.msoucy.ptures.view.SkillChoice
 | 
			
		||||
import me.msoucy.ptures.view.CreatureView
 | 
			
		||||
import me.msoucy.ptures.model.SkillChoice
 | 
			
		||||
 | 
			
		||||
sealed class BattleType(vararg val teams: Team) {
 | 
			
		||||
    init {
 | 
			
		||||
@@ -33,16 +31,19 @@ class RaidBattle(val boss: Creature, vararg teams: Team) : BattleType(*teams) {
 | 
			
		||||
 | 
			
		||||
class Engine(private val battle: BattleType) {
 | 
			
		||||
 | 
			
		||||
    private var currentCreature = 0
 | 
			
		||||
    private lateinit var currentCreature: CreatureView
 | 
			
		||||
 | 
			
		||||
    // List of all creatures that are involved in the battle
 | 
			
		||||
    private val creatures get() = battle.teams.flatMap { it.activeCreatures }
 | 
			
		||||
 | 
			
		||||
    val attacker: Creature
 | 
			
		||||
    // The current attacking creature
 | 
			
		||||
    private var attacker: CreatureView
 | 
			
		||||
        get() {
 | 
			
		||||
            return creatures[currentCreature].creature
 | 
			
		||||
            return currentCreature
 | 
			
		||||
        }
 | 
			
		||||
        private set(value) {
 | 
			
		||||
            currentCreature = value
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    private val forcedSkills = mutableMapOf<Creature, Skill>()
 | 
			
		||||
 | 
			
		||||
    private val activeCreatures
 | 
			
		||||
        get() = creatures
 | 
			
		||||
@@ -50,70 +51,54 @@ class Engine(private val battle: BattleType) {
 | 
			
		||||
                .sortedBy { it.creature.spd }
 | 
			
		||||
 | 
			
		||||
    fun resolveTurn(view: BattleView) {
 | 
			
		||||
        forcedSkills.clear()
 | 
			
		||||
 | 
			
		||||
        // All preconditions
 | 
			
		||||
        for (i in activeCreatures.indices) {
 | 
			
		||||
            val creature = creatures[i]
 | 
			
		||||
        for (creature in activeCreatures) {
 | 
			
		||||
            for (status in creature.creature.statuses) {
 | 
			
		||||
                status.onTurnStart(this, creature.creature)
 | 
			
		||||
                status.onTurnStart(creature.creature)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Get the moves each creature will use this turn
 | 
			
		||||
        val moves = activeCreatures.indices.map { i ->
 | 
			
		||||
            val forcedSkill = forcedSkills[creatures[i].creature]
 | 
			
		||||
            if (forcedSkill != null) {
 | 
			
		||||
                SkillChoice(forcedSkill, creatures[nextOpponent(i)].creature)
 | 
			
		||||
            } else {
 | 
			
		||||
                creatures[i].chooseSkill(activeCreatures.map { it.creature })
 | 
			
		||||
            }
 | 
			
		||||
        activeCreatures.forEach {
 | 
			
		||||
            it.chooseSkill(activeCreatures.map { c -> c.creature })
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Resolve each move
 | 
			
		||||
        for (i in activeCreatures.indices) {
 | 
			
		||||
        for (c in activeCreatures) {
 | 
			
		||||
            // Resolve move
 | 
			
		||||
            val (skill, target) = moves[i]
 | 
			
		||||
            currentCreature = i
 | 
			
		||||
            val (skill, targets) = c.creature.activeSkill!!
 | 
			
		||||
            currentCreature = c
 | 
			
		||||
            val attackingCreature = currentCreature
 | 
			
		||||
            for (step in skill.damageSteps) {
 | 
			
		||||
                for (targetCreature in getTargetList(step.target, target)) {
 | 
			
		||||
                    if (attacker.hits(targetCreature, step)) {
 | 
			
		||||
                        targetCreature.apply(step, attacker)
 | 
			
		||||
                for (targetCreature in targets) {
 | 
			
		||||
                    if (attackingCreature.creature.hits(targetCreature, step)) {
 | 
			
		||||
                        targetCreature.apply(step, attackingCreature.creature)
 | 
			
		||||
                        step.applyStatus(targetCreature)
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            for (step in skill.postSteps) {
 | 
			
		||||
                for (targetCreature in getTargetList(step.target, target)) {
 | 
			
		||||
                for (targetCreature in targets) {
 | 
			
		||||
                    step.apply(targetCreature)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // All post conditions
 | 
			
		||||
        for (creatureView in activeCreatures) {
 | 
			
		||||
            val creature = creatureView.creature
 | 
			
		||||
            for (status in creature.statuses) {
 | 
			
		||||
                status.onTurnEnd(this)
 | 
			
		||||
                status.onTurnEnd(creature)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun getTargetList(target: Target, selected: Creature): List<Creature> {
 | 
			
		||||
        return when (target) {
 | 
			
		||||
            Target.Self -> listOf(attacker)
 | 
			
		||||
            Target.Selected -> listOf(selected)
 | 
			
		||||
            Target.Others -> creatures.filter { it.creature != attacker }.map { it.creature }
 | 
			
		||||
            Target.Opponents -> creatures.filter { it.playerId != creatures[currentCreature].playerId }.map { it.creature }
 | 
			
		||||
            Target.All -> creatures.map { it.creature }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun nextOpponent(idx: Int): Int {
 | 
			
		||||
        var nextIdx = idx + 1
 | 
			
		||||
        while (nextIdx != idx) {
 | 
			
		||||
            if (creatures[nextIdx].playerId != creatures[idx].playerId) {
 | 
			
		||||
                return nextIdx
 | 
			
		||||
            }
 | 
			
		||||
            nextIdx = (nextIdx + 1) % creatures.size
 | 
			
		||||
        }
 | 
			
		||||
        // There are no opponents... so use the "none" index
 | 
			
		||||
        return -1
 | 
			
		||||
    private fun getTargetList(target: Target, selected: Creature): List<Creature> = when (target) {
 | 
			
		||||
        Target.Self -> listOf(attacker.creature)
 | 
			
		||||
        Target.Selected -> listOf(selected)
 | 
			
		||||
        Target.Others -> creatures.filter { it.creature != attacker.creature }.map { it.creature }
 | 
			
		||||
        Target.Opponents -> creatures.filter { it.playerId != attacker.playerId }.map { it.creature }
 | 
			
		||||
        Target.All -> creatures.map { it.creature }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -15,6 +15,8 @@ class Creature {
 | 
			
		||||
    val skills = mutableListOf<Skill>()
 | 
			
		||||
    val statuses = mutableListOf<Status>()
 | 
			
		||||
 | 
			
		||||
    var activeSkill : SkillChoice? = null
 | 
			
		||||
 | 
			
		||||
    val atk : Int get() = statFormula(genes.atk, growth.atk)
 | 
			
		||||
    val def : Int get() = statFormula(genes.def, growth.def)
 | 
			
		||||
    val spd : Int get() = statFormula(genes.spd, growth.spd)
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,8 @@ package me.msoucy.ptures.model
 | 
			
		||||
 | 
			
		||||
import com.badlogic.gdx.math.MathUtils.random
 | 
			
		||||
 | 
			
		||||
data class SkillChoice (val skill : Skill, val target : List<Creature>)
 | 
			
		||||
 | 
			
		||||
@DslMarker
 | 
			
		||||
annotation class SkillMarker
 | 
			
		||||
 | 
			
		||||
@@ -105,6 +107,9 @@ object Skills {
 | 
			
		||||
    val Fly = skill("Fly") {
 | 
			
		||||
        addStatus(Flying(), Target.Self)
 | 
			
		||||
    }
 | 
			
		||||
    val Fly2 = skill("Fly", Attribute.Air) {
 | 
			
		||||
        damage(60)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    val Ember = skill("Ember", Attribute.Fire) {
 | 
			
		||||
        damage(40) {
 | 
			
		||||
 
 | 
			
		||||
@@ -4,48 +4,49 @@ import me.msoucy.ptures.controller.Engine
 | 
			
		||||
 | 
			
		||||
sealed class Status {
 | 
			
		||||
 | 
			
		||||
    open fun onTurnStart(engine : Engine, creature : Creature) {
 | 
			
		||||
    open fun onTurnStart(creature: Creature) {
 | 
			
		||||
        // Do nothing
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    open fun onAdd(creature : Creature) {
 | 
			
		||||
    open fun onAdd(creature: Creature) {
 | 
			
		||||
        // Do nothing
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    open fun onTurnEnd(engine : Engine) {
 | 
			
		||||
    open fun onTurnEnd(creature: Creature) {
 | 
			
		||||
        // Do nothing
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    open fun attackMod(creature : Creature) = 1.0
 | 
			
		||||
    open fun defenseMod(creature : Creature) = 1.0
 | 
			
		||||
    open fun attackMod(creature: Creature) = 1.0
 | 
			
		||||
    open fun defenseMod(creature: Creature) = 1.0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sealed class VisibleStatus(val label : String = "") : Status()
 | 
			
		||||
sealed class VisibleStatus(val label: String = "") : Status()
 | 
			
		||||
 | 
			
		||||
sealed class CountdownStatus(private var turns : Int) : Status()
 | 
			
		||||
{
 | 
			
		||||
    override fun onTurnEnd(engine : Engine) {
 | 
			
		||||
sealed class CountdownStatus(private var turns: Int) : Status() {
 | 
			
		||||
    override fun onTurnEnd(creature: Creature) {
 | 
			
		||||
        turns--
 | 
			
		||||
        if(turns == 0) {
 | 
			
		||||
            onCountdownReached(engine)
 | 
			
		||||
            engine.attacker.removeStatus(this)
 | 
			
		||||
        if (turns == 0) {
 | 
			
		||||
            onCountdownReached(creature)
 | 
			
		||||
            creature.removeStatus(this)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    open fun onCountdownReached(engine : Engine) {
 | 
			
		||||
    open fun onCountdownReached(creature: Creature) {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
object KnockedOut : VisibleStatus("ko")
 | 
			
		||||
object Burned : VisibleStatus("burned") {
 | 
			
		||||
    override fun onTurnEnd(engine : Engine) {
 | 
			
		||||
    override fun onTurnEnd(creature : Creature) {
 | 
			
		||||
        // Deal a small amount of damage
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
object Stunned : VisibleStatus("stunned")
 | 
			
		||||
object Poisoned : VisibleStatus("poisoned")
 | 
			
		||||
class Flying : CountdownStatus(1) {
 | 
			
		||||
    override fun onCountdownReached(engine: Engine) {
 | 
			
		||||
        super.onCountdownReached(engine)
 | 
			
		||||
class Flying(private vararg val targets : Creature) : CountdownStatus(1) {
 | 
			
		||||
    override fun onCountdownReached(creature: Creature) {
 | 
			
		||||
        super.onCountdownReached(creature)
 | 
			
		||||
        creature.activeSkill = SkillChoice(Skills.Fly2, targets.toList())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,50 +2,51 @@ package me.msoucy.ptures.view
 | 
			
		||||
 | 
			
		||||
import me.msoucy.ptures.model.Creature
 | 
			
		||||
import me.msoucy.ptures.model.Skill
 | 
			
		||||
import me.msoucy.ptures.model.SkillChoice
 | 
			
		||||
import me.msoucy.ptures.model.VisibleStatus
 | 
			
		||||
 | 
			
		||||
class SkillViewText(skill : Skill) : SkillView(skill) {
 | 
			
		||||
class SkillViewText(skill: Skill) : SkillView(skill) {
 | 
			
		||||
    override fun display() {
 | 
			
		||||
        println(skill.name)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun displayEnumerated(idx: Int) {
 | 
			
		||||
        println("${idx+1}: ${skill.name}")
 | 
			
		||||
        println("${idx + 1}: ${skill.name}")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class CreatureViewText(playerId : Int, creature : Creature) : CreatureView(playerId, creature) {
 | 
			
		||||
class CreatureViewText(playerId: Int, creature: Creature) : CreatureView(playerId, creature) {
 | 
			
		||||
 | 
			
		||||
    private val skillViews = creature.skills.map { SkillViewText(it) }
 | 
			
		||||
 | 
			
		||||
    private fun chooseSkillName() : Skill {
 | 
			
		||||
    private fun chooseSkillName(): Skill {
 | 
			
		||||
        println("Skills:")
 | 
			
		||||
        println("=======")
 | 
			
		||||
        skillViews.forEachIndexed { index, skillView ->
 | 
			
		||||
            skillView.displayEnumerated(index)
 | 
			
		||||
        }
 | 
			
		||||
        var idx = -1
 | 
			
		||||
        while(idx != -1) {
 | 
			
		||||
        while (idx != -1) {
 | 
			
		||||
            print("> ")
 | 
			
		||||
            val tmpIdx = readLine()?.toIntOrNull() ?: -1
 | 
			
		||||
            if (tmpIdx in creature.skills.indices)
 | 
			
		||||
            {
 | 
			
		||||
            if (tmpIdx in creature.skills.indices) {
 | 
			
		||||
                idx = tmpIdx
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return creature.skills[idx]
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun chooseTarget(skill : Skill, possibleTargets : List<Creature>) : Creature {
 | 
			
		||||
        return creature
 | 
			
		||||
    private fun chooseTarget(skill: Skill, possibleTargets: List<Creature>): List<Creature> {
 | 
			
		||||
        return possibleTargets
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun chooseSkill(possibleTargets : List<Creature>) : SkillChoice {
 | 
			
		||||
    override fun chooseSkill(possibleTargets: List<Creature>) {
 | 
			
		||||
 | 
			
		||||
        val skill = chooseSkillName()
 | 
			
		||||
        val target = chooseTarget(skill, possibleTargets)
 | 
			
		||||
 | 
			
		||||
        return SkillChoice(skill, target)
 | 
			
		||||
        if (creature.activeSkill == null) {
 | 
			
		||||
            val skill = chooseSkillName()
 | 
			
		||||
            val targets = chooseTarget(skill, possibleTargets)
 | 
			
		||||
            creature.activeSkill = SkillChoice(skill, targets)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun displayName() {
 | 
			
		||||
@@ -65,6 +66,6 @@ class CreatureViewText(playerId : Int, creature : Creature) : CreatureView(playe
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class PlayerViewText(playerId : Int) : PlayerView(playerId) {
 | 
			
		||||
class PlayerViewText(playerId: Int) : PlayerView(playerId) {
 | 
			
		||||
    override fun creatureViewFor(creature: Creature) = CreatureViewText(playerId, creature)
 | 
			
		||||
}
 | 
			
		||||
@@ -2,8 +2,7 @@ package me.msoucy.ptures.view
 | 
			
		||||
 | 
			
		||||
import me.msoucy.ptures.model.Creature
 | 
			
		||||
import me.msoucy.ptures.model.Skill
 | 
			
		||||
 | 
			
		||||
data class SkillChoice (val skill : Skill, val target : Creature)
 | 
			
		||||
import me.msoucy.ptures.model.SkillChoice
 | 
			
		||||
 | 
			
		||||
abstract class SkillView(val skill : Skill) {
 | 
			
		||||
    abstract fun display()
 | 
			
		||||
@@ -12,7 +11,7 @@ abstract class SkillView(val skill : Skill) {
 | 
			
		||||
 | 
			
		||||
abstract class CreatureView(val playerId : Int, val creature: Creature) {
 | 
			
		||||
 | 
			
		||||
    abstract fun chooseSkill(possibleTargets : List<Creature>) : SkillChoice
 | 
			
		||||
    abstract fun chooseSkill(possibleTargets : List<Creature>)
 | 
			
		||||
 | 
			
		||||
    abstract fun displayName()
 | 
			
		||||
    abstract fun displaySkills()
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user