In the first of the 2017 logic gate series I described a map hack that creates a multi-way switch, where a gate can be switched between two or more outputs (one of which might not have a target) and then the chosen output be triggered. Today we will look at ways of connecting two or three of these switches together, to make the AND gate, OR gate, and the XOR gate.
You may be glad to learn that don’t have to understand how the hack in the previous post works in order to create the gates in today’s article. You can just copy-paste the ready-made switches from the example maps into your map like building blocks. This is because they have no internal wiring, an concept I will explain now.
Internal wiring
Imagine that we have a button in our map which can be pressed repeatedly, but we want to do something special the first time the button is pressed. Specifically we want to open a door after 2 seconds, and advance a trigger_counter after 4 seconds. We don’t need an entity hack to do this, we can just use standard entities in the following system:
| classname | targetname | target | delay |
|---|---|---|---|
trigger_once |
button_1_pressed | first_press | 0 |
trigger_relay |
first_press | door_1 | 2 |
trigger_relay |
first_press | global_counter | 4 |
We might need to do the same thing again with a second button, another door, but the same global_counter. We could copy-paste this system of trigger_relay and trigger_once entities, change the targetname button_1_pressed and door_1 to the names of the new button and door, and keep global_counter the same. These are the external targetnames, and it’s clear which of them need to change and which stay the same. But what about first_press?
If we leave first_press unchanged, then the trigger_relay entities from the second system will trigger when the first button is pressed, which is not what we want! So this targetname needs to be changed to a new, unique value for the second system. This targetname is what I mean by internal wiring for a system of entities – a targetname which isn’t used outside of the system, but needs to be unique for each system. The switches from the previous post don’t have any internal wiring, which makes them copy-paste friendly. Unfortunately we can’t avoid some internal wiring for the gates we build today, so to help I will continue using the convention from above of putting the internal targetnames in italics in the entity tables.
Test Map
I thought it would be good to share the test map first. If you’re unfamiliar with the logical operations AND, OR and XOR you can explore how they work in the map, then come back to see how it was built. The map has three themed areas connected by teleporters, and each area has multiple routes to climb to the teleporter. The catch is that the button to unlock the teleporter will only operate if you take certain routes. The maps are designed so that you can drop back to the lowest level at any point and try a different route – try disobeying the instructions first time, observe that the button doesn’t work, then restart the journey and do it correctly. The button actually toggles the gate so you can test it as many times as you like.
The AND gate
In logical operations, AND gates have two “inputs”, each of which can be true or false. The gate only outputs true (or in quake terms triggers its goal) if both of the inputs are true. This can be turned into a flow diagram:

How do we translate true and false into Quake? We might try to use “being triggered” as the signal for true, and “not being triggered” as false, but there’s a problem with that. In Quake, a trigger happens instantaneously, it’s not possible for something to continuously “be triggered”. So we can’t ever get two true signals simultaneously, which is what the AND gate needs before it activates. The alternative we take today is to make true and false values which we can store and recall. This separates the process into two operations, firstly storing boolean values in the gate, and secondly testing the state of the gate.
This is where the previous article comes in; for each input of the AND gate, we add a logic gate switch from the first article (you can copy-paste them from the test maps). Each of these switches will have two settings, “true” and “false”. Changing the setting of the switch stores the value of true or false.
The trick is to arrange the gates like the diamonds from the flow diagram, so that the input of the second switch is targetted by the “true” output from the first switch, and the goal of the gate is targetted by the “true” output of the second switch. The only things you need to change are the targets and targetnames of the entities in the switches, as per this entity table:
| gate | role | targetname | target |
|---|---|---|---|
1 |
input | AND_gate_input | |
1 |
output | AND_gate_a_false | |
1 |
output | AND_gate_a_true | AND_gate_internal_input |
2 |
input | AND_gate_internal_input | |
2 |
output | AND_gate_b_false | |
2 |
output | AND_gate_b_true | AND_gate_goal |
Names in italics are internal wiring
The OR gate
OR gates also have two “inputs”, each of which can be true or false. The difference with the AND gate is that an OR gate outputs true if either of the inputs are true. Here is a flow diagram:

Like before, we need to use two switches to create the OR gate. This time to match the flow diagram, we want the “true” output of the first switch to go straight ahead and trigger the goal, and the “false” output to target the input of the second switch. This leads to a slightly different entity table:
| gate | role | targetname | target |
|---|---|---|---|
1 |
input | OR_gate_input | |
1 |
output | OR_gate_a_false | OR_gate_internal_input |
1 |
output | OR_gate_a_true | OR_gate_goal |
2 |
input | OR_gate_internal_input | |
2 |
output | OR_gate_b_false | |
2 |
output | OR_gate_b_true | OR_gate_goal |
Names in italics are internal wiring
The XOR gate
Finally, we come to the XOR (eXclusive OR) gate. As with the other two gates, we have two true/false inputs. This time, the output is true if exactly one of the inputs is true. If both are true or both are false then the output becomes false. This contrasts with the OR gate – that will output true when both the inputs are true. The XOR gate has a more complicated flow diagram, because both of the paths from the first decision lead to a further decision about the second input. There are two different paths to get to the goal.
To make this work, we are going to include three switches. One of the switches will represent the upper left diamond, and will work like the switches in the previous two logic gates – recording the true/false status of the first input to the XOR gate. The other two switches will represent the top right and bottom left diamonds, which means they will both represent the second input! We need them to both store the same true/false value for the second input, and we can do that by giving them the same targetnames for storing values. The reason for having two is so that they can be connected to opposite ends of the first switch, and trigger the goal for opposite truth values.
Use the following entity table to create an XOR gate
| gate | role | targetname | target |
|---|---|---|---|
1 |
input | XOR_gate_input | |
1 |
output | XOR_gate_a_false | XOR_gate_int_false_input |
1 |
output | XOR_gate_a_true | XOR_gate_int_true_input |
2 |
input | XOR_gate_int_false_input | |
2 |
output | XOR_gate_b_false | |
2 |
output | XOR_gate_b_true | XOR_gate_goal |
3 |
input | XOR_gate_int_true_input | |
3 |
output | XOR_gate_b_false | XOR_gate_goal |
3 |
output | XOR_gate_b_true |
Names in italics are internal wiring
Wrap-up
That’s all we’re going to cover today. NOR gates and NAND gates have been skipped, because you can simply take an OR/AND gate and swap which of the output entities in each gate has the goal as its target to get one. One thing you may need to worry about is what the initial truth values are for the inputs, especially if there is a chance that the gate might be tested before anything has triggered the inputs false or true. For that, you’ll need to make sure the key "th_pain" "ai_melee" is added to just the true/false outputs you’d like to be selected initially.
I could say more about how to create a three way gate, but I think that’s more interesting as an exercise. Please let me know if you have any queries in the comments below!


