How do I cascade my powerlines

0 favourites
  • 7 posts
  • So I'm making a Sim City style game, and I've gotten stuck on this part.

    Essentially what needs to happen is that when the power lines are connected to the blue block (power plant) they will cascade down the line to give a value of 1 or On to each of the subsequent power lines along the way. I've tried six ways from Sunday, and still can't seem to get it right. In each test, the power line seems to inherit the value from the surrounding ones, which is fine, but when I bulldoze the middle of a power line set it still retains the previous value and doesn't give a new value to all unconnected power lines (ideally a value of 0 or Off)

    Can someone please take a look and see if you can solve it, as it's the only thing holding up further production of the game :'(

  • I am assuming you have it set so the first power line instance sets itself to powered if its connected to a plant and then each one sets its variable to powered if the one next to it is powered?

    If this is the case you would simply need a global running event every 0.1 seconds or so that set all power lines to unpowered. The powered ones would instantly repower and the unconnected ones would be set to unpowered...

  • I looked into that, but it would cause the game to run very slow.

    Ideally, this calculation would happen only when things are destroyed and the variations I've tried end up with everything being reset.

    I've tried it and set it to effect only when the bulldozer is used, and every 1 second to recheck for power connections, and this is the result.

    https://dl.dropboxusercontent.com/u/108 ... index.html

  • Let me start by saying... THAT LOOKS AWESOME!

    The original SimCity and its later versions all had a small delay when building lost and gained power, I am sure it was for the reasons you speak of, overhead. A periodic check for connection will not significantly affect gameplay. Could you not make is so it only reset the power grid when the bulldozer killed a power line or power transmitting object instead of every time its used?

    Also make sure you are working in reverse on your power, ie. its shouldn't be powered until it has no power, it should be un-powered until it has power... ie. make sure everything is being set to un-powered state periodically until its state is then changed to powered as opposed to just setting there until its powered... this will help avoid overlooked variable changes that cause all kind of silliness.

  • Hey, emoaeden.

    I have to start by seconding chrisinfinger's sentiment. Very cool looking game.

    I can't be sure, but the problem you're running into might have two parts.

    Firstly, while you are checking each power line segment, you may not be checking them in an order that propagates power the way you want.

    Secondly, determining connectivity, or a lack of connectivity, may not be possible by making a single top-to-bottom left-to-right pass over all the tiles.

    Tile checking order:

    To illustrate what I mean through the power of ASCII art,

    Suppose we have a power plant (represented by "#"), and a chain of power line segments (represented by 0 or 1 depending on powered state.)

    From here on, I'll call the power plant a "plant" and each power line segment a "seg".

    Plant on left, with five powered segs.

    #11111

    Now I may be interpreting the capx events wrong, but it looks like there's a nested XY loop that checks every cell, starting from the top-left, moving top to bottom in columns, and moving left to right from column to column. As the loop runs, for each cell, if that cell is powered, then power is propagated to the cardinally adjacent cells.

    I think this may mean that power will propagate asymmetrically, moving much faster from top to bottom than from bottom to top.

    Consider the following 1-dimentional example in which we loop through segs from left to right. The act of running a loop, until all loop iterations are complete, I will refer to as a single "pass".

    Start: #00000 (6 tiles so we will do 6 steps inside each pass.)

    ---- Pass 1:

    index 0: #10000

    index 1: #11000

    index 2: #11100

    index 3: #11110

    index 4: #11111

    index 5: #11111

    ---- Done in 1 pass.

    Now, consider a case where the plant is on the right instead of the left. Note that the loop still steps from left to right:

    Start: 00000# (6 tiles so we will do 6 steps inside each pass.)

    ---- Pass 1:

    index 0: 00000#

    index 1: 00000#

    index 2: 00000#

    index 3: 00000#

    index 4: 00000#

    index 5: 00001#

    ---- Pass 2:

    index 0: 00001#

    index 1: 00001#

    index 2: 00001#

    index 3: 00001#

    index 4: 00011#

    index 5: 00011#

    ---- Pass 3:

    index 0: 00011#

    index 1: 00011#

    index 2: 00011#

    index 3: 00111#

    index 4: 00111#

    index 5: 00111#

    ...

    ---- Pass 4:

    ...

    ---- Pass 5:

    ...

    index 5: 11111#

    Done in 5 passes.

    So it takes much longer to propagate power against the direction the loop is stepping. In the above cases, if you do a pass every 5 seconds, then it will take 5 seconds to propagate power from left-to-right, and it will take 25 seconds to propagate power right-to-left, over the same distance. If the power line was 20 segments long then it would still take 5 seconds to propagate moving right, and 100 seconds to propagate moving left.

    This might be part of the strange behavior you're seeing.

    Connectivity checking issue:

    So the other issue is determining connectivity.

    The problem here is that I don't think you can determine connectivity in a single top-to-bottom left-to-right pass. In the example above, when the power is advancing against the loop stepping direction, a single pass only advances powered status by a single tile, and it takes multiple subsequent passes to complete the propagation. (Again, a pass is not a single loop step, it's the processing of all tiles once.)

    In theory, every time a seg was destroyed, you could set every tile to un-powered, and then immediately run a number of full passes equal to the number of power line segs in the game, and while that would mark all power lines correctly when it finally completed, it would be prohibitively time consuming.

    Assuming I'm thinking about this right, (and I may not be) below is an example of why we can't solve connectivity in a single pass.

    Suppose you destroy a seg in the middle of a chain of powered segs,

    going from this

    #11111

    to this

    #_1111 (with the underscore "_" representing the bulldozed seg.)

    You now have 4 isolated segs in a chain, all marked as being powered.

    The problem is, when making a pass over all the tiles, how do you know if a seg should be un-powered?

    That is, suppose you're in the loop, stepping through tiles,

    index 0: #_1111

    index 1: #_1111

    index 2: #_1111 (we arrive at the left end of the isolated chain)

    and you come to the left end seg of that chain of 4 segs. It's marked as powered. How would you be able to tell if it shouldn't be? Well, it's not connected to a plant, but it *is* connected to another powered seg. Inside the loop, you can't tell whether the chain is powered from the other end, so you can't tell whether it should be powered or un-powered.

    That is, you could be dealing with this case,

    index 2: #_1111#

    With a plant on the right-hand end that seg could have a legitimate reason for being powered. There's no way to know inside the loop, because we can only check the neighboring segs.

    As an interesting aside, Minecraft has a very similar problem. Leaf blocks are "powered" by log blocks. A leaf block is only immune to decay if it was connected to a log block, or if it is connected through a chain of leaf blocks to a log block. In this sense it is exactly what you're trying to solve, but in a 3D grid instead of a 2D grid. Verifying that a leaf block is connected to a log block through a chain of leaf blocks involves path finding through neighboring leaf blocks to see if a path exists. Minecraft also has a max radius from log blocks (4), beyond which it doesn't bother doing any path finding, and instead a too-distant leaf block is simply doomed to decay.

    Connectivity checking - possible solution:

    In order to quickly determine connectivity, you might be able to use a "backtracking" algorithm.

    It would work kind of like this:

    Set all segs to un-powered.

    For each power plant:

    Start walking along a chain of segs coming out of it, marking each segment "powered" as you go.

    Every time you come to a branch (e.g. T-intersection) you put the "hub" tile's coords on a stack. Now you pick one of its un-powered branching tiles and start walking along that chain.

    If you reach a dead end, then pop the last "hub" tile off the stack (if one exists) and jump ("backtrack") directly back to that tile, and continue walking along the next un-powered branch. (Note: If it doesn't have an un-powered branch then treat it just like a dead end.)

    Eventually you'll have hit every dead end, and followed every branch, and there will be nothing left to pop off the stack.

    If you check every power plant, this way, when you're done, the only power line segs that will be un-powered will be those with no connectivity to a plant.

    If two power plants are connected to each other by a chain of segs, then the first power plant check will leave all those segs marked "powered" so the second power plant check will end instantly in a dead end, which is good, because you don't have to re-check any segs.

    Okay, sorry for the lengthy post. The more I started thinking about it the more I realized it's a pretty interesting problem.

    Hope that helps at all.

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • "I looked into that, but it would cause the game to run very slow."

    No, it would not.

    on ever .1 seconds {

    power input on ? power on : power off

    }

    Is barely a blip. Unless you have an absurd number of powerlines of course, but a few hundred of these calls isn't going to make a big difference.

  • This is the perfect scenario where recursivity seems more intuitive than the classic iterative approach. Here, I modified your capx to integrate recursive power propagation. I added a visual representation for tiles with power so it's easily noticeable that the power line behave like you want them to.

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)