Install Steam
login
|
language
简体中文 (Simplified Chinese)
繁體中文 (Traditional Chinese)
日本語 (Japanese)
한국어 (Korean)
ไทย (Thai)
Български (Bulgarian)
Čeština (Czech)
Dansk (Danish)
Deutsch (German)
Español - España (Spanish - Spain)
Español - Latinoamérica (Spanish - Latin America)
Ελληνικά (Greek)
Français (French)
Italiano (Italian)
Bahasa Indonesia (Indonesian)
Magyar (Hungarian)
Nederlands (Dutch)
Norsk (Norwegian)
Polski (Polish)
Português (Portuguese - Portugal)
Português - Brasil (Portuguese - Brazil)
Română (Romanian)
Русский (Russian)
Suomi (Finnish)
Svenska (Swedish)
Türkçe (Turkish)
Tiếng Việt (Vietnamese)
Українська (Ukrainian)
Report a translation problem
A few years ago I was doing the same using the cheat engine until I lost my spreadsheet :( There is (was?) a variable in the memory that increments by 0.016 each time you click next step on an empty loop, I was using that as my basis. (this also corresponds to most animation frames) But my times are exactly the half of yours, like orthogonal step taking 21 frames instaed of 42 cycles.
A few observations:
STEP is slower when a worker goes over the bottom edge of a datacube. (N, S and NW, NE directions are affected). You can see this on the animation, where the workers step to a side diagonally, instear of walking directly N or S. This has a concequence where if you have to traverse S to N while writing to cubes, it's much faster to PickUp N + Step N than Step N + PickUp C. But, if you have to go accross multiple cubes in such way, it's better to step to memory to the last cube in the sequence, rather than stepping n times directionally, because workers would then only step to the side once instead of for each cube.
STEP to memory takes an addional frame.
Workers have what I called an "index". I don't know how it works internally in the game, but my working theory was that workers are put in an array and evaluated each frame in order. This means that if one worker is evaluated first, then the results of their action are available to workers with higher index on the same frame, while the workers with lower index have to wait until the next execution cycle. (If you put to workers side-by-side and tell them to step E or W, then depending on their indices they will step simultaneously in one direction, but in another direction the second worker will lag by 1 frame).
There isn't a convenient rule how to determine the indices though, so you need to determine them experimentally on each level. (I assume this is just the order in which the developers placed them on the map?). I put this mechanic to use on the last level, where you could shave off up to a second if you made workers walk in specific order.
Unfortunately this mechanic makes it a pain in the butt to determine exact timing of actions that involve 2 or more workers, because you need to measure it 2 separate times, once with the 1st worker having higher index and then again with the 2nd worker having higher index.
Another thing to look out for is timing with different actions. This mechanic works reliably when, for example, a worker who's trying to execute a Step is waiting for another worker who executes a Step. But what if another worker executes a Tell? Do all commands run on the same cycle, or are there separate cycles for 'green', 'blue', 'yellow' and 'red' commands?
GiveTo consists of 3 (4?) stages: 1) identifying the target (memory or directional), 2) walking up to the target and ( 4) waiting if necessary?) 3) giving animation. Giving in diagonal directions was surprisingly faster than giving in orthogonal directions. The whole thing also depends on the indices, so I gave up on measuring it precisely.
Calc depends on whether it's only memory or directional. Also, it's slower when the direction is in the first argument, rather then the second(!!).
ForEachDir is whacky as hell. It seems that the rule is thatthe sum of all cycles has to add up to less than 32 frames. So for 1 direction you have (1 cycle) * (31 frames) = (31 frames), while with 8 directions (8 cycles) * (3 frames) = (24 frames).
If the body of ForEachDir is compeletely empty, then the loop only runs for 1 cycle, and takes the time to execute the single cycle. BUT if there is anything in the body, including JUMP destinations or even comments then the loop runs for however many cycles you specified. (This means that comments aren't purely decorative and can actually influence the program logic, hehe)
Also, you can compeletely avoid the time loss on ForEachDir on the first iteration if you jump into the body, instead of letting it execute as normal:
Another funny thing about ForEachDir is that sometime it doesn't take any time for execute itself, but instead it lengthens the time of the next action. For example, directional SET takes, I believe, 31 frames to execute, but it actually sets the memory on the 15th frame. But you can influence the timing of this moment by prefacing SET with ForEachDir.
e.g. "if":
Determining the timing for walking speed was similar; one of the workers just walked less, and instead attempt to compensate for the missing "step"s by adding in other (known-time) commands until they stayed in sync again.
Other commands like pickup/drop were done together, then separately trying to establish that they had the same duration as each other.
As for the half/double values thing: All my values were originally halved like yours, until I hit weird case where workers pass through each other.
Despite the two upper workers crossing over each other twice, only a single "set" was used to keep the upper and lower workers walking in sync, i.e. walking through each other had a cost penalty of 0.5*"set"
It's entirely likely that this is some weird edge case due to the worker evaluation order thing you discovered earlier.
That's pretty whacky. I had a test where I was checking if moving through a datacube slowed things down - but I only checked w/e, so it didn't occur to me to check n/s.
In fact when I was trying to determine diagonal speed, I "relied" on it because the worker moving in diagonals was passing over more datacubes than the control worker - but from the top, so they never actually touched the lower edge of the cube.
Probably would have noticed something was up if they were just a single step lower.
Both giveTo and takeFrom were challenging to test in the way I was doing it, that I sort of just gave up on them.
Calc was, for some insane reason, among the first things I tested and I entirely forgot to check directions on it - I did however check that the operator doesn't seem to matter.
I was only testing the overhead of the command itself, so all my tests on "if" and "forEachDir" were empty bodies - did not even expect that forEachDir would be skipping loop bodies.
Hastily redoing tests on forEachDir (with a comment in the body only), I got:
If we divide the non-empty-body times by the number of directions, it gives [62, 30, 20, 14, 12, 10, 8, 6]
Or, the same timing as when the body is empty (where we assume it's skipping steps).
I'm not able to properly determine what is actually happening here, but I think the answer is most likely that it has both a variable time based on the total number of directions, and an optimisation which skips additional executions of empty loops.