7 Billion Humans

7 Billion Humans

39 oy
Command and Technique Reference
Futae Yamagawa tarafından
A reference guide for the commands and several useful techniques.
   
Ödül
Favorilere Ekle
Favorilere Eklendi
Favorilerden Çıkar
Prologue
Welcome fellow workers! This guide is a reference to the commands and some of the techniques you may use to solve the puzzles in the game. If you are aspiring to be a programmer, or simply here to challenge yourself, I strongly suggest you to play through the game once before reading this or similar documents. My reason for suggesting this is simple.

In the programming world at large, time and again you will find yourself faced with a programming task, and you won't know at a glance how to do it. You might not even know if it can be done. Worse, you may lack helpful resources to aid you with the problem. You may be facing an entirely new language, or an ancient proprietary language. "API Documents? Just read the source code." In either case, Google won't always have your answers for you, and asking on forums won't always provide help. You'll need to solve those problems yourself.

This is your chance to try your hand at exactly that, and you lose this chance if you dive right into the online how-to content.

There's a second reason I ask people to play through the game once first. When you read this reference document, you are going to learn things. The things you learn will allow you to create assumptions.

Assumptions create barriers. Barriers in your thinking, barriers in how you solve problems.

Techniques that you can use to do a specific task may look like techniques you should use for that task, or look like techniques you must use. I'd like for you to avoid these barriers for your first encounter with the game. You may find the game more difficult to work through this way, but it can be far more rewarding. You'll be able to see how far you got without outside aid, and take pride in any methods you created yourself. You may even find an entirely new and valid way to solve one of the problems. Perhaps an even better way.

My challenge to you:
Discover how far you can get through the game without referring to any guides or forums for help.

