Logic World Wednesdays: The Zero-Tick Edition

by @MouseHatGamesDeveloper1 year ago (edited1 year ago)

Blazing Fast Relays: The Linker Layer - Jimmy

Relays are extremely useful components, but they’ve also – since their original implementation – been the slowest components in the game to simulate.

Relays used to work using the same systems that regular peg-wire connections used. When a relay “opened”, it would create an invisible secret wire between its two side pegs, then the cached graph of the simulation would be recalculated. When a relay “closed”, it would destroy that invisible secret wire, and the cached graph of the simulation would be recalculated once again.

Unfortunately, this approach was very slow. To update the simulation graph, every connected peg and wire needs to be walked through and dealt with, and a bunch of node objects need to be created and destroyed. The system is designed to make running a simulation on the graph blazing fast; modifying the graph is the part with low performance, because it’s caching tons of information about the graph state. The performance is perfectly adequate for any reasonable modification you’d make while building, but when you have thousands of Relays updating thousands of times per second each, it’s simply way too slow.

That, of course, sucks. You should be able to build giant Relay-heavy contraptions and run them at high tickrates. This week I had a goal of making Relays way faster. I thought long and hard about how to do it, and I’m happy to say that I’ve found a pretty excellent solution.

On top of the existing circuit graph, I’ve added another layer that stores information about instant connections between different nodes of the graph. I call this the “Linker layer.” After the regular circuit simulation update, the Linker layer propagates signals between connected nodes. If one part of the graph is in the On state, the Linker layer will propagate that signal to its connected nodes, and then to those nodes’ connected nodes, etc.

The benefit of the Linker layer is that it’s extremely fast to modify. Compared to everything I described above for modifications to the Graph layer, the Linker layer is modified just by adding or removing a reference connecting two nodes of the graph. It’s somewhat slower to propagate signals through the Linker layer – after all, the Graph layer is hyper-optimized for this – but it’s orders of magnitude faster to make modifications to the Linker layer.

That’s a very high level overview of what’s happening, but hopefully it makes sense to you!

I haven’t done any formal benchmarking because I am very lazy, but I tried out a few test cases with Relays and observed speedups of 250x - 500x. Relay circuitry is now only about 1.5x-2x slower than “normal” circuitry. I’m extremely happy with this improvement, and there are definitely opportunities for further speedups so things will only get better from here.

But, as I was working on these new systems, something extraordinary dawned on me. The Linker layer is lovely and fast at propagating signals through two-way instant connections. But, there’s no reason it couldn’t also work for one-way instant connections…

Zero-Tick Diodes - Jimmy

I’ve finally done it. Zero-tick, instant, one-way signal transmission in Logic World, without a major performance impact!

I am so freaking pumped about this. I had accepted long ago that I just couldn’t figure out a way to have reasonably-performant instant diodes, and I would have to live with a Logic World missing that feature. But as it turns out, I’m actually incredibly fucking awesome, because I found a way to do it after all. (Some details on how it works are described in the section above, if you’re curious but skipped it)

In light of this glorious new development, I have a few questions for you:

What to do about Exclusive Pegs

After I’d initially determined that performant instant diodes were not practical, I came up with a sort of halfway solution that allowed for some of the same types of circuits. This feature was called Exclusive Pegs; here’s a video of how they work, one of the first Logic World dev videos I ever made. Essentially, it allowed for instant diode transmission but only to a single peg.

Now that we have true, universal instant diodes, I am planning to remove Exclusive Pegs. I want to simplify the gameplay, and have only one way of achieving this functionality. Exclusive Pegs have been a notoriously confusing feature for folks, but in comparison the instant diode components are much easier to intuitively understand. I’ve also seen some testers accidentally make an input exclusive, but not realize it, and get confused about why their circuit doesn’t work. It’s often hard to tell if an input is exclusive, especially in very dense or layered circuits. Plus, removing them would simplify a lot of code, from many parts of the game (simulation/rendering/saving/etc).

For all these reasons, I feel good about removing Exclusive Pegs now. However, they’re a pretty major feature, and they were one of the first promises I made about Logic World. So before I do it, I want to check with you: Do you think Exclusive Pegs should remain in the game, even though we have instant diodes now? If so, why?

What the heck do we call these sexy bois?

What should the name of this new component be? I’ve been referring to it as an “instant diode” here, but I don’t want to use that terminology in the game. “Diode” is a name explicitly about electronics, and Logic World is explicitly not a simulation of electricity. Currently in the game it’s called a “Lock”, but I’m not satisfied with that name either; it feels too vague, like it could reasonably refer to a bunch of other functionality.

Do you have a suggestion for what to name this new component? Here are some more things to think about:

  • I like names that are descriptive, but a little bit mysterious and evocative. The component for making music sounds is the Singer; the component for generating random values is called the Oracle. Stuff like that is cool.
  • A component name should be snappy, memorable, and distinctive.

Here are some terms I’ve been considering:

  • Lock
  • Hatch
  • Hatchway
  • Gateway
  • Spigot
  • Scuttle
  • Bouncer
  • Valve
  • Pipe
  • Stopper
  • Impasse
  • Clog
  • Router
  • Avenue
  • Shortcut

Let me know if any of those strike you as particularly good, or if you have alternative ideas :)

Server-Side Rendering - Felipe

