blob: 5a2864ce843f10b22698daeda08dd922e55dfa88 [file] [edit]
package LambdaTheGathering
/**
* Incomplete solution to the IFCP Contest 2011
* @author yole
*/
class GameError(msg: String): Exception(msg) {
}
abstract class Function(val name: String) {
abstract fun apply(x: Value, proponent: Player): Value
fun toString() = name
open fun asNumber(): Int { throw GameError("could not get numeric value of a function") }
}
object Identity: Function("I") {
override fun apply(x: Value, proponent: Player): Value = x
}
object IdentityValue: Value(Identity)
object Zero: Function("zero") {
override fun apply(x: Value, proponent: Player): Value = Value(0)
override fun asNumber(): Int = 0
}
object Succ: Function("succ") {
override fun apply(x: Value, proponent: Player): Value = Value(x.asNumber() + 1)
}
object Get: Function("get") {
override fun apply(x: Value, proponent: Player): Value = proponent.getSlot(x.asNumber()).field
}
object Dbl: Function("dbl") {
override fun apply(x: Value, proponent: Player): Value = Value(x.asNumber() * 2)
}
class HelpFunc2(val i: Value, val j: Value): Function("help(" + i + ")(" + j + ")") {
override fun apply(x: Value, proponent: Player): Value {
val n = x.asNumber()
proponent.getSlot(i.asNumber()).decreaseVitality(n)
proponent.getSlot(j.asNumber()).increaseVitality(n * 11 / 10);
return Value(Identity)
}
}
class HelpFunc(val i: Value): Function("help(" + i + ")") {
override fun apply(x: Value, proponent: Player): Value = Value(HelpFunc2(i, x))
}
object Help: Function("help") {
override fun apply(x: Value, proponent: Player): Value = Value(HelpFunc(x))
}
class KFunc(val arg: Value): Function("K(" + arg + ")") {
override fun apply(x: Value, proponent: Player): Value = arg
}
object K: Function("K") {
override fun apply(x: Value, proponent: Player): Value = Value(KFunc(x))
}
class SFunc2(val f: Value, val g: Value): Function("S(" + f + ")(" + g + ")") {
override fun apply(x: Value, proponent: Player): Value {
val h = f.apply(x, proponent)
val y = g.apply(x, proponent)
val z = h.apply(y, proponent)
return z
}
}
class SFunc(val f: Value): Function("S(" + f + ")") {
override fun apply(x: Value, proponent: Player): Value = Value(SFunc2(f, x))
}
object S: Function("S") {
override fun apply(x: Value, proponent: Player): Value = Value(SFunc(x))
}
open class Value(val n: Int, val f: Function, val isFunction: Boolean) {
this(n: Int): this(if (n > 65535) 65535 else n, Identity, false) {}
this(f: Function): this(0, f, true) {}
fun equals(rhs: Any?): Boolean {
if (rhs is Value) {
val rhsValue = rhs as Value
if (rhsValue.isFunction) {
return isFunction && f === rhsValue.f
}
else {
return ! isFunction && n == rhsValue.n
}
}
return false
}
fun apply(x: Value, proponent: Player): Value {
if (isFunction) return f.apply(x, proponent)
throw GameError("could not apply non-function value");
}
fun asNumber(): Int {
if (! isFunction) return n;
return f.asNumber()
}
fun toString() = if (isFunction) f.name else Integer.toString(n)
}
class Slot() {
var vitality: Int = 10000
var field: Value = Value(Identity)
val alive: Boolean get() = vitality > 0
fun isDefault() = vitality == 10000 && field == Value(Identity)
fun increaseVitality(delta: Int) {
if (alive) {
vitality += delta
if (vitality > 65535) vitality = 65535;
}
}
fun decreaseVitality(delta: Int) {
if (!alive || delta > vitality) throw GameError("cannot decrease vitality")
vitality -= delta
}
fun toString() = "{" + vitality + "," + field.toString() + "}";
}
class Player() {
var opponent: Player? = null
val slots: Array<Slot> = Array<Slot>(256, { i -> Slot() })
fun getSlot(i: Int): Slot {
if (i < 0 || i > 255) throw GameError("invalid slot index")
if (!slots[i].alive) throw GameError("the slot is dead")
return slots[i]
}
fun printSlots() {
println("(slots {10000,I} are omitted)")
for(val i in 0..255) {
if (!slots[i].isDefault()) {
println("" + i + "=" + slots[i].toString())
}
}
}
fun applyCardToSlot(index: Int, card: Function) {
println("applying card " + card + " to slot " + index)
slots[index].field = card.apply(slots[index].field, this)
}
fun applySlotToCard(index: Int, card: Function) {
println("applying slot " + index + " to card " + card)
slots[index].field = slots[index].field.apply(Value(card), this)
}
}
val p0 = Player()
val p1 = Player()
fun main(args: Array<String>) {
p0.opponent = p1
p1.opponent = p0
print("player 0")
p0.printSlots()
p0.applySlotToCard(0, Help)
p0.printSlots()
p0.applySlotToCard(0, Zero)
p0.printSlots()
p0.applyCardToSlot(0, K)
p0.printSlots()
p0.applyCardToSlot(0, S)
p0.printSlots()
p0.applySlotToCard(0, Succ)
p0.printSlots()
p0.applySlotToCard(0, Zero)
p0.printSlots()
p0.applySlotToCard(1, Zero)
p0.printSlots()
p0.applyCardToSlot(1, Succ)
p0.printSlots()
p0.applyCardToSlot(1, Dbl)
p0.printSlots()
p0.applyCardToSlot(1, Dbl)
p0.printSlots()
p0.applyCardToSlot(1, Dbl)
p0.printSlots()
p0.applyCardToSlot(1, Dbl)
p0.printSlots()
p0.applyCardToSlot(0, K)
p0.printSlots()
p0.applyCardToSlot(0, S)
p0.printSlots()
p0.applySlotToCard(0, Get)
p0.printSlots()
p0.applyCardToSlot(0, K)
p0.printSlots()
p0.applyCardToSlot(0, S)
p0.printSlots()
p0.applySlotToCard(0, Succ)
p0.printSlots()
p0.applySlotToCard(0, Zero)
p0.printSlots()
}