mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-11 19:14:05 +09:00
wire: off-to-on traversal of nonbranching wire connection
This commit is contained in:
@@ -531,6 +531,8 @@ fun Int.abs() = this.absoluteValue
|
|||||||
fun Double.bipolarClamp(limit: Double) =
|
fun Double.bipolarClamp(limit: Double) =
|
||||||
this.coerceIn(-limit, limit)
|
this.coerceIn(-limit, limit)
|
||||||
fun Boolean.toInt() = if (this) 1 else 0
|
fun Boolean.toInt() = if (this) 1 else 0
|
||||||
|
fun Int.bitCount() = java.lang.Integer.bitCount(this)
|
||||||
|
fun Long.bitCount() = java.lang.Long.bitCount(this)
|
||||||
|
|
||||||
|
|
||||||
fun absMax(left: Double, right: Double): Double {
|
fun absMax(left: Double, right: Double): Double {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package net.torvald.terrarum.gameworld
|
|||||||
|
|
||||||
import com.badlogic.gdx.Input
|
import com.badlogic.gdx.Input
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
|
import net.torvald.terrarum.AppLoader.printdbg
|
||||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
||||||
import net.torvald.terrarum.blockproperties.Block
|
import net.torvald.terrarum.blockproperties.Block
|
||||||
import net.torvald.terrarum.blockproperties.BlockCodex
|
import net.torvald.terrarum.blockproperties.BlockCodex
|
||||||
@@ -476,58 +477,111 @@ object WorldSimulator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun traverseWireGraph(world: GameWorld, fixture: FixtureBase, wireType: String, bbi: BlockBoxIndex) {
|
private fun traverseWireGraph(world: GameWorld, fixture: FixtureBase, wireType: String, bbi: BlockBoxIndex) {
|
||||||
fixture.worldBlockPos?.let {
|
fixture.worldBlockPos?.let { sourceBlockPos ->
|
||||||
val branchesVisited = ArrayList<Point2i>()
|
val branchesVisited = ArrayList<WireGraphCursor>()
|
||||||
val branchingStack = Stack<Point2i>()
|
val points = ArrayList<WireGraphCursor>() // a queue, enqueued at the end
|
||||||
val point = it + fixture.blockBoxIndexToPoint2i(bbi)
|
var point = WireGraphCursor(sourceBlockPos + fixture.blockBoxIndexToPoint2i(bbi))
|
||||||
branchingStack.push(point.copy())
|
var terminate = false
|
||||||
|
|
||||||
|
fun dequeue() {
|
||||||
|
points.removeAt(0)
|
||||||
|
if (points.size == 0) terminate = true
|
||||||
|
else point = points[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
points.add(point.copy())
|
||||||
|
|
||||||
|
while (points.isNotEmpty() && !terminate) {
|
||||||
|
// break if there are no available wires underneath
|
||||||
|
if (world.getAllWiresFrom(point.x, point.y)?.filter { WireCodex[it].accepts == wireType }?.isEmpty() != false)
|
||||||
|
break
|
||||||
|
|
||||||
|
printdbg(this, branchesVisited)
|
||||||
|
|
||||||
while (branchingStack.isNotEmpty()) {
|
|
||||||
// get all wires that matches 'accepts' (such as Red/Green/Blue wire) and propagate signal for each of them
|
// get all wires that matches 'accepts' (such as Red/Green/Blue wire) and propagate signal for each of them
|
||||||
world.getAllWiresFrom(point.x, point.y)?.filter { WireCodex[it].accepts == wireType }?.forEach { wire ->
|
world.getAllWiresFrom(point.x, point.y)?.filter { WireCodex[it].accepts == wireType }?.forEach { wire ->
|
||||||
|
|
||||||
world.getAllWiringGraph(point.x, point.y)?.get(wire)?.let { node ->
|
world.getAllWiringGraph(point.x, point.y)?.get(wire)?.let { node ->
|
||||||
val cnx = node.connections.toInt()
|
|
||||||
when (wireConToStatus[cnx]) {
|
val signal = node.emitState
|
||||||
WireConStatus.THRU -> {
|
val cnx = node.connections.toInt() // 1-15
|
||||||
// TODO
|
val nextDirBit = cnx and (15 - point.fromWhere) // cnx minus where the old cursur was; also 1-15
|
||||||
}
|
printdbg(this, "(${point.x}, ${point.y}) from ${point.fromWhere} to $nextDirBit")
|
||||||
WireConStatus.END -> {
|
|
||||||
// TODO
|
// mark current position as visited
|
||||||
}
|
branchesVisited.add(point.copy())
|
||||||
WireConStatus.BRANCH -> {
|
|
||||||
// TODO
|
// termination condition 1
|
||||||
branchingStack.push(point.copy())
|
if (branchesVisited.linearSearch { it.x == point.x && it.y == point.y }!! < branchesVisited.lastIndex) {
|
||||||
|
printdbg(this, "(${point.x}, ${point.y}) was already visited")
|
||||||
|
dequeue()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
when (nextDirBit.bitCount()) {
|
||||||
|
in 4..64 -> { throw IllegalArgumentException("Bad nextDirBit: $nextDirBit") }
|
||||||
|
// nowhere to go
|
||||||
|
0 -> {
|
||||||
|
dequeue()
|
||||||
|
}
|
||||||
|
// only one direction to go
|
||||||
|
1 -> {
|
||||||
|
// move the "cursor"
|
||||||
|
point.moveOneCell(nextDirBit)
|
||||||
|
|
||||||
|
// propagate the signal to next position
|
||||||
|
world.setWireEmitStateOf(point.x, point.y, wire, signal)
|
||||||
|
}
|
||||||
|
// two or three directions to go
|
||||||
|
else -> {
|
||||||
|
return
|
||||||
|
|
||||||
|
// propagate the signal
|
||||||
|
|
||||||
|
// mark this branch
|
||||||
|
points.add(point.copy())
|
||||||
|
|
||||||
|
// move the "cursor" by try right, down, left then up
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
printdbg(this, "Point = $point")
|
||||||
|
} // end While
|
||||||
|
|
||||||
|
printdbg(this, "------------------------------------------")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum class WireConStatus { THRU, END, BRANCH }
|
private fun getNearbyTilesPos(x: Int, y: Int): Array<Point2i> {
|
||||||
private val wireConToStatus = arrayOf(
|
return arrayOf(
|
||||||
WireConStatus.END, // 0000
|
Point2i(x + 1, y),
|
||||||
WireConStatus.END, // 0001
|
Point2i(x, y - 1),
|
||||||
WireConStatus.END, // 0010
|
Point2i(x - 1, y),
|
||||||
WireConStatus.THRU,// 0011
|
Point2i(x, y + 1) // don't know why but it doesn't work if I don't flip Y
|
||||||
WireConStatus.END, // 0100
|
)
|
||||||
WireConStatus.THRU,// 0101
|
}
|
||||||
WireConStatus.THRU,// 0110
|
|
||||||
WireConStatus.BRANCH,// 0111
|
|
||||||
WireConStatus.END, // 1000
|
|
||||||
WireConStatus.THRU,// 1001
|
|
||||||
WireConStatus.THRU,// 1010
|
|
||||||
WireConStatus.BRANCH,// 1011
|
|
||||||
WireConStatus.THRU,// 1100
|
|
||||||
WireConStatus.BRANCH,// 1101
|
|
||||||
WireConStatus.BRANCH,// 1110
|
|
||||||
WireConStatus.BRANCH // 1111
|
|
||||||
)
|
|
||||||
|
|
||||||
data class WireGraphBranch(
|
data class WireGraphCursor(
|
||||||
val x: Int,
|
var x: Int,
|
||||||
val y: Int,
|
var y: Int,
|
||||||
val con: Byte
|
var fromWhere: Int, //1: right, 2: down, 4: left, 8: up, 0: *shrug*
|
||||||
)
|
var len: Int
|
||||||
|
) {
|
||||||
|
constructor(point2i: Point2i): this(point2i.x, point2i.y, 0, 0)
|
||||||
|
|
||||||
|
fun moveOneCell(dir: Int) {
|
||||||
|
when (dir) {
|
||||||
|
1 -> { x += 1; fromWhere = 4 }
|
||||||
|
2 -> { y += 1; fromWhere = 8 }
|
||||||
|
4 -> { x -= 1; fromWhere = 1 }
|
||||||
|
8 -> { y -= 1; fromWhere = 2 }
|
||||||
|
else -> throw IllegalArgumentException("Unacceptable direction: $dir")
|
||||||
|
}
|
||||||
|
len += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -46,11 +46,11 @@ class WireGraphDebugger(originalID: ItemID) : GameItem(originalID) {
|
|||||||
sb.clear()
|
sb.clear()
|
||||||
|
|
||||||
Terrarum.ingame!!.world.getAllWiringGraph(mx, my)?.let {
|
Terrarum.ingame!!.world.getAllWiringGraph(mx, my)?.let {
|
||||||
it.forEachIndexed { index, (itemID, simCell) ->
|
it.forEach { (itemID, simCell) ->
|
||||||
if (sb.isNotEmpty()) sb.append('\n')
|
if (sb.isNotEmpty()) sb.append('\n')
|
||||||
|
|
||||||
|
|
||||||
val connexionIcon = (simCell.con + 0xE0A0).toChar()
|
val connexionIcon = (simCell.connections + 0xE0A0).toChar()
|
||||||
val wireName = WireCodex[itemID].nameKey
|
val wireName = WireCodex[itemID].nameKey
|
||||||
|
|
||||||
val emit = simCell.emitState
|
val emit = simCell.emitState
|
||||||
|
|||||||
Reference in New Issue
Block a user