Any programmer worth his or her salt can at least produce a working solution for each core puzzle unaided. (Even expert programmers may lose some hair over some optional levels, but they should be able to manage even those - probably? I honestly don't know, multi-threaded programming is hard for many skilled programmers to grasp, and this game focuses on that Achilles’ heel) When you're finished the game, or you've ♥♥♥♥♥♥ stumped, or you feel you're ready for another viewpoint, please, swing back and peruse this guide. If you manage to discover or create something innovative and effective, by all means show us all.

I'll try to keep the guide as free of spoilers as possible, but it will still contain spoily things for the careful reader to spot. To omit spoilers entirely would cut into the usefulness of this guide.

You have been both challenged and warned. Proceed at your own discretion, and good luck!

--Yamagawa
Commands, Part 1
About the Execution Time: Execution times as listed are only estimates and are often variable.
  • Brief - Nearly instantaneous.
  • Short - This is the minimum delay for instructions that require the worker to notice the world around them. Those same instructions may be faster without noticing the world.
  • Medium - Most actions involving movement fall into this broad category. Thinking is normally fast, but doing takes time.
  • Long - Indicates an action that takes significantly longer than walking one tile.

<memory> = calc <value> <operation> <value>
Execution time: Long. "Math is hard".
This is perhaps the slowest thing a worker can do.
This will set the indicated memory register to the result of the math operation.

drop
Execution time: Medium
If the worker is carrying a data cube, they will drop it on their current position.
If the worker is not carrying a data cube, they will complain.

end
Execution time: Infinite
Causes the worker to stop all work, the same as if the program finished executing the final statement. The worker will automatically walk towards anyone walking on their current tile so as to not impede movement, and objects can still be given to/taken from them.

forEachDir <directions> as <memory>
Execution Time: Short
Requires the worker to notice their surroundings, thus this has a delay similar to that of an 'if' or 'set' that notices the worker's surroundings.
Unlike other functions that take a directional input, this cannot target the tile the worker is standing on, it can only observe selected adjacent tiles. Which adjacent tiles is configurable.
This will loop over the nested instructions, once per direction. At the start of each iteration, it sets the selected memory register to what can be observed in one of the selected adjacent tiles at the start of that iteration.

Order of observing the adjacent tiles is in a clockwise direction starting form the nw corner. That is, they are observed in the order of nw, n, ne, e, se, s, sw, w.

If you are creative, you can move once per loop, and the next observed adjacent cell will be based upon your new position at the start of that loop.
Advice to aspiring new programmers: "Just because you can do a thing, doesn't mean you should." Move the worker from inside a forEachDir loop at your own risk. Lost or misplaced body parts are your responsibility.

giveto <direction|object>
Execution time: Medium. Can trigger movement.
This causes the worker to give their held datacube to someone or something else.
If a machine is targeted, it is given to that machine, with the worker moving to the machine's north side to give the object.
If a worker is targeted, the datacube is given to the targeted worker. The targeted worker will pause all work until they receive the cube - this will stop them even if the worker giving the datacube is across the room.

if <arg1> <condition> <arg2> [<operator> <arg3> <condition> <arg4> [<operator>...]]
Execution time: Brief/short
Execution time is brief if there are no positional references (n/s/e/w/etc). If any positional references are used, the worker has to look at the world around them, taking extra time.

The if statement takes the form of 'If/Then/Else'
The else clause, if present, will count for a single instruction of program size.

The if statement has a special relationship with 'lines', discussed further in the Sundry section at the end of this document.

An example of an if statement:


Up to 8 conditional clauses may be used with a single if statement. The conditions are checked in order (there is no evaluation priority scheme), top to bottom (aka left to right). The boolean operator used to join them may be either 'and' or 'or'. The condition may be ==, ≠, >, <, >=, <=

If you are evaluating a tile with a datacube, you can evaluate the value of that datacube.
If you are evaluating a tile with a worker holding a data cube, you can evaluate the value of the held datacube.
If you are evaluating a tile with a worker standing on a datacube, while holding a datacube, there are two datacubes you are looking at in the single evaluation. The value of the datacube on the ground takes precedence. The held datacube will be ignored.

jump
Execution time: Brief/Nil
This causes execution to jump to the indicated point - it is this language's form of a 'GOTO' statement from BASIC.
This is one of two ways to implement loops, the other being ForEachDir. It also allows you to create subroutines, or otherwise shift flow between blocks of logic.

The jump statement has a special relationship with 'lines', discussed further in the Sundry section at the end of this document.

Tip to aspiring programmers: The use of jump/goto in programming languages with more advanced flow control is normally strongly discouraged! These are discouraged for very good reasons. While you will need to use them in most levels to complete the required tasks, please do not learn bad habits.

listen <message>
Execution time: Variable.
The worker will stop and wait until they hear the selected message.
The tell/listen messaging functions as little more than an implemenetation of 'sleep'/'wake' functions. The actual messaging bandwidth of these functions allows the transfer of exactly 0 bytes of information - Despite the instruction names, you cannot transfer information between workers this way. If you need to transfer information, please refer to Quantum Signaling in the Techniques section.

<memory> = nearest <object type>
Execution time: Brief
This sets the selected memory 'register' to the nearest instance of the selected type of object, or 'nothing' if no instances of that object type exist.
Desired objects can include workers, walls, printers, shredders, holes, and datacubes.
The reference this gives is fluid and may change without notice, should the target cube become unavailable - to see this happen, play Level 28 - Neural Pathways, and debug the worker that starts in the bottom-left corner. The worker will get a cube late in the process, but which cube he aims to get changes as everyone picks up their cube in turn. If you need a static, unchanging reference to the nearest cube, copy it. The copy will be unchanging. (More testing is warranted, but it looks like other commands will also 'fix' the reference provided by this command).
Commands, Part 2
pickup
pickup <direction|object>
Execution time: Medium, can require longer for movement.
This command comes in two forms. One form, used in the early levels, does not accept an argument and will act on the worker's location. The other form accepts either a direction or an object as an argument.
If a worker is supplied as the argument, the worker complains.
If a datacube is supplied as the argument, the worker walks onto the tile with the datacube and picks it up.
If a compass direction is supplied, the worker picks up the object at that location, without moving. This means that the worker may pick up data cubes without standing on their tile, if picking them up with compass directions, but will always stand on a datacube to pick it up if picking it up by reference.
Picking up things that are not datacubes is discouraged.

<memory> = set <value>
Execution time: Brief/short
If the set requires the worker to look at their surroundings, the worker will require more time to complete a set operation.
This sets the selected memory 'register' to the indicated value.

tell <direction|worker|everyone> <message>
Execution time: Short
Tell the selected message to the indicated recipient(s). Distance has no effect on this command. Workers listening for the message they hear will resume work.

step <direction>
step <directions|object>
Execution time: ~Medium - Will vary based on distance covered and obstacles encountered, which can make this brief or infinite.
This command takes two forms. One accepts a single direction, the other accepts multiple directions and values from memory registers.
This causes the worker to move. If a compass direction is given, the worker will step in that direction. If an object is given, the worker will step to that object, however close or distant it may be.
If multiple directions are given, the worker will select one unblocked direction at random.
Obstacles:
If the worker is directed to walk into another worker, the execution of this command will halt until the occupied floor tile is clear, as in the example to the right. Our walking worker in the example may need to wait a while, it looks like our math expert may be caught in a loop.
If the worker is directed to walk into a stationary obstacle, for example, a wall, the worker will not move and the command will promptly finish.
If walking to a distant object, the worker will select a free path at the time the step command is issued, and will not divert from their path if another worker then blocks one of the intermediate floor tiles - this can be a problem if you specifically park a worker on a tile in an infinite loop.
Workers that have stopped executing the program, either at an end statement, or by finishing the final line of code, will automatically step towards any workers trying to step on their tile, swapping places, so as to not be an obstacle to other workers still working their assigned tasks.
Walking in loops:
If multiple workers all want to step onto each other's tiles, such that they will all step in a loop, this loop movement will be allowed. This works with any number of workers, whether it's two workers that each walk towards the other to merely swap places, or 20 workers all walking in a giant loop. The advantage here is that workers cannot deadwalk. Ahem, workers cannot deadlock from simply trying to walk around. They can still get stuck in other ways, but the inability to get stuck simply by walking around is convenient.

Mixing diagonal and cardinal travel can in some contexts introduce slight delays.

takefrom <direction|object>
Duration: Medium. Will take longer if movement is involved
When taking things from machines, the worker will move to the north side of that machine.
If taking things from other workers, the worker will walk towards that other worker. The worker being taken from will stop all work until the data cube is taken from them.

write <value>
Duration: Medium
Write the indicated value onto the currently held data cube.
The value is recorded on the data-cube at the end of the operation.
Techniques, Part 1
As stated at the start of this document, reading this may cause you to create assumptions that create barriers for you, holding you back from the creative solutions you might devise for yourself. If you have not already attempted the game, I urge you to stop reading at this point and play through the game once before returning here. The techniques I list here are not an exhaustive, all inclusive set of techniques. The idea is to give you a few tools and start you thinking about ways you might approach problems, and to point out subtle behaviors which might both frustrate or be exploited by players.

The Wall-Stop
Checking for walls involves asking workers to look at the world around them, and nobody has time for this. Looking around at the world is slow! It's often much faster and simpler to just have the workers bang into a wall as though you want them to walk through it. The wall will stop them. Used intelligently, this can be used to move workers safely around obstacles without having them pause to look. The basic form of this is a lot of step instructions in the same direction, towards a wall, eg: step e, step e, step e... Any excess step instructions will be ignored at the cost of a brief time delay, and possibly injury. While this may seem like an obvious technique, I mention it because people may wish to not injure their workers. Fear not, bruised noses and broken teeth from walking into walls won't hinder your workers' ability to move data cubes to their proper destinations.

Look, Then Act
Noticing things in the world takes time. Sometimes, you find yourself needing to check several things about the same tile - Is it a data cube? Do this. Is it a hole? Do that. Is it my Boss (he counts as 'something'), give him a hello. If you have to check several different things about a single tile and have access to the set instruction, use set. First look at the tile - save it's contents to memory, then evaluate it in memory as much as you need to, while incurring only the time penalty from that first look at the tile..

Binary If Tree
Math is hard, and it takes forever to complete. Almost.
You may be better served on an OCD-speed run by using a binary if-tree. The example to right has part of such a tree. You could just do a series of if statements ... "If foo = 1 then 2, else if foo 2 = then 3, etc..." instead of using the binary tree format, but then you can wind up executing a lot of if statements with each pass through the logic, which can bog down and be slow.
In programming, a binary tree is a type of data set, and walking these data sets is much like walking a Binary If Tree, except the code usually looks more compact.

Walking Loop Filter
If you need to find something on one of your workers, discarding what the other workers have, you can have the workers walk in a loop. At one point in the loop, have workers check to see if they can stay or need to 'discard' themselves, taking care that when they do discard themselves, they do not path through the workers in the loop on the way to whatever you are using as a 'discard pile'. If there are excess workers for the loop (as in the animation, where the loop holds 4 workers and extras queue behind it), they will wait outside the loop until it has room to fit them. These loops can be small, only two tiles in size, or larger, up to 8 tiles. It's important to note that you should check for whether you belong in the loop or need to leave from only one point. Checking from more points in the loop actually hurts its performance, and can bug on duplicate values.

Random Walk
You prepare this by directing a worker to select a random direction to walk in, then have them either do whatever task is needed at that location, or keep random walking until they find a desired destination. When random walking, workers will automatically try to avoid walking into other workers/obstacles - perhaps there is some advantage to be found in that avoidance?

Quantum Signaling
Workers know instantly when a data-cube they are tracking in their limited memory is either destroyed or modified. This action will even happen at a distance. (This is spooky.) They don't need to 'look' at the cube again to see the new state, which is good - that looking can involve annoying delays. Workers just need to 'set' the value one time, and recall the value in memory at any later time. A place to use this may be to have a worker pause until something useful happens someplace else - perhaps they need to act when some data-cube gets changed to a new value?
In the example above, the left worker is updating their cube and the right worker is copying those updates by way of this technique.

We have independent confirmation: This signaling works faster than the speed of light! It also represents to a lesser degree a violation of causality - effect can occur simultaneously with cause. If one worker starts copying the value of a cube and the source cube has a new value written to it... This gets complicated. The worker copying it's value will have been writing the new value the entire time. In the right circumstance, this can save your workers some time.
Techniques, Part 2
Idle Pauses
Timing can be critical, and correct timing sometimes needs a little help. You can use tell/listen to coordinate pauses in work, but when these are not available or are too slow, there are other ways to occupy workers waiting for things to happen, such as by having them walk in circles or practice their math. The right amount of pause at the right time can be valuable.

Nearest Speed Search
As a curious detail, most things that cause a worker to look at the world around them involve a delay. There is an exception to this. The exception is the 'nearest' function, which finds the nearest occurrence of an object type with only a brief delay. Clearly the workers must be psychic to find things without stopping to look for them, but the drawback is it doesn't tell workers where that object is. You can get a reference to the object, but is that object at your feet? To your left? Three floor tiles behind you? You can of course direct your worker to walk to it, but that takes time, and the whole point here was to get instant information.
If you happen to have a row of objects of a known length to inspect, you can use 'nearest' while standing on each object in turn to quickly read their values.

Loop Unrolling
It's a time honored technique for programmers, and more often, compilers, to optimize code by unrolling loops. Instead of using 'For a=1 to 5', they may just put the same command 5 times. This removes the overhead of maintaining the loop itself, and can run faster. Sometimes, given the right problem, it can run much faster.

Testing & Play
While properly speaking testing and play are not techniques to use in a winning program, it outlines that you should not get trapped in a box built of assumptions that were handed to you.
Not every program you create needs to solve the level. You can write programs to test how commands work under controlled scenarios, or as challenges to yourself. Or to see if workers can get dizzy. Or try and make a funny dance. Anything that strikes your fancy. These more playful tasks may seem a waste of time or energy to some, but to others, they are valuable practice and a priceless tool for discovery.

Sometimes, a program's only purpose is to make someone smile, and that's completely fine.
Sundry
Not everything that you need to know is a command or a technique. This section covers the remaining items.

Program Lines and Instructions
OCD challenges count program instructions.
The program editor and it's paste function will keep track of program 'Lines'.
The import function is not counting the number of text lines being imported.
It is not directly counting the program instructions either, and that's where things get a little confusing.
  • 'If' commands count as 2 lines, without regard to the number of conditional clauses or the presence/absence of an else clause. Consider it to be counting the initial 'if' statement and the 'endif' statement in the text format.
  • Jump statements count as 2 lines. Consider it one line for the Jump instruction, one more for the label.
  • Other commands count as a single 'line'
The hard limit of 255 lines becomes important if you are unrolling loops to complete an OCD challenge for a level. Lets say you have 100 cubes you need your workers to set. Setting a cube involves 4 actions: Picking it up, writing it, setting it down, and moving to the next cube. To unroll loops to set everything, you'll need something near 100 cubes * 4 instructions/cube -> 400 instructions. When you're limited to 255 lines - you won't always be able to completely unroll every loop, so you will need to find other ways to speed up a program.

Reduced Instruction Set
Levels in the game honor the RISC architecture - that is, the number of available instructions for any level is kept fairly low, never more than about a dozen different commands. This may require you to perform an old task in a new way on new levels.

Things to Avoid Doing (aka 'Challenges, Lampshades, and/or Tips')
Your mileage may vary.
  • Misuse office equipment - this is exciting.
  • Random-walking near holes - this can be exciting.
  • Contemplate the infinite - this is exciting, briefly.
  • Walk when commanded to stay put - this is much less exciting than it sounds, but signifies trying to work outside established boundaries.
  • Forget Mel - Never forget a Real Programmer. They show us things beyond the accepted limits.
  • Allow a worker to do whatever they want after they finish the job you assigned them - this can be exciting, frustrating, or both.
7 Yorum
Rudokhvist 31 Ağu 2020 @ 6:45 
About "Quantum Signaling" you mentioned - there is also an reverse effect to it. If there are two cubes with the same number on it, worker will go to the nearest, not to the one that was put to memory. This may produce undesirable side effects.
TheVoiid 3 Haz 2019 @ 3:31 
The picture in the part about Loop Unrolling isn't correct, every time it sets mem1 to 1 so the loop never ends ;)

But nice guide overall!
commonnickname 26 Ara 2018 @ 6:26 
Comments count towards the command limit too
Futae Yamagawa  [yaratıcı] 25 Ağu 2018 @ 8:16 
I've revised the notes for both if and jump, give them a peek and let me know what you think.

Translation:
I'm a programmer -> I therefore have poor communications skills -> I suck at even my own native language. Please, peer review my work and tell me if failed to convey information properly
threedotonefour 25 Ağu 2018 @ 4:29 
It seems like I got confused between "program lines" and "program size". I think you should remove any reference to "program lines" from the IF command reference, since placing that info there only serves to confuse, and already is better described in the "Sundry" section.
Futae Yamagawa  [yaratıcı] 24 Ağu 2018 @ 18:55 
Either I wasn't clear enough, or you didn't read closely enough. I'm not sure which. Were you reading under the command reference or the Sundry section?
--
Take a program with a single if statement, nothing else.
Copy it out to notepad.
Make it 130 if statements.
Paste it back into the game.
The game will complain because the program is, as far as it counts 'lines', 260 lines.
Remove 5 if statements (making it 250 'lines' as the game counts them) and paste that.
Add 5 instructions (say, step) via the in-game editor. Doesn't matter where or how you add them, you can add all 5, but not 6.
Remove an empy if statement, and you can put a jump statement in, but only if you don't add anyhting else first.

The game care about 'instructions' which it counts one way, for OCD challenges, and puts a hard limit on program size, by way of 'lines' which it counts another way, and neither correspond to the lines in the text version of a program. I expect some confusion from that.
threedotonefour 24 Ağu 2018 @ 5:07 
The article is wrong about "if" statements. They count as only a single line, at least in the release version of the game. So avoiding "else" statements is a way to save lines.