diff --git a/befunge/befunge.iml b/befunge/befunge.iml
index 6cea5be..da87f9f 100644
--- a/befunge/befunge.iml
+++ b/befunge/befunge.iml
@@ -37,5 +37,14 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/befunge/src/main/kotlin/befide/befunge/b93/B93Funge.kt b/befunge/src/main/kotlin/befide/befunge/b93/B93Funge.kt
index c7019d4..5244407 100644
--- a/befunge/src/main/kotlin/befide/befunge/b93/B93Funge.kt
+++ b/befunge/src/main/kotlin/befide/befunge/b93/B93Funge.kt
@@ -6,21 +6,57 @@ import befide.befunge.state.*
class B93Funge : Funge {
override val width = 80
override val height = 25
+ private var cars = Array(height) { Array(width) {' '.toLong()}}
override fun get(vec: Vec): Value {
- TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+ return Value(cars[vec.y][vec.x])
}
override fun set(vec: Vec, value: Value) {
- TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+ cars[vec.y][vec.x] = value.value
}
override fun nextVec(vec: Vec, delta: Vec): Vec {
- TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+ var x = vec.x + delta.x
+ var y = vec.y + delta.y
+ if (x >= width || x < 0) {
+ x %= width
+ }
+ if (x < 0) {
+ x += width
+ }
+ if (y >= height || y < 0) {
+ y %= height
+ }
+ if (y < 0) {
+ y += height
+ }
+
+ return Vec(x,y)
}
override fun setString(data: String) {
- TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+ val strings = data.split('\n')
+ for (i in strings.size until height) {
+ cars[i] = Array(width) {' '.toLong()}
+ }
+ strings.map {
+ it.toList().map{it.toLong()}
+ }
+ .forEachIndexed { index, list ->
+ if (index > height) {
+ return
+ }
+ cars[index] = (
+ list.toList() + List(
+ if (list.size <= width) width - list.size else 0
+ ){
+ ' '.toLong()
+ }
+ )
+ .subList(0, width)
+ .toTypedArray()
+ }
}
}
diff --git a/befunge/src/main/kotlin/befide/befunge/b93/B93Interpreter.kt b/befunge/src/main/kotlin/befide/befunge/b93/B93Interpreter.kt
index 4cfa6f5..1e34412 100644
--- a/befunge/src/main/kotlin/befide/befunge/b93/B93Interpreter.kt
+++ b/befunge/src/main/kotlin/befide/befunge/b93/B93Interpreter.kt
@@ -1,16 +1,20 @@
package befide.befunge.b93
import befide.befunge.core.Interpreter
-import befide.befunge.events.Event
-import befide.befunge.events.FungeEvent
-import befide.befunge.events.IpEvent
-import befide.befunge.events.StackEvent
+import befide.befunge.events.*
import befide.befunge.state.IpMode
import befide.befunge.state.Value
import befide.befunge.state.Vec
import java.util.*
class B93Interpreter : Interpreter {
+ private companion object {
+ val RIGHT = Vec(1, 0)
+ val LEFT = Vec(-1, 0)
+ val UP = Vec(0, -1)
+ val DOWN = Vec(0,1)
+ }
+
override val funge = B93Funge()
override val stack = Stack()
override val ip = B93Pointer(Vec(0, 0), Vec(1, 0), IpMode.Normal)
@@ -19,11 +23,269 @@ class B93Interpreter : Interpreter {
override val stackChanged: Event = Event()
override val ipChanged: Event = Event()
+ private val fungeMods = HashMap()
+
+ private fun _pop(): Value? {
+ if (!stack.empty())
+ return stack.pop()
+ return null
+ }
+
+ private fun pop(): Value {
+ val v = _pop()
+ val ret = v?.let {
+ stackChanged(StackEvent(StackAction.Pop, listOf(it)))
+ it
+ } ?: Value(0)
+ return ret
+ }
+
+ private fun pop(num: Int): List {
+ val vs = List(num) {_pop()}
+ stackChanged(StackEvent(StackAction.Pop, vs.filterNotNull()))
+ return vs.map { it ?: Value(0) }
+ }
+
+ private fun _push(v: Value) {
+ stack.push(v)
+ }
+
+ private fun push(v: Value) {
+ _push(v)
+ stackChanged.invoke(StackEvent(StackAction.Push, listOf(v)))
+ }
+
+ private fun push(vs: List) {
+ vs.forEach { _push(it) }
+ stackChanged.invoke(StackEvent(StackAction.Push, vs))
+ }
+
+ private fun peek(): Value {
+ if (!stack.empty()) {
+ return stack.peek()
+ }
+ return Value(0)
+ }
+
+ private fun binop(bop: Char) {
+ val (vb, va) = pop(2)
+ val a = va.value
+ val b = vb.value
+ val res = when(bop) {
+ '+' -> a + b
+ '-' -> a - b
+ '*' -> a * b
+ '/' -> a / b
+ '%' -> a % b
+ '`' -> if (a > b) 1L else 0L
+ else -> null
+ }
+ res?.let {
+ val vres = Value(res)
+ push(vres)
+ }
+ }
+
+ private fun unop(uop: Char) {
+ val vv = pop()
+ val v = vv.value
+ val res = when(uop) {
+ '!' -> if (v == 0L) 1L else 0L
+ else -> null
+ }
+ res?.let {
+ val vres = Value(it)
+ push(vres)
+ }
+ }
+
+ private fun changeDir(dir: Char) {
+ val newDelta = when(dir) {
+ '>' -> RIGHT
+ '<' -> LEFT
+ '^' -> UP
+ 'v' -> DOWN
+ else -> null
+ }
+ newDelta?.let {
+ ip.delta = it
+ }
+ }
+
+ private fun randomDir() {
+ val dirs = listOf('<', '>', '^', 'v')
+ val ind = Random().nextInt(4)
+ changeDir(dirs[ind])
+ }
+
+ private fun conditional(cop: Char) {
+ val vcond = pop()
+ val cond = vcond.value == 0L
+ val newDelta = when(cop) {
+ '|' -> if (cond) DOWN else UP
+ '_' -> if (cond) RIGHT else LEFT
+ else -> null
+ }
+ newDelta?.let {
+ ip.delta = it
+ }
+ }
+
+ private fun toggleStrmode() {
+ val newMode = when (ip.mode) {
+ IpMode.String -> IpMode.Normal
+ IpMode.Normal -> IpMode.String
+ IpMode.Inactive -> IpMode.Inactive
+ }
+ ip.mode = newMode
+ }
+
+ private fun stackop(sop: Char) {
+ when (sop) {
+ ':' -> {
+ val vc = peek().copy()
+ push(vc)
+ }
+ '\\' -> {
+ val (v2, v1) = pop(2)
+ push(listOf(v2, v1))
+ }
+ '$' -> {
+ pop()
+ }
+ }
+ }
+
+ private fun output(type: Char) {
+ val vv = pop()
+ val v = vv.value
+ val out = when (type) {
+ '.' -> v.toString().toCharArray() + ' '
+ ',' -> charArrayOf(v.toChar())
+ else -> charArrayOf()
+ }
+ print(out) //TEMPORARY
+ //TODO output {out} chararray
+ }
+
+ private fun stepIP() {
+ ip.pos = funge.nextVec(ip.pos, ip.delta)
+ // No ipChanged here, shown in execInstr
+ }
+
+ private fun input(type: Char) {
+ val inp = readLine()
+ val vinp = Value(when(type) {
+ '&' -> inp?.toLong() ?: 0L
+ '~' -> inp?.get(0)?.toLong() ?: 0L
+ else -> 0L
+ })
+ push(vinp)
+ }
+
+ private fun fget() {
+ val (vy, vx) = pop(2)
+ val x = vx.value.toInt()
+ val y = vy.value.toInt()
+ if (0 <= x && x < funge.width && 0 <= y && y <= funge.height) {
+ val vv = funge[Vec(x, y)]
+ push(vv)
+ }
+ }
+
+ private fun fput() {
+ val (vy, vx, vv) = pop(3)
+ val x = vx.value.toInt()
+ val y = vy.value.toInt()
+ if (0 <= x && x < funge.width && 0 <= y && y <= funge.height) {
+ val loc = Vec(x, y)
+ val old = funge[loc]
+ funge[loc] = vv
+ if (!fungeMods.contains(loc)) {
+ fungeMods[loc] = old
+ }
+ fungeChanged(FungeEvent(listOf(FungeChange(loc,old,vv))))
+ }
+ }
+
+ private fun terminate() {
+ ip.mode = IpMode.Inactive
+ }
+
+ private fun pushDig(dig: Char) {
+ val num = dig.toLong() - '0'.toLong()
+ push(Value(num))
+ }
+
+ private fun noOp() {}
+
+ private fun execInstr(instr: Value) {
+ val car = instr.asChar
+ when (car) {
+ null -> noOp()
+ '+', '-', '*', '/', '%', '`' -> binop(car)
+ '!' -> unop(car)
+ '>', '<', '^', 'v' -> changeDir(car)
+ '?' -> randomDir()
+ '_', '|' -> conditional(car)
+ '"' -> toggleStrmode()
+ ':', '\\', '$' -> stackop(car)
+ '.', ',' -> output(car)
+ '#' -> stepIP()
+ 'g' -> fget()
+ 'p' -> fput()
+ '&', '~' -> input(car)
+ '@' -> terminate()
+ in '0'..'9' -> pushDig(car)
+ else -> noOp()
+ }
+ }
+
+ private fun strMode(instr: Value) {
+ if (instr.asChar == '"') {
+ toggleStrmode()
+ return
+ }
+ push(instr)
+ }
+
override fun step(): Boolean {
- TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+ val instr = funge[ip.pos]
+ val currIP = ip.copy()
+ when (ip.mode) {
+ IpMode.Inactive -> noOp()
+ IpMode.Normal -> execInstr(instr)
+ IpMode.String -> strMode(instr)
+ }
+ if (ip.mode != IpMode.Inactive) {
+ stepIP()
+ if (ip.mode != IpMode.String) {
+ while (funge[ip.pos].asChar == ' ') {
+ stepIP()
+ }
+ }
+ val newIP = ip.copy()
+ ipChanged(IpEvent(currIP, newIP))
+ }
+ return ip.mode != IpMode.Inactive
}
override fun reset() {
- TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+ val oldIP = ip.copy()
+ ip.pos = Vec(0,0)
+ ip.delta = RIGHT
+ ip.mode = IpMode.Normal
+ val newIP = ip.copy()
+ ipChanged.invoke(IpEvent(oldIP, newIP))
+
+ stack.clear()
+ stackChanged(StackEvent(StackAction.Clear, listOf()))
+
+ val changes = fungeMods.map { FungeChange(it.key, funge[it.key], it.value) }
+ for ((k,v) in fungeMods) {
+ funge[k] = v
+ }
+ fungeMods.clear()
+ fungeChanged(FungeEvent(changes))
}
}
\ No newline at end of file
diff --git a/befunge/src/main/kotlin/befide/befunge/b93/B93Pointer.kt b/befunge/src/main/kotlin/befide/befunge/b93/B93Pointer.kt
index f1a2fdf..ffadaf5 100644
--- a/befunge/src/main/kotlin/befide/befunge/b93/B93Pointer.kt
+++ b/befunge/src/main/kotlin/befide/befunge/b93/B93Pointer.kt
@@ -4,4 +4,4 @@ import befide.befunge.core.Pointer
import befide.befunge.state.IpMode
import befide.befunge.state.Vec
-data class B93Pointer(override val pos: Vec, override val delta: Vec, override val mode: IpMode) : Pointer
\ No newline at end of file
+data class B93Pointer(override var pos: Vec, override var delta: Vec, override var mode: IpMode) : Pointer
\ No newline at end of file
diff --git a/befunge/src/main/kotlin/befide/befunge/state/IpMode.kt b/befunge/src/main/kotlin/befide/befunge/state/IpMode.kt
index 511168b..16af492 100644
--- a/befunge/src/main/kotlin/befide/befunge/state/IpMode.kt
+++ b/befunge/src/main/kotlin/befide/befunge/state/IpMode.kt
@@ -3,6 +3,5 @@ package befide.befunge.state
enum class IpMode {
Normal,
String,
- Char,
Inactive
}
\ No newline at end of file
diff --git a/befunge/src/main/kotlin/befide/befunge/state/Value.kt b/befunge/src/main/kotlin/befide/befunge/state/Value.kt
index 3884051..dd469fe 100644
--- a/befunge/src/main/kotlin/befide/befunge/state/Value.kt
+++ b/befunge/src/main/kotlin/befide/befunge/state/Value.kt
@@ -1,7 +1,7 @@
package befide.befunge.state
-data class Value(val value: Int) {
- constructor(value: Char) : this(value.toInt())
+data class Value(val value: Long) {
+ constructor(value: Char) : this(value.toLong())
val asChar: Char? = if (value in (32..126)) value.toChar() else null
}
\ No newline at end of file
diff --git a/ide/ide.iml b/ide/ide.iml
index d51fa71..86b45e9 100644
--- a/ide/ide.iml
+++ b/ide/ide.iml
@@ -29,6 +29,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+