diff --git a/Cards.kt b/Cards.kt index 4c7f846..5622501 100644 --- a/Cards.kt +++ b/Cards.kt @@ -3,8 +3,8 @@ import java.util.* abstract class AggressiveCard: Card { override fun startSkill() { println(activeString) - owner.enemy.effectBuffer = this.effects owner.enemy.attackingCard = this + owner.enemy.effectBuffer = this.effects owner.enemy.effectBuffer.forEach { it.apply() } } @@ -19,8 +19,6 @@ abstract class DefensiveCard: Card { if(owner.effectBuffer.isEmpty()) { throw NotInPassiveContextException() } - println("attacking: ${owner.attackingCard}") - println("${owner.enemy.attackingCard}") println(activeString) this.effects.forEach { it.apply() } } @@ -41,6 +39,7 @@ abstract class GeneralCard: Card { } } +//ordinary card class AttackCard(override val owner: Character): AggressiveCard() { override val name = "攻擊" override val id = 1 @@ -125,3 +124,57 @@ class ReverseCard(override val owner: Character): DefensiveCard() { override val activeString = "$owner 反制了 ${owner.enemy} 的攻擊,反彈了其效果" } +//SP card +//Guo's card +class SpaceZipperDoor(override val owner: Character): DefensiveCard() { + override val name = "空間之鍊(門)" + override val id = 101 + override val activeString = "$owner 使出了空間之鍊(門)" + override val effects: Array = arrayOf(Copy(owner), Defense(owner)) +} +class SpaceZipperShell(override val owner: Character): GeneralCard() { + override val name = "空間之鍊(殼)" + override val id = 102 + override val activeString = "$owner 使出了空間之鍊(殼)" + override val effects: Array = arrayOf(BecomeInvincible(owner, turns = 2)) +} +class SpaceZipperDestroy(override val owner: Character): AggressiveCard() { + override val name = "空間之鍊(滅)" + override val id = 103 + override val activeString = "$owner 使出了空間之鍊(滅)" + override val effects: Array = arrayOf(Damage(owner.enemy, decreaseLife = 5), + LoseCard(owner.enemy, num = 2)) +} + +//Rabbit's card +class NoScienceSlash(override val owner: Character): Card { + override val name = "科學無用論(高速砍擊)" + override val id = 201 + override val activeString = "$owner 使用了科學無用論(高速砍擊)" + override val effects: Array = arrayOf(UndefendableDamage(owner.enemy, decreaseLife = 3)) + override fun startSkill() { + effects.forEach { it.apply() } + } + + override fun toString() = "$id. $name" +} +class NoSciencePowerIncrease(override val owner: Character): GeneralCard() { + override val name = "科學無用論(力量增幅)" + override val id = 202 + override val activeString = "$owner 使用了科學無用論(力量增幅)" + override val effects: Array = arrayOf(ChangeDamageAddition(owner.enemy, num = 1, turns = 3)) +} +class NoScienceFinal(override val owner: Character): Card { + override val name = "科學無用論(終焉一擊)" + override val id = 203 + override val activeString = "$owner 使用了科學無用論(終焉一擊)" + override val effects: Array = arrayOf(UndefendableDamage(owner.enemy, decreaseLife = 5)) + override fun startSkill() { + effects.forEach { it.apply() } + } + + override fun toString() = "$id. $name" +} + + + diff --git a/Character.kt b/Character.kt index 2f721b5..a5de483 100644 --- a/Character.kt +++ b/Character.kt @@ -45,6 +45,9 @@ class Guo: Character() { arr += MutableList(1) { PoisonCard(this) } arr += MutableList(1) { ChaosCard(this) } arr += MutableList(1) { ReverseCard(this) } + arr += MutableList(2) { SpaceZipperDoor(this) } + arr += MutableList(2) { SpaceZipperShell(this) } + arr += MutableList(1) { SpaceZipperDestroy(this) } val deck = Deck(arr) deck.shuffle() @@ -97,6 +100,9 @@ class Rabbit: Character() { arr += MutableList(0) { PoisonCard(this) } arr += MutableList(3) { ChaosCard(this) } arr += MutableList(0) { ReverseCard(this) } + arr += MutableList(3) { NoScienceSlash(this) } + arr += MutableList(3) { NoSciencePowerIncrease(this) } + arr += MutableList(1) { NoScienceFinal(this) } val deck = Deck(arr) deck.shuffle() diff --git a/Effect.kt b/Effect.kt index 98b9f87..ebafd44 100644 --- a/Effect.kt +++ b/Effect.kt @@ -19,7 +19,7 @@ class Damage(override vararg val subjects: Character, override val id = 1 override fun apply() { - subject.life -= decreaseLife + subject.gotDamage(decreaseLife) } } @@ -38,7 +38,7 @@ class Heal(override vararg val subjects: Character, private val increaseLife: In override val id = 2 override fun apply() { - subject.life += increaseLife + subject.heal(increaseLife) } } @@ -83,8 +83,8 @@ class ChooseFromCharacterHand(override vararg val subjects: Character): Effect() } } -//This class take subjects[0] as the one who loses one card randomly -class LoseCard(override vararg val subjects: Character): Effect() { +//This class take subjects[0] as the one who loses cards randomly +class LoseCard(override vararg val subjects: Character, private val num: Int = 1): Effect() { init { if (subjects.isEmpty()) { @@ -98,9 +98,11 @@ class LoseCard(override vararg val subjects: Character): Effect() { override val id = 5 override fun apply() { - val cards = subject.hand - val index = Random().nextInt(cards.size) - cards.toMutableList().removeAt(index) + for (i in 1..num) { + val cards = subject.hand + val index = Random().nextInt(cards.size) + cards.toMutableList().removeAt(index) + } } } @@ -211,3 +213,84 @@ class Reverse(override vararg val subjects: Character): Effect() { } } +//This class take subject[0] as the one who wants to get the copied card +class Copy(override vararg val subjects: Character): Effect() { + + init { + if (subjects.isEmpty()) { + throw WrongParameterException() + } + } + private val subject = subjects[0] + override val reverseEffect: Effect + get() = Copy(subject.enemy) + override val id = 11 + override fun apply() { + subject.hand.add(subject.attackingCard!!) + } + +} + +//This class take subject[0] as the one to become invincible +class BecomeInvincible(override vararg val subjects: Character, + private var turns: Int): Effect() { + init { + if(subjects.isEmpty() || turns == 0) { + throw WrongParameterException() + } + } + private val subject = subjects[0] + override val reverseEffect: Effect + get() = BecomeInvincible(subject.enemy, turns = turns) + override val id = 11 + override fun apply() { + subject.isInvincible = true + subject.enemy.nextTurnListeners.add { + if(turns == 0) { + subject.isInvincible = false + true //listener will be removed + } else { + turns -= 1 + false //listener will not be removed + } + } + } +} + +//This class take subject[0] as the one to change damage addition +class ChangeDamageAddition(override vararg val subjects: Character, + private val num: Int, + private var turns: Int): Effect() { + private val subject = subjects[0] + override val reverseEffect: Effect + get() = ChangeDamageAddition(subject.enemy, num = num, turns = turns) + override val id = 12 + override fun apply() { + subject.damageAddition = num + val listener: NextTurnListener = { + if (turns == 0) { + subject.damageAddition = 0 + true //listener will be removed + } else { + turns -= 1 + false //listener will not be removed + } + } + subject.nextTurnListeners.add(listener) + } +} + +class UndefendableDamage(override vararg val subjects: Character, + private val decreaseLife: Int): Effect() { + private val subject = subjects[0] + override val reverseEffect: Effect + get() = UndefendableDamage(subject.enemy, decreaseLife = decreaseLife) + override val id = 13 + override fun apply() { + subject.gotDamage(decreaseLife, false) + } + +} + + + diff --git a/Interfaces.kt b/Interfaces.kt index fdd268e..84893ba 100644 --- a/Interfaces.kt +++ b/Interfaces.kt @@ -3,18 +3,29 @@ import java.util.* import kotlin.math.abs import kotlin.properties.Delegates +//Character is the one who entered next turn +//Returned value indicates whether this listener can be removed +typealias NextTurnListener = (Character) -> Boolean + abstract class Character { //basic info abstract val name: String abstract val id: Int abstract val deck: Deck + var damageAddition: Int = 0 + var damageMultiplier: Int = 1 var life: Int by Delegates.observable(0) {_, old, new -> val diff = abs(old-new) if (new < old) { println("${this.name} 受到 $diff 點傷害") } //heal description is provided in HealCard } + protected set //This line of code belong's to life property + + //This describe whether the character can be damaged by non_SP attack + var isInvincible = false + var poisoned: Boolean by Delegates.observable(false) {_, _, new -> if(new) { println("${this.name} 中毒了") @@ -23,8 +34,12 @@ abstract class Character { } } var hand: Cards = emptyList().toMutableList() + lateinit var enemy: Character //This will be set in GameLoop.init lateinit var endGameAsLoser: () -> Unit //This will be set in GameLoop.init + //listeners inside this will be called immediately after character enter next turn + var nextTurnListeners: MutableList = emptyList().toMutableList() + var turn = 0 var effectBuffer: Array by Delegates.observable(emptyArray()) { _, old, new -> @@ -92,6 +107,12 @@ abstract class Character { fun nextTurn() { turn++ + nextTurnListeners.forEach {listener -> + val result = listener(this) + if(result) { //listener can be removed + nextTurnListeners.remove(listener) + } + } println("${this.name} 的第 $turn 回合") if (this.poisoned) { println("中毒,扣1滴血") @@ -124,6 +145,19 @@ abstract class Character { } } } + + fun gotDamage(point: Int, defendable: Boolean = true) { + if (defendable && this.isInvincible) { + return + } + val damage = point * damageMultiplier + damageAddition + life -= damage + } + + fun heal(point: Int) { + life += point + } + override fun toString() = this.name } @@ -143,7 +177,6 @@ class Deck(cards: Cards) { fun shuffle() = cards.shuffle() } -class EmptyDeckException: Exception() typealias Cards = MutableList