fixed a bug where only the first wire item of same 'accepts' property would be chosen for signals be propagated

This commit is contained in:
minjaesong
2021-08-18 15:27:37 +09:00
parent f764448d06
commit c0ef84412b
2 changed files with 42 additions and 50 deletions

View File

@@ -475,65 +475,60 @@ object WorldSimulator {
// signal-emitting fixtures must set emitState of its own tiles via update() // signal-emitting fixtures must set emitState of its own tiles via update()
sources.forEach { sources.forEach {
(it as Electric).wireEmitterTypes.forEach { wireType, bbi -> (it as Electric).wireEmitterTypes.forEach { wireType, bbi ->
traverseWireGraph(world, it, wireType, bbi)
val startingPoint = WireGraphCursor(it.worldBlockPos!! + it.blockBoxIndexToPoint2i(bbi))
val signal = (it as Electric).wireEmission[bbi] ?: Vector2(0.0, 0.0)
world.getAllWiringGraph(startingPoint.x, startingPoint.y)?.keys?.filter { WireCodex[it].accepts == wireType }?.forEach { wire ->
traverseWireGraph(world, wire, startingPoint, signal)
}
} }
} }
} }
} }
private fun traverseWireGraph(world: GameWorld, fixture: FixtureBase, wireType: String, bbi: BlockBoxIndex) { private fun traverseWireGraph(world: GameWorld, wire: ItemID, startingPoint: WireGraphCursor, signal: Vector2) {
fun getAdjacent(cnx: Int, point: WireGraphCursor): List<WireGraphCursor> { fun getAdjacent(cnx: Int, point: WireGraphCursor): List<WireGraphCursor> {
val r = ArrayList<WireGraphCursor>() val r = ArrayList<WireGraphCursor>()
for (dir in intArrayOf(RIGHT,DOWN,LEFT,UP)) { for (dir in intArrayOf(RIGHT, DOWN, LEFT, UP)) {
if (cnx and dir != 0) r.add(point.copy().moveOneCell(dir)) if (cnx and dir != 0) r.add(point.copy().moveOneCell(dir))
} }
return r return r
} }
fixture.worldBlockPos?.let { sourceBlockPos -> var point = startingPoint.copy()
val points = Queue<WireGraphCursor>() // a queue, enqueued at the end
val marked = HashSet<Long>()
val signal = (fixture as Electric).wireEmission[bbi] ?: Vector2(0.0, 0.0) fun mark(point: WireGraphCursor) {
var point = WireGraphCursor(sourceBlockPos + fixture.blockBoxIndexToPoint2i(bbi)) marked.add(point.longHash())
// do some signal action
world.setWireEmitStateOf(point.x, point.y, wire, signal)
}
world.getAllWiresFrom(point.x, point.y)?.filter { WireCodex[it].accepts == wireType }?.forEach { wire -> fun isMarked(point: WireGraphCursor) = marked.contains(point.longHash())
// this makes sure that only the emitters with wires installed will get traversed fun enq(point: WireGraphCursor) = points.addFirst(point.copy())
world.getWireGraphOf(point.x, point.y, wire)?.let { _ -> fun deq() = points.removeLast()
printdbg(this, wire)
val points = Queue<WireGraphCursor>() // a queue, enqueued at the end enq(point)
var marked = HashSet<Long>() mark(point)
fun mark(point: WireGraphCursor) { while (points.notEmpty()) {
marked.add(point.longHash()) point = deq()
// do some signal action // TODO if we found a power receiver, do something to it
world.setWireEmitStateOf(point.x, point.y, wire, signal) world.getWireGraphOf(point.x, point.y, wire)?.let { connections ->
} for (x in getAdjacent(connections, point)) {
if (!isMarked(x)) {
fun isMarked(point: WireGraphCursor) = marked.contains(point.longHash()) mark(x)
fun enq(point: WireGraphCursor) = points.addFirst(point.copy()) enq(x)
fun deq() = points.removeLast()
enq(point)
mark(point)
while (points.notEmpty()) {
point = deq()
// TODO if we found a power receiver, do something to it
for (x in getAdjacent(world.getWireGraphOf(point.x, point.y, wire)!!, point)) {
if (!isMarked(x)) {
mark(x)
enq(x)
}
}
} }
} }
} }
printdbg(this, "------------------------------------------")
} }
} }
private const val RIGHT = 1 private const val RIGHT = 1
private const val DOWN = 2 private const val DOWN = 2
private const val LEFT = 4 private const val LEFT = 4

View File

@@ -45,23 +45,20 @@ class WireGraphDebugger(originalID: ItemID) : GameItem(originalID) {
sb.clear() sb.clear()
Terrarum.ingame!!.world.getAllWiringGraph(mx, my)?.let { Terrarum.ingame!!.world.getAllWiringGraph(mx, my)?.forEach { (itemID, simCell) ->
it.forEach { (itemID, simCell) -> if (sb.isNotEmpty()) sb.append('\n')
if (sb.isNotEmpty()) sb.append('\n')
val connexionIcon = (simCell.connections + 0xE0A0).toChar()
val wireName = WireCodex[itemID].nameKey
val connexionIcon = (simCell.connections + 0xE0A0).toChar() val emit = simCell.emitState
val wireName = WireCodex[itemID].nameKey val recv = simCell.recvStates
val emit = simCell.emitState sb.append("$connexionIcon $wireName")
val recv = simCell.recvStates sb.append("\nE: $emit")
recv.forEach {
sb.append("$connexionIcon $wireName") val src = Terrarum.ingame!!.world.getWireEmitStateOf(it.src.x, it.src.y, itemID)!!
sb.append("\nE: $emit") sb.append("\nR: $src $EMDASH d ${it.dist}")
recv.forEach {
val src = Terrarum.ingame!!.world.getWireEmitStateOf(it.src.x, it.src.y, itemID)!!
sb.append("\nR: $src $EMDASH d ${it.dist}")
}
} }
} }