Change background image
  1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

The Integrated Circuits Guide Absolutely Nobody Asked For

Discussion in 'Tutorials & Information' started by Cheb Pomidorov, Sep 20, 2019.

  1. Cheb Pomidorov

    Cheb Pomidorov Bartender

    Hello kids, I'm Cheb and I'm here to teach you how to make Integrated Circuits. As the title says, nobody asked for it and nobody needs it, but that won't stop me from wasting your time and cluttering the Tutorials subforum with this mess until an admin removes it.
    I'll assume you have no experience with circuits and no knowledge of information technology principles/subjects such as Algorithms and Data Structures, Computer Architecture and Low-level programming. Not that I'm particularly fluent in those myself.
    While writing this guide I realised it's become less of a theoretical guide and more of a training dojo of sorts, so that's nice.

    DISCLAIMER
    There is already a Circuits guide on the /tg/station 13 wiki. Unlike this guide made specifically for Baystation 12, that guide has actual pictures, nice formatting, neat icons and cute little diagrams with arrows made in MS Paint. This guide has none of that, so if you must, here's the link:
    https://tgstation13.org/wiki/Guide_to_circuits
    (The link above is tiny on purpose).
    The only reason you should be reading this guide instead of that one is that /tg/ is bad. No wonder they removed circuits from their code.
    But really though, it's an alright guide, much superior in quality to this one.
    I will be showing some stuff that guide doesn't, so there's still some merit in reading this.
    For actual disclaimery stuff, you can use whatever circuits I show off here, not that I can stop you. Not that anyone would use the stuff I make.

    Chapter one: What's this then, eh?
    What are circuits?
    Unlike the usual items of the game like toolboxes, insulated gloves and water-potassium grenades, whose behaviour is coded into the game by some high-level nerds, circuits are entirely modular, flexible items made out of a multitude of ridiculously inflexible components. They are custom-built items to which you assign a behaviour of your choosing.
    Each circuit is made up of:
    • An assembly, a case which houses all your components. This is the first thing you decide on. Assemblies come in different sizes, and some have different functions. Assembly size determines the amount of components that can be placed inside, and increases the upper complexity limit.
      • Drones are the only ones capable of autonomous movement.
      • Wall-mounted assemblies can be... mounted on walls. Most others can only be fitted on floors.
      • The gun-shaped mechanism is the only one that isn't a drone AND can fire ranged weaponry.
    • The components, the modules that make the assembly do what you want it to do. There are power generation modules, item manipulation modules, pathfinding modules, arithmetic and logic, and others. Each component adds a certain amount of complexity to the assembly, which will prevent you from adding too many high-complexity components.
    • A battery, needed for the assembly to function and whose charge is consumed by its components.
    Research's Miscellanous Laboratory, Petrov's Equipment Storage and Robotics all contain a black metal box called an Integrated Circuit Printer, not to be confused with an Integrated Positronic Chassis. You can construct additional ICPs in the Protolathe. The printer performs two functions: printing and cloning.
    Printing refers to the creation of assemblies and components out of metal (steel). 25 sheets of steel fill up the ICP's metal reserves to capacity. Note that some components will require an Upgrade Disk available from R&D. You should be maxing out R&D anyway, so this is hardly a concern.
    Cloning refers to the creation of complete circuits using some incomprehensible code. The code is generated by using a Circuit Analyser tool on the completed assembly you want to clone. Cloning takes time, unless you obtain a Cloning Upgrade Disk from R&D and use it on the ICP, and metal.
    Get ahold of one, preferably fully upgraded. Fill it with metal, and you're good to go.
    You still need tools to perform your work, but these can be printed from the ICP in the appropriate section, aptly named Tools. The Big Three are:
    • Circuit Wirer: the most used, this allows you to connect the components together and actually setup your circuit. Essential.
    • Circuit Debugger: not just for debugging, this allows you to more easily assign values to your parametres, toggle components manually, and some other stuff. Not essential in most cases, but life would be hell without one.
    • Circuit Analyser: as mentioned, generates some code that you can save to some fancy .txt file on your computer (mine's called Soap's Shitty SS13 Sircuits.txt) and clone them in later rounds as you see fit. Not essential.
    Now navigate to the Arithmetic tab and print something like a Multiplication circuit. Examine it directly and you'll see a panel you'll learn to hate. It has two types of wires: data wires and pulse wires.
    • Data wires are the blue ones on the sides, and they come in two types.
      • Input wires are located at the left side and provide the input for the component. In the case of a Multiplication circuit, the wires represent the Multiplicand and the Multiplier (obviously in interchangeable order). Input wires must almost always contain some form of data for the component to function.
      • Output wires are on the right side and represent the output of the calculation performed, or the "state" of the component. They update every time the component is used. Whenever they update, even if their value remains the same, all data wires connected to them carry their value over to themselves. This is very important.
    • Pulse wires are the red ones and they also come in two types.
      • "Pulse in" wires receive a "pulse out" from some other component. Whenever a component is "pulsed in," it simply activates. That's all there is to it. In the multiplication example, it'd perform the operation and push the multiplication output to its output wire.
      • "Pulse out" wires send a pulse to another component's "pulse in" wire when certain conditions are met. These conditions are outlined on the component itself and are fairly obvious.
    A given component doesn't necessarily need to have any data wires, while some have like, 18. Same for pulse wires, they don't need to be there, but some components have more than two.
    The wires themselves can be connected together by a circuit wirer. The components need to be housed in an assembly to do this. Wires are disconnected by using the wirer in your hand, setting it to Disconnect mode. Note that you can do some tricks like wiring a component's output to its own input (useful) or wiring a component's output to another's output (not so much).
    And here's an explanation of most data types you'll be working with:

    All: this type is usually for input wires. You can provide such wires any type of input.
    Number: self-explanatory. I'm pretty sure the system can't make any floating point calculations, though, so you'll need to provide integers.
    Text: also known as String. Data of this type is enclosed in double quotation marks " ". Be aware that using the symbols [, ], { and } may make the circuit impossible to clone.
    List: a variable amount of data condensed into a single entity. One list may contain hundreds of values. These are, functionally, arrays of variable size. The "Lists" tab of the ICP provides components that work with lists.
    Boolean: a TRUE/FALSE value. You'll usually use the numbers 0 and 1 to set these to FALSE and TRUE respectively, but be aware that "" (empty string) and null (nonexistent value) also set it to FALSE, and anything else sets it to TRUE.
    Ref: this is a reference to an object. It can't be set manually: you either have to scan an object with the Circuit Debugger and copy its reference, or obtain a reference through other components, like sensors. Refs are usually provided by Input components and used by Manipulation components, but there are other categories that use them.

    The debugger is most useful for when certain data values, once set, are supposed to never be overwritten. Use the debugger in your hand to access a menu and enter a value into its internal memory, then use it on a data wire to write data to that wire.
    And speaking of the debugger, there's an oft overlooked trick: you can use it to pulse an input wire on a given component and, provided the assembly has a power cell installed, it'll activate the component.
    I used the word "component" too many times

    Chapter Two: Electronic Boogaloo
    If you read the previous part, you should have at least a basic understanding of how this stuff works. The rest must come from experience, so here are some examples you can try, starting with the most banal and increasing in complexity. This chapter is the core of the guide, and teaches several advanced techniques.
    I tried to come up with some challenges, but my circuit ideas are admittedly lacking.
    This chapter won't teach any basic stuff like Universal Translators, ID access broadcasters, and other common circuits. The point of this chapter is to teach technique rather than provide examples. Problem solving is an inherent part of integrated circuits, so you're encouraged to do these challenges and come up with your own solutions.

    1: Basic flashlight
    Flashlights are possibly the easiest circuits you can make, and with good reason. There's very little room to mess up all the wiring (and in this case, there's literally no room to mess up the wiring). Make a simple white flashlight one can toggle on or off with a button.
    In this case, the "button" and "toggle button" components are interchangeable. Their respective PULSE OUT wires do the exact same thing. The only difference there is between the two is that the toggle button has an extra output wire which isn't useful for this example.
    Not trying to be a big meanie, but if you need the solution for this example, perhaps circuits aren't for you.
    Code:
    {"assembly":{"type":"type-a electronic assembly"},"components":[{"type":"button","name":"Light"},{"type":"light","name":"Output"}],"wires":[[[1,"A",1],[2,"A",1]]]}

    2: Emergency flashlight
    Useful for drawing attention to yourself during a crisis, especially if the power is out. Help the EMT find your dying-in-the-dark self more easily with this circuit!
    Make a circuit that, if a button is toggled on, sends out a pulse every second, toggling a red light on and off repeatedly.
    The Advanced Light component accepts a <COLOUR> data type. It's a very specific type of string: a "#" followed by a 6-digit hexadecimal number. The colour red would be #FF0000.
    Code:
    {"assembly":{"type":"type-a electronic assembly"},"components":[{"type":"toggle button","name":"Light"},{"type":"custom ticker","name":"Tick","inputs":[[2,0,10]]},{"type":"advanced light","name":"Output","inputs":[[1,0,"#FF0000"],[2,0,100]]}],"wires":[[[1,"O",1],[2,"I",1]],[[2,"A",1],[3,"A",1]]]}
    The debugger is used 3 times here.

    2.5: For Nerds, Improved Emergency flashlight
    Unfortunately, toggling off the toggle button of the above circuit doesn't necessarily mean the light will stay off: it may stay on instead. Fix this by adding some logic elements. When the button is toggled, the light, if off, should stay off, whereas if it's on, it should turn off.
    The light being turned off should occur when the button is toggled off AND the light is still on. That AND is a hint.
    The advanced light, unlike the toggle button, doesn't provide an output wire indicating its current state. You'll need to figure that out in some other way, that may be logic, arithmetic or memory operations, which are all valid solutions (as long as it works!)
    Code:
    {"assembly":{"type":"type-a electronic assembly"},"components":[{"type":"toggle button","name":"Light"},{"type":"custom ticker","name":"Tick","inputs":[[2,0,10]]},{"type":"advanced light","name":"Output","inputs":[[1,0,"#FF0000"],[2,0,100]]},{"type":"JK latch","name":"ToggleState","inputs":[[1,0,1],[2,0,1]]},{"type":"not gate","name":"ButtonIsOff","inputs":[[1,0,0]]},{"type":"and gate","name":"ButtonIsOffAndLightIsOn","inputs":[[1,0,1],[2,0,0]]}],"wires":[[[1,"O",1],[2,"I",1]],[[1,"O",1],[5,"I",1]],[[1,"A",1],[5,"A",1]],[[2,"A",1],[3,"A",1]],[[2,"A",1],[4,"A",1]],[[3,"A",1],[6,"A",2]],[[4,"O",1],[6,"I",2]],[[4,"A",1],[6,"A",2]],[[5,"O",1],[6,"I",1]],[[5,"A",2],[6,"A",1]]]}
    This one is tricky as it uses a very seldom used component called a JK Latch. It's not exactly the most proper way to use the Latch, but it gets the job done. If J and K are both TRUE, then the JK Latch toggles its state every time it's pulsed. Q is its state, !Q is the state's negation (they're always logical opposites).
    Other solutions include having arithmetic components switch between 0 and 1, or having memory components, set to 0 and 1, switch data one to another (although swapping requires the use of a temporary variable).

    3: Hydroponics Uprooter
    Hydroponics/Xenobotany can be tedious because plants and trees take many hits to cut. In a similar manner to the circuit directly above, make a handheld tool that combines the functionality of a mini hoe and a hatchet. A toggle button should toggle whether the tool removes weeds or plants. Here's a secret: removing plants with an integrated circuit removes weeds as well.
    You'll need to use something similar to the former example in order to track the status (weed/plant). You'll also need some kind of way to remember the 1 and 2 (1 is the selector for weeds and 2 is the selector for plants). Finding out the best way to do so is the challenge here.
    Code:
    {"assembly":{"type":"type-a electronic assembly"},"components":[{"type":"sensor","name":"GetRef"},{"type":"constant chip","name":"UprootWeeds","special":1},{"type":"constant chip","name":"UprootPlants","special":2},{"type":"plant manipulation module","name":"Uproot","inputs":[[2,0,1]]},{"type":"toggle button","name":"Remove Plants"},{"type":"JK latch","name":"ToggleState","inputs":[[1,0,1],[2,0,1]]}],"wires":[[[1,"O",1],[4,"I",1]],[[1,"A",1],[4,"A",1]],[[2,"O",1],[4,"I",2]],[[2,"A",1],[6,"A",3]],[[3,"O",1],[4,"I",2]],[[3,"A",1],[6,"A",2]],[[5,"A",1],[6,"A",1]]]}
    JK Latch returns, and it's still not used very elegantly, but I'd say it's a bit better. What's new here is the constant chip, which is a memory component that's supposed to be used with a debugger. Don't let the description fool you: overwriting its output data is as simple as connecting it to some other component's output. Don't do that, as it defeats the purpose of a constant chip.
    As circuits become more and more complex, the usage of memory will become more and more relevant and necessary.

    4: Countdown
    While the above circuits have some degree of usefulness, this one is not of that kind, but teaches an important technique. Starting at n=10, make it so that every n tenths of a second, the following occurs:
    1. A text message is stated aloud/a light is toggled/whatever you can imagine, and
    2. n is decremented by 1.
    When n reaches 0, reset it back to 10.
    The two crucial procedures here are the one that decrements n and the one that resets n when n=0. As with every single solvable problem in existence, there are infinite solutions, but it makes sense to strive for a simple and efficient one.
    Code:
    {"assembly":{"type":"type-a electronic assembly"},"components":[{"type":"toggle button","name":"Power"},{"type":"constant chip","name":"TEN","special":10},{"type":"custom ticker","name":"Tick","inputs":[[2,0,10]]},{"type":"light","name":"Output"},{"type":"subtraction circuit","name":"Count","inputs":[[1,0,10],[2,0,1]]},{"type":"less than or equal gate","name":"CountIsZero","inputs":[[1,0,5],[2,0,0]]}],"wires":[[[1,"O",1],[3,"I",1]],[[2,"O",1],[3,"I",2]],[[2,"O",1],[5,"I",1]],[[2,"A",1],[6,"A",2]],[[3,"I",2],[5,"O",1]],[[3,"A",1],[4,"A",1]],[[3,"A",1],[5,"A",1]],[[5,"I",1],[5,"O",1]],[[5,"O",1],[6,"I",1]],[[5,"A",2],[6,"A",1]]]}
    I used a light in this case. It doesn't look the best, but it does what it's supposed to. Central to the whole thing is the subtraction component I labelled "Count." Note how its output wire is connected to its own input wire.

    5: Renald Dalton is a legend
    Arkter, the guy who plays Renald Dalton, hates lists. So let's reference him in this list example. First, clone this circuit:
    Code:
    {"assembly":{"type":"type-a electronic assembly"},"components":[{"type":"at circuit","inputs":[[1,0,["Renald","Dalton","is","a","legend."]]]}]}
    The task here is to make the circuit say the phrase contained in the list, not as a single string, but as 5 different strings. There should be a delay of 1 second before one string being spoken and the next. This time, it should start saying the phrase at the press of a button, and only say it once (No looping). Pressing the button again will start the phrase from the beginning.
    The preinstalled component is essential in this task.
    Code:
    {"assembly":{"type":"type-a electronic assembly"},"components":[{"type":"constant chip","name":"ZERO","special":0},{"type":"button","name":"Speak"},{"type":"addition circuit","name":"Count","inputs":[[2,0,1]]},{"type":"at circuit","name":"GetNext","inputs":[[1,0,["Renald","Dalton","is","a","legend."]],[2,0,0]]},{"type":"text-to-speech circuit","name":"Output"},{"type":"greater than or equal gate","name":"IterationOver","inputs":[[2,0,5]]},{"type":"one-sec delay circuit","name":"Delay"}],"wires":[[[1,"O",1],[3,"I",1]],[[1,"A",1],[2,"A",1]],[[2,"A",1],[3,"A",1]],[[3,"I",1],[3,"O",1]],[[3,"O",1],[4,"I",2]],[[3,"O",1],[6,"I",1]],[[3,"A",1],[7,"A",2]],[[3,"A",2],[4,"A",1]],[[4,"O",1],[5,"I",1]],[[4,"A",2],[5,"A",1]],[[4,"A",2],[6,"A",1]],[[6,"A",3],[7,"A",1]]]}
    Finally, something larger than 6 components. What we've built is called an iterator, as it accesses all elements of a list/all characters of a string. Of particular note is the fact that the "Count" number isn't just used for iteration, but also for access to the list (by index). String manipulation components are found under the Conversion tab.

    6: Lights, for the last time
    I know flashlights have become cliché and quite boring already, but this is a nice challenge. Make it so a circuit contains an advanced light that, every 0.6 seconds, changes its colour to a randomly generated one. Try to use as few components as possible.
    As in examples 2 and 3, you need a string formed by a "#" followed by 6 hexadecimal digits. These digits must be randomly generated, but the only random generator in our repertoire is one for numbers. That doesn't mean it can't be used, if a way is found to quickly convert a [0, 15] integer into a hexadecimal digit.
    The Multiplexer and Demultiplexer are useful.
    Code:
    {"assembly":{"type":"type-a electronic assembly"},"components":[{"type":"constant chip","name":"ZERO","special":0},{"type":"button","name":"Light"},{"type":"addition circuit","name":"Count","inputs":[[1,0,3],[2,0,1]]},{"type":"random number generator circuit","name":"RandomNum","inputs":[[1,0,1],[2,0,16]]},{"type":"sixteen multiplexer","name":"Mux","inputs":[[1,0,2],[2,0,"0"],[3,0,"1"],[4,0,"2"],[5,0,"3"],[6,0,"4"],[7,0,"5"],[8,0,"6"],[9,0,"7"],[10,0,"8"],[11,0,"9"],[12,0,"a"],[13,0,"b"],[14,0,"c"],[15,0,"d"],[16,0,"e"],[17,0,"f"]]},{"type":"eight demultiplexer","name":"Demux","inputs":[[1,0,3],[2,0,"1"]]},{"type":"greater than or equal gate","name":"IterationIsOver","inputs":[[1,0,3],[2,0,6]]},{"type":"tenth-sec delay circuit","name":"Delay"},{"type":"concatenator","name":"Concatenate","inputs":[[1,0,"#"],[2,0,"1"],[3,0,"1"],[4,0,"1"],[5,0,"e"],[6,0,"1"],[7,0,"0"]]},{"type":"advanced light","name":"Output","inputs":[[1,0,"#47EE10"],[2,0,100]]}],"wires":[[[1,"O",1],[3,"I",1]],[[1,"A",1],[2,"A",1]],[[1,"A",1],[7,"A",2]],[[2,"A",1],[3,"A",1]],[[2,"A",1],[10,"A",1]],[[3,"I",1],[3,"O",1]],[[3,"O",1],[6,"I",1]],[[3,"O",1],[7,"I",1]],[[3,"A",1],[8,"A",2]],[[3,"A",2],[4,"A",1]],[[4,"O",1],[5,"I",1]],[[4,"A",2],[5,"A",1]],[[5,"O",1],[6,"I",2]],[[5,"A",2],[6,"A",1]],[[6,"O",1],[9,"I",2]],[[6,"O",2],[9,"I",3]],[[6,"O",3],[9,"I",4]],[[6,"O",4],[9,"I",5]],[[6,"O",5],[9,"I",6]],[[6,"O",6],[9,"I",7]],[[6,"A",2],[7,"A",1]],[[7,"A",2],[9,"A",1]],[[7,"A",2],[8,"A",1]],[[7,"A",3],[8,"A",1]],[[9,"O",1],[10,"I",1]]]}
    This one uses both the multiplexer and the demultiplexer to great effect. The multiplexer and the number generator could, in theory, be replaced with a "pick circuit" drawing from a list[16] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"}, but said list would first have to be constructed, which is a great tedium and uses at least 1 extra component.
    Why 0.6 seconds? Because a 0.1 second delay is necessary for each iteration.

    7: For Nerds, Caesar Cypher
    My favourite circuits are ones that operate on strings and do something fancy with them. Construct a list[26] containing all the letters of the alphabet, in order. Then implement a Caesar cypher in such a way that the "letter shift" is configurable by the user (it can be set manually to any positive integer). Allow the user to input a string that will be encoded by the cypher. Iterate over the entire string, leave the values that aren't contained in the alphabet list unchanged (push them to the output without making any alterations). Mind the lowercase/uppercase distinction.
    The biggest problem here is that list/string indexing always starts at 1, like in DM. Explaining why this is retarded is best left for another time, but just remember that the allowed indexes are not between 0 and 25 but between 1 and 26.
    A lot of times, you'll be pushing several data values to the same input wire. It's up to you to decide when and how these values should overwrite each other, depending on time, condition, or something else entirely. Oftentimes, you'll push some data to input, but only perform an operation on that particular value if it suits you (otherwise you'll wait until the value is overwritten by something else and then pulse the component).
    If the example's taking you a lot of time and many components, and you're frequently stumped, there's a reason the header says "For Nerds." Don't worry too much about it, as the problem is inherently more complex than any other encountered so far in this guide.
    Code:
    {"assembly":{"type":"type-a electronic assembly"},"components":[{"type":"constant chip","name":"NULL"},{"type":"constant chip","name":"ZERO","special":0},{"type":"append circuit","name":"Alphabet","inputs":[[1,0,["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]],[2,0,"z"]]},{"type":"number pad","name":"Shift"},{"type":"text pad","name":"Input"},{"type":"lowercase string converter","name":"StringLowercase","inputs":[[1,0,"TEST!"]]},{"type":"get length","name":"GetLength","inputs":[[1,0,"TEST!"]]},{"type":"addition circuit","name":"Count","inputs":[[1,0,6],[2,0,1]]},{"type":"less than or equal gate","name":"ContinueIteration","inputs":[[1,0,6],[2,0,5]]},{"type":"indexer","name":"GetChar","inputs":[[1,0,"test!"],[2,0,6]]},{"type":"search circuit","name":"GetCharIndex","inputs":[[1,0,["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]],[2,0,"!"]]},{"type":"addition circuit","name":"AddToIndex","inputs":[[1,0,0],[2,0,7357]]},{"type":"subtraction circuit","name":"DecrementIndex","inputs":[[1,0,7377],[2,0,1]]},{"type":"greater than gate","name":"GreaterThanTwentyFive","inputs":[[1,0,7376],[2,0,25]]},{"type":"modulo circuit","name":"GetModulo","inputs":[[1,0,7376],[2,0,26]]},{"type":"addition circuit","name":"IncrementModulo","inputs":[[1,0,18],[2,0,1]]},{"type":"at circuit","name":"GetAlphabetLetter","inputs":[[1,0,["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]],[2,0,19]]},{"type":"small concatenator","name":"Concatenate","inputs":[[1,0,"sdrs!"],[2,0,"!"]]},{"type":"custom delay circuit","name":"Delay","inputs":[[1,0,10]]},{"type":"small screen","name":"Output","inputs":[[1,0,"sdrs!"]]}],"wires":[[[1,"O",1],[18,"I",1]],[[1,"A",1],[5,"A",1]],[[2,"O",1],[8,"I",1]],[[2,"A",1],[5,"A",1]],[[3,"I",1],[3,"O",1]],[[3,"O",1],[17,"I",1]],[[3,"O",1],[11,"I",1]],[[4,"O",1],[12,"I",2]],[[5,"O",1],[7,"I",1]],[[5,"O",1],[6,"I",1]],[[5,"A",1],[7,"A",1]],[[5,"A",1],[6,"A",1]],[[6,"O",1],[10,"I",1]],[[7,"O",1],[9,"I",2]],[[7,"A",2],[8,"A",1]],[[8,"I",1],[8,"O",1]],[[8,"O",1],[10,"I",2]],[[8,"O",1],[9,"I",1]],[[8,"A",1],[19,"A",2]],[[8,"A",2],[9,"A",1]],[[9,"A",2],[10,"A",1]],[[9,"A",3],[20,"A",1]],[[10,"O",1],[11,"I",2]],[[10,"O",1],[18,"I",2]],[[10,"A",2],[11,"A",1]],[[11,"O",1],[12,"I",1]],[[11,"A",2],[12,"A",1]],[[11,"A",3],[18,"A",1]],[[12,"O",1],[13,"I",1]],[[12,"O",1],[17,"I",2]],[[12,"A",2],[13,"A",1]],[[13,"O",1],[14,"I",1]],[[13,"O",1],[15,"I",1]],[[13,"A",2],[14,"A",1]],[[14,"A",2],[15,"A",1]],[[14,"A",3],[17,"A",1]],[[15,"O",1],[16,"I",1]],[[15,"A",2],[16,"A",1]],[[16,"O",1],[17,"I",2]],[[16,"A",2],[17,"A",1]],[[17,"O",1],[18,"I",2]],[[17,"A",2],[18,"A",1]],[[18,"I",1],[18,"O",1]],[[18,"O",1],[20,"I",1]],[[18,"A",2],[19,"A",1]]]}
    What a clusterfuck. The Modulo component is vital in ensuring cyclicity, but the indexing starting at 1 doesn't work terribly well with it.
    Problem being: n mod 26 should never return 0, because it's an invalid index. The workaround is pretending momentarily that we're working in a system where indexing does start at 0 (that's why the value is decremented,) get our result, and convert it back to the "lists start at 1" hell.
    The delay component is set to 1 second, but it could also be set to 0.1 seconds. The delay must be there due to the fact that each and every component has a pulse cooldown of at least 0.1 seconds (10 seconds at most, to my understanding), during which it cannot be pulsed again.

    8: Radio
    Up until now we've worked with single, standalone assemblies, but there are many designs and concepts that could benefit from having 2 or more assemblies interact with each other. Build a radio device with a microphone and text-to-speech capabilities. Clone the device. It should be able to transmit to, and receive messages from, any of its clones.
    This is an incredibly simple device, but it's the first device where the advanced integrated signaller is needed.
    Code:
    {"assembly":{"type":"type-a electronic assembly"},"components":[{"type":"microphone","name":"Input"},{"type":"advanced integrated signaler","name":"SendReceive","inputs":[[1,0,1357],[2,0,"Radio"]]},{"type":"text-to-speech circuit","name":"Output"}],"wires":[[[1,"O",2],[2,"I",3]],[[1,"A",1],[2,"A",1]],[[2,"O",1],[3,"I",1]],[[2,"A",3],[3,"A",1]]]}
    This implementation is annoying in-game, but you could improve on the radio's concept by adding toggleable microphones, microphones that only transmit if a certain word or phrase is heard, and other improvements you can think of.
    Beware: you'll likely need to use the debugger to overwrite the "id tag" variable (just write the same value to it) after cloning. This is a bug we have to live with for now. Just remember that if nothing's working despite the cell being charged and all the wires being correctly placed, you probably just need to update the "id tag."

    9: Drones
    Drones are assemblies capable of movement if a "locomotion circuit" is installed. There's only so much a handheld/stationary assembly can do, so movement is a pretty big deal. There are infinite ways to make a drone move, but the simplest, both in usage and in implementation, is the remote-controlled drone that moves to the tile/object/character you point the remote towards. Make a drone base, which you can later clone and add new functionality to, using the point-to-tile method.
    The ranged scanner is a very high-complexity item, adding 36 to the assembly's complexity. As a general rule, the remote should only have inputs and signallers. Leave all the arithmetic/logic operations to the drone itself, as the drone is a size 75 and complexity 225 assembly. It also makes the whole mess a lot more organised and comprehensible.
    The advanced integrated signaller only accepts a string for its "command" variable. However, we're scanning a ref here. If only there were a way to encode a ref into a string.
    Remote:
    Code:
    {"assembly":{"type":"type-a electronic assembly"},"components":[{"type":"ranged sensor","name":"GetRef"},{"type":"reference encoder","name":"RefEncode"},{"type":"advanced integrated signaler","name":"RefSignal","inputs":[[1,0,1357],[2,0,"Ref"]]}],"wires":[[[1,"O",1],[2,"I",1]],[[1,"A",1],[2,"A",1]],[[2,"O",1],[3,"I",3]],[[2,"A",2],[3,"A",1]]]}
    Drone:
    Code:
    {"assembly":{"type":"type-a electronic drone"},"components":[{"type":"advanced integrated signaler","name":"GetRef","inputs":[[1,0,1357],[2,0,"Ref"]]},{"type":"reference decoder","name":"RefDecode"},{"type":"custom ticker","name":"MoveTick","inputs":[[1,0,1],[2,0,1]]},{"type":"basic pathfinder","name":"GetDirection"},{"type":"locomotion circuit","name":"Move"}],"wires":[[[1,"O",1],[2,"I",1]],[[1,"A",3],[2,"A",1]],[[2,"O",1],[4,"I",1]],[[3,"A",1],[4,"A",1]],[[4,"O",1],[5,"I",1]],[[4,"A",2],[5,"A",1]]]}
    Very basic implementation. If the ref you scan with the remote changes its position, this drone will follow it. It's up to your personal tastes whether or not this is a good thing. Of course, there's a way to make it only follow the ref's coordinates at the time of the scan: use an examiner.

    10: For nerds, Stack
    A simple data structure, the Stack is a list (in reality, an array of fixed size, but let's ignore that) with, at its most basic, two algorithms that permit it to function properly: Push() and Pop().
    Push is very descriptive of what it does: it pushes a value to the top of the stack.
    Pop removes the top value and outputs it.
    Stacks operate on a Last In - First Out principle, LIFO for short. The last value pushed into the stack is the first value to be removed when Pop is called.
    Implement a Stack in this way. The Push algorithm will only accept numbers.
    Since Push and Pop must operate on the same list, don't forget to send the right output data to the right components!
    Code:
    {"assembly":{"type":"type-c electronic mechanism"},"components":[{"type":"number pad","name":"Push"},{"type":"append circuit","name":"PushAdd","inputs":[[1,0,[]],[2,0,29]]},{"type":"button","name":"Pop"},{"type":"at circuit","name":"PopGet","inputs":[[1,0,[5,2,25,29]],[2,0,0]]},{"type":"delete circuit","name":"PopRemove","inputs":[[1,0,[]],[2,0,0]]},{"type":"len circuit","name":"GetListLength","inputs":[[1,0,[]]]},{"type":"addition circuit","name":"IncrementListLength","inputs":[[1,0,0],[2,0,1]]},{"type":"join text circuit","name":"ListToString","inputs":[[1,0,[]],[2,0,", "],[4,0,1]]},{"type":"small screen","name":"Output"}],"wires":[[[1,"O",1],[2,"I",2]],[[1,"A",1],[2,"A",1]],[[2,"I",1],[2,"O",1]],[[2,"I",1],[5,"O",1]],[[2,"O",1],[6,"I",1]],[[2,"O",1],[8,"I",1]],[[2,"O",1],[4,"I",1]],[[2,"O",1],[5,"I",1]],[[2,"A",2],[6,"A",1]],[[3,"A",1],[4,"A",1]],[[4,"I",2],[6,"O",1]],[[4,"A",2],[5,"A",1]],[[5,"I",1],[5,"O",1]],[[5,"I",2],[6,"O",1]],[[5,"O",1],[6,"I",1]],[[5,"O",1],[8,"I",1]],[[5,"A",2],[6,"A",1]],[[6,"O",1],[7,"I",1]],[[6,"A",2],[7,"A",1]],[[7,"O",1],[8,"I",4]],[[7,"A",2],[8,"A",1]],[[8,"O",1],[9,"I",1]],[[8,"A",2],[9,"A",1]]]}
    The "join text circuit" is a bit wonky, I'll be honest.
    The "at circuit" has no real purpose here other than to show that the removed element is also supposed to be used someplace else.

    These examples use several advanced techniques, like iteration, JK Latch toggling, list operations, the use of modulo, the use of signallers and others. These may be employed in more complex scenarios for better complexity economy, allowing you to use fewer high-complexity items by substituting them with arithmetic and logic operations.

    Chapter Three: This One WEIRD Trick
    This short part focuses on Integrated Circuit tips that make your life easier.
    General
    • Label all your components. When you're tackling very complicated circuits, this becomes essential. Imagine having 5 constant chips and having to click each of them to check their output data. Labels should be clear, concise, and ideally explain what they accomplish rather than simply what they do with the input data (but it's not always easy to label them this way).
    • If your circuit is very complex, you'll likely want to split it into small subproblems I refer to as "functions" or "methods" or "procedures." Each of them will do their own task, and provide an output that can be fed into another function. The system doesn't actually provide ways to work with functions: they're an abstract concept. Say you have functions Verify and Switch. You can label their components like this for easy reference:
      1. VerifyCount
      2. VerifyIterate
      3. Verify <- (This one could do the main operation of the function)
      4. SwitchCheck
      5. Switch <- (Same here)
    • Order your components. This will give your circuit a nice, organised feel. Work out the component order you're most comfortable with, and each time you add a new component to the assembly, choose the best position for it. My circuits' components roughly follow this structure:
      1. Constants
      2. Other memory components
      3. Inputs, ordered by how they should appear on the UI
      4. All the operation circuits, ordered by whatever makes the most sense
      5. Outputs, ordered by how they should appear on the UI
    • You don't really have to plan ahead when creating an assembly. You can choose the smallest assembly available and upgrade it if you need to. Smaller assemblies are more valuable due to their portability, but a complex program simply won't fit in one. To upgrade your assembly, analyse it. The code should begin with something like "type-a electronic assembly." Change it to "type-b electronic mechanism," for example, and clone the result. Now you have a bigger assembly that's wired in exactly the same way as the smaller one.
    • To empty out an assembly, remove its power cell and use it on the Printer. To recycle an empty assembly, use it on the Printer again. The metal used for the circuit is refunded 100%.
    • A word on iterators: the time delay is critical for iteration, but how small can you make it without breaking your loop?
    The common iterator is constructed as such:
    [1] Reset constant (pulsed at the beginning of the iteration as a whole)
    [2] Addition/subtraction (increment the counter by 1)
    [3] Less than/greater than (check if the iteration is over or not)
    [4...n-1] Actions (anything you wish to be done repeatedly)
    [n] Delay
    So how small can the delay be?
    All arithmetic/logic operations only have 0.1 seconds as their pulse cooldown. The smallest delay possible, then, will be the largest pulse cooldown among all the components labeled above as "Actions." Not following this rule may bring unexpected results, for instance:
    You want to fire a weapon every 1 second, 10 times, so you set the delay variable to 10 tenths-of-a-second, and the upper bound for your less-than-or-equal circuit to 10. But when you test it, it only fires once. This is because the weapon firing component has a pulse cooldown of 10 whole seconds, and pulsing it repeatedly is meaningless, but the counter has no trouble at all being incremented every 1 second, so it reaches 10 before the weapon has a chance to fire again. Setting the delay to 100 tenths-of-a-second fixes the problem.
    Tools
    • The order in which your pulse wires are does matter, and differently ordered pulse wires will occasionally produce different results. Pulses are sequential from top to bottom. If your shit is breaking due to bad wire order, you'll have no choice but to unwire the conflicting wire at the top and wire it again, placing it at the bottom.
    • The order in which your data wires are does not matter: the system doesn't care. You might care though, if you want aesthetics in your circuit.
    • Wiring is a 2-step process. You'll usually be wiring a PULSE OUT to a PULSE IN and an output wire to an input wire, but the reverse also works: you can wire input to output and it'll work the same way. Makes placing 16 wires from one component to another an easier process to stomach.
    • The debugger's Ref function allows you to scan an object and save its Ref to be inserted into your assembly, but you can't make Ref into a persistent data type you can save forever. This is because a Ref is a reference to an object saved on the server's memory, which will eventually be de-allocated. There's no guarantee the same memory address will contain the same object in later rounds, so the system doesn't allow you to reference that same memory address (for your own sake). Correct me if this is bullshit/too inaccurate.

    EXTRA: Aria's Cookbook
    This part will outline some common design patterns, useful for solving certain classes of subproblems.

    Iterator
    What I call the Integrated Circuit equivalent of the for() loop in most programming languages. It is, by far, my most used construct, as it is powerful and versatile, while having a small impact on size and complexity. It can be used to access all (or some) elements of a list, all (or some) characters of a string, for timers and countdowns, or just to perform a certain operation (or different variations of that operation) a set number of times. Extremely useful, it should be in every circuiteer's repertoire.

    [1] constant chip
    [2] addition circuit
    [3] less than or equal circuit
    [4] delay circuit

    The [1]'s output is connected to the [2]'s first input.
    The [2]'s output is connected to its own first input, and then connected to the [3]'s first input. The [2]'s second input is set to 1.
    The [3]'s second input should be defined by debugger or connected to a component external to the pattern. It defines how many times the loop will run.

    The [1] will be pulsed by an external component, the "loop starter." Its data, usually 0 or null, will be sent to the [2], which will also be pulsed by the "loop starter." The [2] will add 1 to the input, thus incrementing its own first input while sending its value to the [3] (and pulsing [3]). The [3] will tell whether or not the loop is over. If the loop is over, its "on false" pin will pulse an external component. Reverse logic: if the "on false" pin is pulsed, it means the loop finished successfully. If the loop is instead continuing, its "on true" pin will pulse [4], or some other set of actions which eventually pulses [4]. [4]'s outgoing pin will pulse [2].

    As for the function of each component: The [1] is a resetter, used to start the loop. Without it, the loop would only ever run once.
    The [2] is a counter, which not only keeps track of the loop's current iteration, but also provides an index for accessing lists and strings, or the time elapsed for a timer, and so on. The [3] determines whether the loop is over or not. The [4] is necessary since all components have a cooldown of at least 0.1.
    Summarising in the form of a for loop:
    for([1]; [3]; [2]){
    (actions)
    [4]​
    }

    Cycler
    The name I give to a special subtype of iterator. While the above pattern's iteration ends after the less than or equal circuit returns false, this pattern is circular: it simply returns to the beginning and starts its task again. It is useful for any tasks which you'd like to be circular, such as cycling a gun's 3 firing modes, or cycling access levels on an access copier. It's even simpler, too.

    [1] addition circuit
    [2] modulo circuit


    That's it!

    The [1]'s second input should be 1. Its output is connected to the first input of the [2].
    The [2]'s second input should be equivalent to however many times you want the cycler to do its work before reverting to the beginning and starting it over, let's call this variable n. In the 3 firing modes example, n would be set to 3. In the access copier example, n would be the length of the list of saved access levels. The [2]'s output connects to the [1]'s input.

    In the way it is built, this is not a loop, due to lacking a delay circuit. In those situations where a Cycler is useful, you'll most often be using something like a button as a "starter." The "starter" pulses [1]. The [1] pulses [2], or some other set of actions which eventually pulses [2]. The [2] pulses nothing.

    As for their function, there's little to explain: when the [1]'s output is equivalent to n, the [2] sets the [1]'s first input to 0.

    The toggle-check construct
    This is the name I give to a small, 2-component construct that makes checking an item's state a very trivial process.

    [1] JK latch
    [2] RS latch

    Both the [1]'s inputs are set to 1. The [1]'s first output is connected to the [2]'s first input, and the [1]'s second output is connected to the [2]'s second input.

    The [1] and the [2] are pulsed in different moments, for different purposes. The [1] is pulsed whenever the state of an item changes from 1 to 0 or from 0 to 1. The [2] is pulsed when another component requests the state of that item.

    There's nothing keeping you from using another logic circuit in place of the RS, but:
    1. It lets you show off, and
    2. It tends to make everything a little bit tidier and cleaner, especially if you need to request the item's state multiple times.


    Why patterns?
    By incorporating patterns into your list of techniques, you accomplish two fundamental tasks:
    1. You formalise the solution to a specific problem, and are less prone to making mistakes when solving that problem (since you've used the same solution dozens of times already, and it works). Ideally, the solution is small and low-complexity.
    2. When coming back to your work after a few days, you tend to forget what each component is supposed to do, no matter how elegantly you labeled and ordered them. Patterns stick out, though. If you see a 4-component construct with a constant, some addition, a logic check and a delay at the end, your first thought is "Aha, that's an iterator." It makes everything easier.

    ________________________________________________________________________________________________________________
    NOTES
    I'd like to mention some honourable gentlemen of the present Circuit scene. Starting with Arkter, whose Renald Dalton first taught me Circuits around February or March 2019. He's an alright noodle man, reach out to him for some in-game guidance if you need it.
    Off the top of my head, here are other nerd characters worthy of mention:
    Leonard Maillard (very complex designs)
    Carson Johnson (also good, but I haven't seen him or his player in a while)
    Jim Mason (good circuit-antagger)
    In-game, you can occasionally find me as Ensign Aria Guinness, Researcher. I sit in the fabrication lab making circuits and processing fabrication requests (after maxing out R&D, of course).
    Please feel free to post fancy circuits of your own, better/alternative solutions and other examples.
    Inb4 "NERD"

    EDIT: removed a part containing inaccuracies.
     
    Last edited: Nov 18, 2019 at 8:22 PM
  2. Arkter

    Arkter Chef

    As Resident Circuit Shitlord Renald Dalton I approve of this guide.
     
    Cheb Pomidorov likes this.
  3. Astrospacedude

    Astrospacedude Bartender

    Thanks for this, my dream of making a computer is a bit closer now.
     
  4. Cheb Pomidorov

    Cheb Pomidorov Bartender

    Glad you find it useful. I've already made a simplistic computer using Integrated Circuits, so I'd be open to give you a few extra pointers if you need them.
     
  5. Astrospacedude

    Astrospacedude Bartender

    Integrated circuits? The exist in game?
     
  6. Cheb Pomidorov

    Cheb Pomidorov Bartender

    They are what the guide is about. The guide wouldn't exist if they didn't exist in-game.
     
  7. Astrospacedude

    Astrospacedude Bartender

    As in the circuit which is a small amount of logic gates on a board
     
  8. Cheb Pomidorov

    Cheb Pomidorov Bartender

    Yeah, you can use the system outlined above to make whatever logic gate, arithmetic operator, bistable, memory unit, etc. you desire
     
  9. Syncron

    Syncron Bartender

    Jim Mason here. I need to figure more circuits out. I can make weapons and dodads, But I need to learn how to properly use JK latches, and all sorts of that stuff. I like to 'research' my ideas, But admittedly I've been stumped on stuff thats made me stop working with circuits for a little bit.

    EDIT: Only a little salty that I don't get a mention for my dodads. They have enraged security, and saved exploration before. Hah. (This salt is a joke.)
     
    Last edited: Oct 20, 2019
  10. Cheb Pomidorov

    Cheb Pomidorov Bartender

    My bad, how could I forget? I myself fell prey to one of your reagent circuits back when I was still playing LT Weber. I hope to see you around more.

    Latches are essentially binary memory units, also known as bistables, as they have two stable states, those being TRUE and FALSE.
    The latches we are provided have two data inputs and a pulse input. When the pulse, commonly called "clock," is signalled, the latch adjusts its state based on:
    - The state of the first input
    - The state of the second input
    - Its own state, Q
    This property makes latches useful for answering the question, "what changed since last time I pulsed this?" And the use I've made of the JK Latch is rather reductive, as it's a very capable tool useful for several situations, but it was enough for the job.
    The JK Latch is an improvement over the SR/RS Latch (Set-reset).

    S | R | Action
    0 | 0 | latch
    1 | 0 | set
    0 | 1 | reset
    1 | 1 | invalid state (in in-game circuits, this is latch instead)

    "Latch" means the value of Q remains the same. "Set" means it becomes 1. "Reset" means it becomes 0.
    The JK Latch eliminates the unstable state by adding the following configuration:

    J | K | Action
    1 | 1 | toggle

    This is the one I use often. If Q is 0, then it becomes 1, whereas if Q is 1, it becomes 0.
    Then we have, uh... this.

    Gated D latch
    E | D | Action
    0 | 0 | latch
    0 | 1 | latch
    1 | 0 | reset
    1 | 1 | set

    Which basically latches if E is 0 and sets/resets depending on D if E is 1.
    It's hard to find a use for these latches, but if you do find it, you can save a lot of time and complexity cost. I admit I've yet to use the Gated D and the SR myself, and I only use the JK for its toggle function.
     
  11. Syncron

    Syncron Bartender

    You can usually find me playing Rrs'var T'sanis, an Unathi as of late. I still tinker with circuits sometimes though. Usually in Engineer, Robotics, or Engineering.

    My more recent hangup however is designing a name designation with a whitelist function. The problem is for me, the locators only seem to scan the first person in range, and not change targets to scan anybody else. I'm trying to find a workaround for it. If I can, one of my long listed projects will become easier.
     
  12. Cheb Pomidorov

    Cheb Pomidorov Bartender

    I think I've seen T'sanis around. I'm just humans all the way, but I'm patiently waiting for response on my Adherent whitelist application, hence my profile status.

    From what I can extrapolate, you want to make a thing that locates ALL people in range, so why not use the 'list advanced locator?' You'll get a list of everyone in the area, and working with lists is easier and more predictable than working with locators, whose type comparison algorithm I've yet to understand (same as the 'custom filter').
     
  13. Syncron

    Syncron Bartender

    I can get a list of people, But I don't know how to make it cycle through the list of people IN said list. It can scan the first person, But not the rest.
     
  14. Cheb Pomidorov

    Cheb Pomidorov Bartender

    I've added a new EXTRA chapter after the third. It might have the answer you seek.
     
  15. Syncron

    Syncron Bartender

    I took a look, and even looked ingame. It might help, But the problem is making it cycle a list. It'll require a lot more additions in order to convert the list to properly work with the circuit (Since the cycler and the likes use numbers) I've been trying to work out how to make it work properly currently.

    EDIT:

    Actually, is there a way to make something automatically move down to the next thing in a list? Example would be memory sticks.

    INPUT 1
    INPUT 2
    INPUT 3

    Is there a known way to make a circuit cycle to the next section, Such as going down.

    INPUT 1 - Jimmy Jams<REF>
    then it goes down instead to input 2, for adding a new selection to said memory card?
     
    Last edited: Nov 11, 2019
  16. Cheb Pomidorov

    Cheb Pomidorov Bartender

    Sure is. For a 16-memory stick, use a 16-demultiplexer and an iterator from 1 to 16. At each nth iteration the demultiplexer's output selection should equal n; the demultiplexer's input should be whatever you wish to be inserted; each of the demultiplexer's outputs should point to exactly one of the memory stick's inputs.
    Same with the 16-multiplexer if you want to access the memory instead of writing it.

    For lists, you can use the "at circuit" to access elements.
     
  17. Syncron

    Syncron Bartender

    Ah. Might help with the stage I'm at. My whitelist system is almost prepared, Then I need to design a system for multi-targetting. But the moving down a list part I've never bothered with regarding memory. I rarely even looked at memory sticks and the likes. Thanks. If I ever find your discord I'll probably toss thought there since forums are slow, Lol. And hey, I'm not ONLY a circuit antagger, Lmao. But the mention amuses me.
     
    Cheb Pomidorov likes this.