The logicworld.net website is a Single-Page Application, meaning that there’s only one page that gets updated with the required content whenever the user clicks on a link. This has many benefits, like reduced bandwidth usage, snappier navigation, etc, but there’s the drawback of requiring JavaScript to be enabled in order to be able to browse and interact with the site.

However, you may have noticed that the site feels a bit different now. The site is now using a technique called Server-Side Rendering (SSR for short), which means that instead of sending a blank “template” page to the browser for it to fill in, the server now sends a page with all the appropriate HTML and styles necessary to view the page just like when the browser renders it. This has many advantages, but the most significant ones are improved SEO as any engine can now recognize the content without running any JavaScript, and dropping the requirement of JavaScript (note that it is still required for interactions like creating a comment, liking a post, etc).

For example, Discord can now recognize the contents of the post and even show the first image in the post:

discord embeds.png

The site works well right now, however it’s a little rough around the edges. Namely, there is sometimes a flash right after the page is loaded. I’m also tweaking the cache times in the server, so if you ever want to make sure you have the latest content you can press CTRL+R. I’ll keep improving it over the next few days, and please report any bugs you may find.

We’ll keep releasing these weekly updates right up until the game comes out. To make sure you don’t miss them, you can sign up for our newsletter. Be sure also to wishlist Logic World on Steam and join the official Discord.

See you next Wednesday!

More Logic World Wednesdays

@DaMastaCoda1 year ago

I like “valve” and it was what appeared in my head second. First I thought of one-way valve.

@JimmyDeveloper1 year ago

It’s a nice name, but I don’t like the implication that the signals are a fluid (they’re not). As you can read about in the followup, I decided on “buffer”.

@Irasozim1 year ago

I feel like Exclusive Pegs would do more harm than good in the long run. I also like “Bouncer” for the name of the component, and if I had to make my own for it I would suggest “Forcer”, because the component forces the signals to go one way.

@JimmyDeveloper1 year ago

I’m feeling the same way about exclusive pegs. Thanks for the thoughts on component names.

@vigilantehobo1 year ago

Some sucky suggestions. *Oneway *Ratchet (Don’t like this one a lot, Mechanical Engineering based) *Identity gate *Simplex

@vigilantehobo1 year ago


@shamus0301 year ago (edited1 year ago)

“Clog” and “Guard” are my favorite suggestions for the instant diode so far. Here are mine:

  • Turnstile
  • Excluder (comes from beekeeping!)
  • Barrier
  • “Check valve”, or maybe just “checker” or “check”
@JimmyDeveloper1 year ago

Oooh those are good, thank you!

@tokumei1 year ago (edited1 year ago)

Name ideas for the diode (largely based on anthropomorphisms like the Oracle and Singer):

A diode can also be described as a “buffer” - I like the way that sounds, but it has a second definition in software (data buffers) which might cause some confusion for people approaching this game with CS/software backgrounds as opposed to electrical and computer engineering. But I’ll use it for the rest of this comment to make it stick in your head :)

If I understand correctly, there’s still a drawback to the linker layer - the performance benefits break down when there’s a long chain of relays and/or buffers, because propagating updates each tick across all of them is going to be linear with respect to the length of the chain. While this may not be a problem for small circuits, I can imagine some builds where TPS might suffer (for example, using relays to implement instant carry on 64 or even 32 bit adders).

This is also a problem that I’m also working on solving for FlipFlop, to see if I can lower the complexity of those updates. I do like the 2-layer approach, something like that could be used to speed up graph updates for things like sockets, which connect and disconnect larger circuits when boards are moved, and I’m planning on having a socket-like component in FlipFlop. However because Logic World has dynamically-connecting components like relays (and also now asymmetric connections thanks to buffers), the optimization problem is definitely not as easy.

As for exclusive pegs, they would allow for more compact builds compared to buffers. Especially because the input peg for buffers isn’t exclusive, meaning you need 1 buffer per input wire, whereas with exclusive pegs, all of the wires can connect to the same peg. However I do like the idea of moving that functionality into an explicitly separate component.

In fact, it’d be interesting to make exclusive pegs into a standalone component, with a single exclusive input and an instant propagation, (or perhaps 1 tick if it needs balance). Actually, I think I just described an OR - like the AND gate component that already exists, the inputs are isolated from each other and from the output, unlike a “wire-OR”.

@JimmyDeveloper1 year ago

I really like “Guard” and “Gatekeeper”, thank you for the suggestions! Yeah, I thought about calling them Buffers, but I wanted to avoid confusion with data buffers. Perhaps I should reconsider, it’s a very pleasant name…

If I understand correctly, there’s still a drawback to the linker layer - the performance benefits break down when there’s a long chain of relays and/or buffers, because propagating updates each tick across all of them is going to be linear with respect to the length of the chain.

This is correct, but I’m honestly stunned by how fast it still is. Long chains result in a lot to do, but it’s a lot of extremely simple things to do.

As for exclusive pegs, they would allow for more compact builds compared to buffers.

This is true, but I’m okay with that. I think more spread-out circuits are better for gameplay anyway, as it’s easier to analyze them visually.

In fact, it’d be interesting to make exclusive pegs into a standalone component, with a single exclusive input and an instant propagation, (or perhaps 1 tick if it needs balance).

Hm, interesting. Thanks for the idea.

@tokumei1 year ago

Actually just thought of another name - “isolator”. Not sure which one I like better, but buffer and isolator are my top two suggestions.

@JimmyDeveloper1 year ago

Also a good one!