secminhr bf36952e73 Card update
Add SP card for Guo and Rabbit
2018-08-28 10:01:49 +00:00

213 lines
6.5 KiB
Kotlin
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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} 中毒了")
} else {
println("${this.name} 毒性解除")
}
}
var hand: Cards = emptyList<Card>().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<NextTurnListener> = emptyList<NextTurnListener>().toMutableList()
var turn = 0
var effectBuffer: Array<Effect> by Delegates.observable(emptyArray()) { _, old, new ->
if(new.isNotEmpty() /* been clean*/ &&
old.map { it.reverseEffect }.toTypedArray().contentNotEquals(new) /*tmp effect of reverse*/) {
val defensiveInHand = hand.filter { it is DefensiveCard }
if (defensiveInHand.isNotEmpty()) {
println("請選擇要使用的防禦卡片或是打0放棄")
println(defensiveInHand.filterIndexed { index,_ ->
if (index != 0) {
defensiveInHand[index].name != defensiveInHand[index-1].name
} else {
true
}
})
val scanner = Scanner(System.`in`)
var id = scanner.nextInt()
while(id != 0) {
if(defensiveInHand.indexOfFirst { it.id == id } == -1){
id = scanner.nextInt()
continue
} else {
val index = hand.indexOfFirst { it.id == id }
hand[index].startSkill()
hand.removeAt(index)
break
}
}
}
}
}
var attackingCard: Card? = null
fun drawFromDeck(num: Int = 1) {
for (i in 1..num) {
try {
val card = deck.firstCard
println("${this.name}抽到了 ${card.id}. ${card.name}")
hand.add(card)
println("牌組剩餘 ${deck.size} 張牌")
} catch (e: NoSuchElementException) {
println("牌庫已空,你抽到了死神")
life = -9999
endGameAsLoser()
}
}
}
fun chooseFromCards(cards: Cards) {
println("請選擇一張")
cards.forEach { println("${it.id}. ${it.name} ") }
val scanner = Scanner(System.`in`)
while(true) {
val id = scanner.nextInt()
val card = try {
cards.filter { it.id == id }[0]
} catch (e: IndexOutOfBoundsException) {
continue
}
println("${this.name} 選擇了 ${card.name}")
hand.add(card)
break
}
}
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滴血")
this.life--
}
println("生命值: $life")
println("請出牌:(或輸入0放棄)")
println(this.hand.filter { !(it is DefensiveCard) })
val scanner = Scanner(System.`in`)
var id = scanner.nextInt()
while (id != 0) {
val index = hand.indexOfFirst {
it.id == id
}
if (index == -1) {
println("請出牌:(或輸入0放棄)")
id = scanner.nextInt()
continue
} else {
if (hand[index] is DefensiveCard) {
println("請出牌:(或輸入0放棄)")
id = scanner.nextInt()
continue
} else {
hand[index].startSkill()
hand.removeAt(index)
drawFromDeck()
break
}
}
}
}
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
}
fun <T> Array<T>.contentNotEquals(array: Array<out T>) = !this.contentEquals(array)
class Deck(cards: Cards) {
var cards: Cards = cards
private set
val size: Int
get() = cards.size
val firstCard: Card
get() {
val card = cards.first()
cards.removeAt(0)
return card
}
fun shuffle() = cards.shuffle()
}
typealias Cards = MutableList<Card>
interface Card {
val owner: Character
val name: String
val id: Int
val activeString: String
//This must be a calculated property instead of a stored value
//in order to prevent StackOverflowError
val effects: Array<Effect>
fun startSkill()
}
abstract class Effect {
abstract val subjects: Array<out Character> //The structure of subjects will defined by the concrete classes
abstract val reverseEffect: Effect
abstract val id: Int
abstract fun apply()
override fun toString(): String = this.javaClass.name
override fun equals(other: Any?): Boolean {
return if(other is Effect) {
this.id == other.id
} else {
false
}
}
override fun hashCode() = this.id
}