Moved forced skills into creature

This commit is contained in:
Matt Soucy 2019-12-07 11:08:39 -05:00
parent f496abee18
commit 2683ce69a9
6 changed files with 77 additions and 84 deletions

View File

@ -1,12 +1,10 @@
package me.msoucy.ptures.controller package me.msoucy.ptures.controller
import me.msoucy.ptures.model.Creature import me.msoucy.ptures.model.*
import me.msoucy.ptures.model.KnockedOut
import me.msoucy.ptures.model.Skill
import me.msoucy.ptures.model.Target import me.msoucy.ptures.model.Target
import me.msoucy.ptures.model.Team
import me.msoucy.ptures.view.BattleView 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) { sealed class BattleType(vararg val teams: Team) {
init { init {
@ -33,16 +31,19 @@ class RaidBattle(val boss: Creature, vararg teams: Team) : BattleType(*teams) {
class Engine(private val battle: BattleType) { 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 } private val creatures get() = battle.teams.flatMap { it.activeCreatures }
val attacker: Creature // The current attacking creature
private var attacker: CreatureView
get() { get() {
return creatures[currentCreature].creature return currentCreature
}
private set(value) {
currentCreature = value
} }
private val forcedSkills = mutableMapOf<Creature, Skill>()
private val activeCreatures private val activeCreatures
get() = creatures get() = creatures
@ -50,70 +51,54 @@ class Engine(private val battle: BattleType) {
.sortedBy { it.creature.spd } .sortedBy { it.creature.spd }
fun resolveTurn(view: BattleView) { fun resolveTurn(view: BattleView) {
forcedSkills.clear()
// All preconditions // All preconditions
for (i in activeCreatures.indices) { for (creature in activeCreatures) {
val creature = creatures[i]
for (status in creature.creature.statuses) { for (status in creature.creature.statuses) {
status.onTurnStart(this, creature.creature) status.onTurnStart(creature.creature)
} }
} }
// Get the moves each creature will use this turn // Get the moves each creature will use this turn
val moves = activeCreatures.indices.map { i -> activeCreatures.forEach {
val forcedSkill = forcedSkills[creatures[i].creature] it.chooseSkill(activeCreatures.map { c -> c.creature })
if (forcedSkill != null) {
SkillChoice(forcedSkill, creatures[nextOpponent(i)].creature)
} else {
creatures[i].chooseSkill(activeCreatures.map { it.creature })
}
} }
// Resolve each move // Resolve each move
for (i in activeCreatures.indices) { for (c in activeCreatures) {
// Resolve move // Resolve move
val (skill, target) = moves[i] val (skill, targets) = c.creature.activeSkill!!
currentCreature = i currentCreature = c
val attackingCreature = currentCreature
for (step in skill.damageSteps) { for (step in skill.damageSteps) {
for (targetCreature in getTargetList(step.target, target)) { for (targetCreature in targets) {
if (attacker.hits(targetCreature, step)) { if (attackingCreature.creature.hits(targetCreature, step)) {
targetCreature.apply(step, attacker) targetCreature.apply(step, attackingCreature.creature)
step.applyStatus(targetCreature) step.applyStatus(targetCreature)
} }
} }
} }
for (step in skill.postSteps) { for (step in skill.postSteps) {
for (targetCreature in getTargetList(step.target, target)) { for (targetCreature in targets) {
step.apply(targetCreature) step.apply(targetCreature)
} }
} }
} }
// All post conditions // All post conditions
for (creatureView in activeCreatures) { for (creatureView in activeCreatures) {
val creature = creatureView.creature val creature = creatureView.creature
for (status in creature.statuses) { for (status in creature.statuses) {
status.onTurnEnd(this) status.onTurnEnd(creature)
} }
} }
} }
private fun getTargetList(target: Target, selected: Creature): List<Creature> { private fun getTargetList(target: Target, selected: Creature): List<Creature> = when (target) {
return when (target) { Target.Self -> listOf(attacker.creature)
Target.Self -> listOf(attacker)
Target.Selected -> listOf(selected) Target.Selected -> listOf(selected)
Target.Others -> creatures.filter { it.creature != attacker }.map { it.creature } Target.Others -> creatures.filter { it.creature != attacker.creature }.map { it.creature }
Target.Opponents -> creatures.filter { it.playerId != creatures[currentCreature].playerId }.map { it.creature } Target.Opponents -> creatures.filter { it.playerId != attacker.playerId }.map { it.creature }
Target.All -> creatures.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
}
} }

View File

@ -15,6 +15,8 @@ class Creature {
val skills = mutableListOf<Skill>() val skills = mutableListOf<Skill>()
val statuses = mutableListOf<Status>() val statuses = mutableListOf<Status>()
var activeSkill : SkillChoice? = null
val atk : Int get() = statFormula(genes.atk, growth.atk) val atk : Int get() = statFormula(genes.atk, growth.atk)
val def : Int get() = statFormula(genes.def, growth.def) val def : Int get() = statFormula(genes.def, growth.def)
val spd : Int get() = statFormula(genes.spd, growth.spd) val spd : Int get() = statFormula(genes.spd, growth.spd)

View File

@ -2,6 +2,8 @@ package me.msoucy.ptures.model
import com.badlogic.gdx.math.MathUtils.random import com.badlogic.gdx.math.MathUtils.random
data class SkillChoice (val skill : Skill, val target : List<Creature>)
@DslMarker @DslMarker
annotation class SkillMarker annotation class SkillMarker
@ -105,6 +107,9 @@ object Skills {
val Fly = skill("Fly") { val Fly = skill("Fly") {
addStatus(Flying(), Target.Self) addStatus(Flying(), Target.Self)
} }
val Fly2 = skill("Fly", Attribute.Air) {
damage(60)
}
val Ember = skill("Ember", Attribute.Fire) { val Ember = skill("Ember", Attribute.Fire) {
damage(40) { damage(40) {

View File

@ -4,48 +4,49 @@ import me.msoucy.ptures.controller.Engine
sealed class Status { sealed class Status {
open fun onTurnStart(engine : Engine, creature : Creature) { open fun onTurnStart(creature: Creature) {
// Do nothing // Do nothing
} }
open fun onAdd(creature : Creature) { open fun onAdd(creature: Creature) {
// Do nothing // Do nothing
} }
open fun onTurnEnd(engine : Engine) { open fun onTurnEnd(creature: Creature) {
// Do nothing // Do nothing
} }
open fun attackMod(creature : Creature) = 1.0 open fun attackMod(creature: Creature) = 1.0
open fun defenseMod(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() sealed class CountdownStatus(private var turns: Int) : Status() {
{ override fun onTurnEnd(creature: Creature) {
override fun onTurnEnd(engine : Engine) {
turns-- turns--
if(turns == 0) { if (turns == 0) {
onCountdownReached(engine) onCountdownReached(creature)
engine.attacker.removeStatus(this) creature.removeStatus(this)
} }
} }
open fun onCountdownReached(engine : Engine) { open fun onCountdownReached(creature: Creature) {
} }
} }
object KnockedOut : VisibleStatus("ko") object KnockedOut : VisibleStatus("ko")
object Burned : VisibleStatus("burned") { object Burned : VisibleStatus("burned") {
override fun onTurnEnd(engine : Engine) { override fun onTurnEnd(creature : Creature) {
// Deal a small amount of damage // Deal a small amount of damage
} }
} }
object Stunned : VisibleStatus("stunned") object Stunned : VisibleStatus("stunned")
object Poisoned : VisibleStatus("poisoned") object Poisoned : VisibleStatus("poisoned")
class Flying : CountdownStatus(1) { class Flying(private vararg val targets : Creature) : CountdownStatus(1) {
override fun onCountdownReached(engine: Engine) { override fun onCountdownReached(creature: Creature) {
super.onCountdownReached(engine) super.onCountdownReached(creature)
creature.activeSkill = SkillChoice(Skills.Fly2, targets.toList())
} }
} }

View File

@ -2,50 +2,51 @@ package me.msoucy.ptures.view
import me.msoucy.ptures.model.Creature import me.msoucy.ptures.model.Creature
import me.msoucy.ptures.model.Skill import me.msoucy.ptures.model.Skill
import me.msoucy.ptures.model.SkillChoice
import me.msoucy.ptures.model.VisibleStatus import me.msoucy.ptures.model.VisibleStatus
class SkillViewText(skill : Skill) : SkillView(skill) { class SkillViewText(skill: Skill) : SkillView(skill) {
override fun display() { override fun display() {
println(skill.name) println(skill.name)
} }
override fun displayEnumerated(idx: Int) { 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 val skillViews = creature.skills.map { SkillViewText(it) }
private fun chooseSkillName() : Skill { private fun chooseSkillName(): Skill {
println("Skills:") println("Skills:")
println("=======") println("=======")
skillViews.forEachIndexed { index, skillView -> skillViews.forEachIndexed { index, skillView ->
skillView.displayEnumerated(index) skillView.displayEnumerated(index)
} }
var idx = -1 var idx = -1
while(idx != -1) { while (idx != -1) {
print("> ") print("> ")
val tmpIdx = readLine()?.toIntOrNull() ?: -1 val tmpIdx = readLine()?.toIntOrNull() ?: -1
if (tmpIdx in creature.skills.indices) if (tmpIdx in creature.skills.indices) {
{
idx = tmpIdx idx = tmpIdx
} }
} }
return creature.skills[idx] return creature.skills[idx]
} }
private fun chooseTarget(skill : Skill, possibleTargets : List<Creature>) : Creature { private fun chooseTarget(skill: Skill, possibleTargets: List<Creature>): List<Creature> {
return creature return possibleTargets
} }
override fun chooseSkill(possibleTargets : List<Creature>) : SkillChoice { override fun chooseSkill(possibleTargets: List<Creature>) {
if (creature.activeSkill == null) {
val skill = chooseSkillName() val skill = chooseSkillName()
val target = chooseTarget(skill, possibleTargets) val targets = chooseTarget(skill, possibleTargets)
creature.activeSkill = SkillChoice(skill, targets)
return SkillChoice(skill, target) }
} }
override fun displayName() { 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) override fun creatureViewFor(creature: Creature) = CreatureViewText(playerId, creature)
} }

View File

@ -2,8 +2,7 @@ package me.msoucy.ptures.view
import me.msoucy.ptures.model.Creature import me.msoucy.ptures.model.Creature
import me.msoucy.ptures.model.Skill import me.msoucy.ptures.model.Skill
import me.msoucy.ptures.model.SkillChoice
data class SkillChoice (val skill : Skill, val target : Creature)
abstract class SkillView(val skill : Skill) { abstract class SkillView(val skill : Skill) {
abstract fun display() abstract fun display()
@ -12,7 +11,7 @@ abstract class SkillView(val skill : Skill) {
abstract class CreatureView(val playerId : Int, val creature: Creature) { 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 displayName()
abstract fun displaySkills() abstract fun displaySkills()