|
What do you really want? I thought he might like.... Given the actual speeds that the EXAs work at, I think anyone watching TV might have barely seen a blip or two, thinking it was a transmission error to a glitch for a second before their movie played.
|
# ? Mar 12, 2022 15:50 |
|
|
# ? Jun 9, 2024 14:30 |
|
berryjon posted:Given the actual speeds that the EXAs work at, I think anyone watching TV might have barely seen a blip or two, thinking it was a transmission error to a glitch for a second before their movie played. Yeah, that's never made completely clear. If you pause the simulation at any point the movie footage just keeps playing (well, repeating). Same thing with the CCTV cam footage for the ATM hack, for instance.
|
# ? Mar 12, 2022 16:41 |
|
Hacker battles are a neat idea, buh ehh.....it's seemingly impossible to make a robust solution. It's like trying to optimize rock paper scissors, you're always going to be vulnerable to one tactic when using another.
|
# ? Mar 12, 2022 18:16 |
|
GuavaMoment posted:Hacker battles are a neat idea, buh ehh.....it's seemingly impossible to make a robust solution. It's like trying to optimize rock paper scissors, you're always going to be vulnerable to one tactic when using another. feels more like they put them into the game to show that they could, competing over solution efficiency on a leaderboard feels way more satisfying
|
# ? Mar 12, 2022 18:21 |
|
Huh, you know I tried searching backwards for the keywords at one point since I noticed the same issue - one test has all the keywords near the end. It didn't work out for me. I'm shocked it works at all, the search is 50% slower due to the extra SEEK command.
|
# ? Mar 12, 2022 18:27 |
|
What do you really want? I'm not sure My zines and manuals have shipped but no delivery date yet. Work faster please, UPS
|
# ? Mar 13, 2022 22:09 |
|
Nth Doctor posted:What do you really want? They're here!
|
# ? Mar 18, 2022 19:10 |
|
Part 18 - TEC Redshift - Dev kit === Trash World Inbox === Cloudmonkey98 posted:At no point did the instructions say you lost points for your opponent's movie playing, just for you touching them, or trying to hide them in your Host room, since the enemy can't access that area, the instructions aren't incorrect As for the hacker battles, I agree with GuavaMoment here: GuavaMoment posted:Hacker battles are a neat idea, buh ehh.....it's seemingly impossible to make a robust solution. It's like trying to optimize rock paper scissors, you're always going to be vulnerable to one tactic when using another. Nth Doctor posted:They're here! Since it doesn't really make sense to talk about optimizations for the hacker battles, let's jump straight into the new update. === TEC Redshift - Development kit === You're off to a good start. I knew you were good at what you did. Even after you forgot, you picked it right back up. That's why I contacted you. Three votes for the second option. But what do you really want? All I've wanted is for you to do a little hacking for me. That's it. Really. Well, that doesn't explain anything. Leafing through the zine I found the letters page. Some interesting stuff there. First of all, heh, the letter Ember made me edit actually got printed in the zine. The original writer is in for a bit of a shock. Also, the tip about the KGOG tv station is probably where mutex got the number for the modem through which we did our hacker battle. I also like the reference to "red boxes" and "blue boxes". They were real things. Back in the day phone exchanges were controlled through specific tones (nowadays it's usually a digital signal of some kind). In the USA, red boxes could be used to make an exchange think you put a coin in a pay phone, so it would let you place a call for free. Blue boxes could be used to place long-distance calls and bill them to some other number. Anyway, I got this developer Redshift kit from Ghast, let's see if I can do anything with it. Why do you think Ghast gave you this? Two out of three votes for "I'm not sure". I'm not sure. Does he get something out of it? I suppose he enjoys helping people. Such a nice guy. Too bad the dev kit is password protected. He should have thought of that. Better not let that stop you... Yeah, no worries Ember, we'll just jailbreak this thing real quick. There's a whole section about the Redshift in the zine, but most of it is about how to develop games for it. We're not quite there yet, but here's the frst page just so you have an idea of what we're dealing with. The small print under the ad says: "Batteries not included; 3D mode not intended for use more than 15 minutes at a time; EXA is a registered trademark of Axiom, Inc. Used with permission." An early attempt at a 3D handheld where using the 3D mode for too long would cause problems? This thing seems to be some sort of mix of a Nintendo Game Boy and a Virtual Boy. OST: Code and Registers No files or anything in this thing. Our assignment simply says: There is an unknown three-digit code (such as 4-7-3) that, when entered one digit at a time into #PASS, will unlock the link between debug and secret. Find the three-digit code and create a file in your host that contains the code as a sequence of three values, followed by the development kit's RDK ID. Okay, simple brute-forcing it is. Entering some numbers into #PASS makes them appear on the little display in the secret host. If the code is wrong nothing will happen, and the fourth digit is simply the start of a new attempt. Any negative numbers or multi-digit values are ignored by #PASS. Well, we got an instruction to grab specific digits from a number, why not use that? code:
Since the #PASS expects digits from left to right while this takes the input from right to left, I actually enter the numbers in reverse. It shouldn't matter, it will try all numbers anyway, just in a different order. But since I need to store the password I'll swap the SWIZ calls around so I get the right password in X. This unlocks the secret host, but this EXA keeps going forever. The #PASS register keeps accepting digits even after entering the right password. I need to somehow stop this EXA at the right time, save its password, and go get that id from the secret host. Let's first see what we can find in the secret host, now that I unlocked it. The link id between the debug and secret hosts is simply 800 again. There's four files in there: two core dumps, some game's save file, and a file containing the RDK id. This is my first working solution. After some trial and error I decided that while a multi-EXA solution might be faster, it's gonna be hard to get the passcode out of the initial EXA at the right time. So I went for a single-EXA solution. Every loop, it tries to send a replica into the secret host. If the link is closed, the replica dies immediately. Otherwise it gets the ID from the file. Then it needs to explicitly DROP the file (if you LINK an EXA holding a file with a lock icon it dies). It KILLs twice (because by the time it gets back, the original had just enough time to execute a new REPL instruction), then goes back to the home host to write the file (which contains each digit of the password and then the ID). This runs quite slow at 5959/22/11. I tried to output it as a gif, but since it shows all digits being entered on the password display, the result is over 10MB and over 2 minutes. It also crashed my game when I tried to go back to editing afterwards. Don't try this at home. Anyway, getting the activity down should be a question of minimizing LINK and KILL instructions. We don't need to LINK back home with an EXA that waits for M signals: code:
code:
Next, let's look at cycle count. As I already said, if you swap around the SWIZ instructions, you basically change the order in which you test the passwords. Since I use the same SWIZ to write the data to the file I can easily try all permutations. Turns out 1,3,2 is the fastest at 5821 cycles, as compared to the 5959 solution. But that's just a minor optimization. I'll need to do much better. A basic loop unroll gets me to 5020/47/11. code:
It took some fiddling but this solution runs at 3405/50/17. It still uses the ADDI/SWIZ combo so each EXA keeps a full counter. I could have one EXA just store the tens digit and one just store the hundreds digit but I don't think that would matter much since that would speed up those EXAs... for them to be limited by the one having to increment the ones digit every loop. The EXA that makes it to the secret host immediately sends a REPL back to go KILL its buddies because the TRY REPLs add up fast now. In fact, I just barely managed to squeeze out a single loop unroll. The loop unroll makes the REPL trigger even faster so I needed an extra KILL, which I managed to fit in by giving XC only one starting NOOP and hoping it would LINK after XB, which it did. I also needed an extra SUBI instruction because for some reason the ones digit is off by one now. By the way, there's something cathartic about typing "KILL KILL KILL". To make this even faster, well, as I said at least one EXA needs an increment instruction in its loop so it will act as the bottle neck. The only thing I can still remove from that loop is the REPL TRY: code:
So Ghast used to work at a game studio? I'll skip this vote because all three answers lead to the same follow-up question. Yeah, he was a programmer. It says so in the zine. I wonder what that was like. This one is for the thread. Next time, we explore the Redshift dev kit. Ember would like to know why. You're really going to make a game with this? Why? I'm not offering a reward for it.
|
# ? Mar 19, 2022 16:43 |
|
I bet it was fun Making something is its own reward
|
# ? Mar 19, 2022 16:53 |
|
code:
code:
megane posted:I bet it was fun edit: GuavaMoment posted:...aside from leaving incorrect files in your home node, but as long as one of them is correct it works. I played the entire game naming my REPLs as REPL. I wonder if there is a fancy MODI command to cycle through every number and have that exa die on it's own at some point instead of using ADDI X 1 X. That would save the need for the KILL command. another method for execution/flow control is to pass a token between EXAs, like the M register or having each generation attempt to run a sequence that becomes invalid due to another EXA specifically not crashing: code:
Tinkering around further, turns out splitting the LMAO subroutine across two separate EXAs saved a bunch of cycles/lines. Also looks sillier, which is extremely important. code:
silentsnack fucked around with this message at 03:49 on Mar 20, 2022 |
# ? Mar 19, 2022 17:18 |
|
Start at 967 in X, make a new exa, subtract one from X and make another new exa forever. The new exa inputs the code stored in X and attempts to go into the secret node. It either makes it or fails and dies. Nothing terribly fancy, 2880/28/10 You can make a 19 line solution, again no real tricks... code:
Edit: You have the bog witch's approval, complete the rite of passage! GuavaMoment fucked around with this message at 18:32 on Mar 19, 2022 |
# ? Mar 19, 2022 18:28 |
|
quote:Here's an interesting question. Were Panda Expresses around in 1997? I think that meetup place in the second letter from the bottom in the rightmost column is a real location. I wonder if anyone's gone...
|
# ? Mar 19, 2022 19:18 |
|
Panda Express was founded in 1983. I have never used SWIZ and I find it fully incomprehensible lol This was my awful solution code:
|
# ? Mar 19, 2022 20:49 |
|
Part 19 - A SECRET TO EVERYBODY === Trash World Inbox === Let's see what improvements we got this time. My high scores were 2918 cycles and 22 size for the Redshift unlock. First, the size improvements. silentsnack and GuavaMoment have basically identical 19 line solutions. GuavaMoment posted:
Anyway, I thought I tried a solution where it leaves some garbage and it didn't work. Must've done something else wrong then. Next, cycle count. GuavaMoment mentioned a 2880 cycle solution is possible by counting down instead of up. It's gaming the tests a little bit - but not nearly as much as the following. silentsnack posted:
Thinking about it, what silentsnack actually did was change a brute force attack into a partial dictionary attack. Sounds much less like bullshit if I phrase it this way, wouldn't you say? So this solution makes for a good real life lesson: hacking into an account is much easier if the hacker has foreknowledge about likely passwords. That's why you should never use dictionary words as passwords (use random characters instead), and you should never reuse passwords across sites. If it gets leaked in one place, hackers will first try that same password for all your other accounts. Instead, invest in a proper password manager. Anyway, silentsnack came up with a further improvement. silentsnack posted:
I've talked about communication modes but I've not needed them so far so I'll explain it again: EXAs, by default, start in GLOBAL communication mode. That means they can receive and send messages over M from any friendly EXA in any host. You can swap them to LOCAL mode using the MODE command, or at the start by clicking the toggle on the M register. In LOCAL mode, they can only communicate with EXAs in the same host - and very importantly, only with other EXAs that are also in LOCAL mode. So, by putting XC in GLOBAL and the other two in LOCAL, XC's COPY M T will just wait until XA switches modes and sends its first GLOBAL mode package. Meanwhile, as long as XA and XB stay in the same host, they can communicate in LOCAL mode all they want. === Redshift Homebrew - A SECRET TO EVERYBODY === Before I continue, GuavaMoment reminded me that there's a Steam Achievement tied to last week's assignment. It is called RITE_OF_PASSAGE and the description states: You have the bog witch’s approval. Now complete the rite of passage. Of course it's up to the player to figure out it's linked to this assignment. Remember that random save file? We need to set RITE OF PASSAGE COMPLETE to TRUE. Not 1 for TESTs, no, the actual word TRUE. No speed goals or anything so let's just grab my initial brute force solution to open the locked host and write some code after it. code:
And that's another achievement in the pocket. Let's get back to Ember. So Ghast used to work at a game studio? Yeah, he was a programmer. I wonder what that was like. One vote for "Probably terrible" and two for... I bet it was fun, while it lasted. Figuring out how to push a console to its limits... Making something that brings joy to people... Yeah, I can see that. You can? Hm. Now that I unlocked the Redshift dev kit, it's time for some homebrew, don't you think? You're really going to make a game with this? Why? I'm not offering a reward for it. One vote for "Not everything I do is for you", but two for "Making something". Making something is its own reward. Oh, it's one of those intangible things. A sense of accomplishment? Self-actualization? I'm not good at abstract concepts. I'll have to observe you closely. You surprise me, Ember. You do understand why Ghast would make games but not why I would do so? OST: Code and Registers This is the Redshift dev kit. As you can see, it looks quite different from the other things we've done so far. Luckily the zine has a comprehensive guide on this. Welcome to this game's sandbox mode. Other than the EXAs being a bit different than we're used to, this stage has no size limit, no EXA limit other than what fits in the host and it lets you go wild. This is a special episode, I've been looking forward to showing this off since I started this LP, but I'll start with a description of all the features in the sandbox. If this is a bit too dry for you, feel free to skip to the next occurrence of the text: "Let's build something!" Let's use the zine to go through all the features. There's already a lot to cover on the first page. You can skip reading it if you like since I'll show an example of each feature. First of all, the DATA instruction. DATA is a special pseudo-instruction that indicates that an EXA should already hold a file when it starts, containing the values after DATA. All DATA instructions are parsed in order they appear in, before the game even starts. During execution, these instructions are ignored. A very convenient way to store your game data. You can place them wherever you want in your code but I prefer to have them at the start. By the way - sadly you cannot use DATA outside of the Redshift. That would make some earlier assignments much easier to solve. --- The only type of graphics in Redshift are sprites. Each EXA can hold a 10x10 sprite in the G register. An EXA can be initialized with a sprite, you can turn pixels on and off by drawing on them with your mouse. Every sprite starts out on the top left. To move it, simply write a new X position directly to GX, or Y position to GY. If I run this program for two steps, you see my drawing jump right and then down, so it appears in roughly the middle of the 120x100 pixels screen. If you really want to use the 3D mode you better get yourself some of those special glasses. Switching the 3D toggle on the Exapunks device dims the lights of the dev kit so you can truly focus on the headache inducing game. By writing a value between -9 and 9 to the GZ register, you can make the sprite pop "in" or "out" of the screen in 3D mode. In 2D mode, there's no difference. Finally, you can change the contents of the sprite itself by writing three digit values to GP. The first digit tells the EXA what to do (0 = turn pixel off, 1 = turn it on, 2 = toggle), and the second and third digit have the X and Y positions, counting from the top left. This picture is after running COPY 060 GP, turning the 6th pixel of the top row off, and COPY 199 GP, turning the pixel in the bottom right on. --- You can follow drawing code easily if you go step by step, but if you run the Redshift at normal speed (which is done with the dev kit's fast forward button), you won't see anything. That's because these draw instructions go by real fast. What you're supposed to do is use the WAIT instruction for this. Unique to the Redshift, WAIT makes the EXA wait until the next frame. The Redshift runs at 30 fps. So, if I put a WAIT instruction after all this drawing code, the user will only see the final result. That drawing hopping from the top left to the intended position? Individual pixels going on or off? That's way too fast for the user to see. A big annoyance, though, is that WAIT instructions don't cause EXAs to wait for each other. So if EXAs have different amounts of instructions and you don't sync them up with NOOPs or M communication, they will quickly desync. It's a lot to keep in mind while coding for the Redshift. As far as I can tell a WAIT instruction only takes a single cycle. So in practice, it doesn't mean "pause the EXA", it means "advance the frame of the Redshift". That means you can't even line up other EXAs by counting the number of instructions that can be run between frames (which was how real life old consoles dealt with this issue). It's weird. You're better off making sure all the EXAs are synced before doing a WAIT. Next page of the zine. If you need a score display or something you can use the built in font. Sending a value in the 300 range to GP replaces whatever was in the sprite register with that character. 300 itself is a space which blanks out the entire sprite. That could be useful. The Redshift has a built-in collision detection system, a common way for games to prevent characters going through walls, or for detecting when a bullet hits the target. You use it by first having an EXA write something to the CO (collision output) register. Then, if a collision occurs (which happens if both sprites have at least one lit-up pixel in same position on the Redshift's screen), the CI register (the bottom-most to the right) will contain the CO value of the other EXA. If there's multiple collisions, the highest CO value wins. And if there's no collisions, CI will always contain -9999. Collision ignores the GZ (3D depth) value. --- While graphics and collision are handled within the EXAs, for input and sound we need to deal with hardware registers. For input, read the #PADX and #PADY registers for the state of the D-pad. Each digit in the output of #PADB stands for one of the other buttons (X, Y, Z and Start). #EN3D will tell you if the device is in 3D mode. While a game is running, you can control the Redshift with the mouse (by clicking the buttons) or keyboard, by default WASD for the d-pad, JKL for the three action buttons, and Enter for the Start button. This can be remapped from the EXAPUNKS options menu. Finally, there are four sound registers. #SQR0 and #SQR1 are linked to square wave sound channels, #TRI0 to a triangle wave, and #NSE0 is a simple noise channel. Writing a number to any sound register will cause that sound to play continuously until a new number is sent. 0 turns it off, and for the square and triangle channels, 60 is the middle C, with lower numbers corresponding to lower notes and higher numbers to higher ones, following the piano keys as seen in the zine. Similarly, a value sent to the noise channel controls the pitch. That's basically all there's to say about Redshift development. Let's build something! As a few readers might already know, during my initial playthrough back in 2018, I got kinda nerdsniped by this sandbox and spent way too much time on it. I will show here what I built back then because I still like it. But since this is an in-depth playthrough I'll take you through the design as well. When I read the documentation, the first thing that piqued my interest was the sound channel setup. Two square waves, one triangle wave and a noise channel? That's almost exactly how the sound was set up in 8-bit Nintendo consoles such as the NES and the Game Boy. So, it should be possible to do something with that, right? And programming an actual game in Redshift is hard. Game music is good enough for me. Since I'm not a music writer, I first went to search for some sort of reference of how music is actually written in those old consoles. To my surprise I actually found sheet music for a famous 8-bit song, with the 8-bit sound wave channels as the "instruments". A bit weird, but exactly what I needed. One problem, though, I barely knew anything about sheet music. I knew about time signatures and measures and half notes and quarter notes and that's about where it ends. I had to learn about how to recognize what key the music was played in (the clef with the flat symbols), and whatever the heck this was: I mean I can figure out those are eighth notes with a rest in between. The flat symbol is easy to understand but hard to implement because when you need to convert your tones to numbers, a flat becomes an extra offset that I found easy to forget. But that little 3. That damned 3. It's apparently called a "tuplet" and it means something like "I want you to play notes that don't actually fit in the meter, so shorten all of them a bit so it kinda fits." This song plays at 144 bpm, or 2.4 per second. Redshift has 30 frames per second. That means every frame is 2.4 / 30 = 0.08 of a beat. That means one beat is 12.5 frames exactly. With a 4/4 signature, a beat is a quarter note. Since this doesn't quite fit in the frame count I decided to bump the speed to 150 BPM, because that makes every possible note I want to play a round number of frames. Half note: 24 frames. Quarter note: 12 Eighth: 6 Sixteenth: 3 And those funky tuplet notes are 4 frames each. It plays slightly fast but at least you don't get weird variation in timing due to rounding errors. With that in mind I started coding. code:
I quickly noticed that my first version sounded terrible. It sounded like one long continuous note changing pitch. I realized I needed to build in a 'breath' between each note. That's what the COPY 0 #SQR0; WAIT does. I changed the TEST to already jump out if the value is 1 (1 frame to go). It then adds a single frame of silence. So the data snippet I included plays 23 frames of sound, 1 of silence (a half note), 8 frames of silence, (a rest, part of a tuplet), 3 frames of sound, 1 of silence (an 'eighth note' in the tuplet) and so on. There's one more thing - this song has a repeat for the second part. That was no trouble to code since DATA instructions respect @REP macros. The second square wave and the triangle wave have the exact same code as the first, just a different data file. The triangle wave took a bit more effort because it has a bass clef and as the music noob I am, I had to figure out where my middle C went. Something else I noticed around this time is that it's incredibly easy to make timing mistakes while copying the sheet music into the data files - but also easy to figure out because if one instrument goes out of sync it sounds awful immediately. Finally, there's the noise channel. The sheet music's fourth instrument is not called "noise", it's in fact a snare drum. This one was harder to convert than I thought. First of all, I had to find a pitch. The noise channel is actually a quite horrible crackling noise and there was no sound I really loved, but a pitch value of 50 sounded closest to the original. Secondly, I started making a data file like for the other channels - and utterly failed. If the sheet music calls for a quarter note - well, it's not a piano or a flute - on a snare drum that's still a very short sound. It's the speed of the beats that goes down for longer notes, not the length of the sound. It turns out 2 frames of noise works the best here. The snare drum has a section where it repeats the same measure 40 times. I could've put 40 repeats in the data file but I decided to clean that up a bit, so the noise channel is handled by two EXAs. This is the first: code:
Once this EXA reaches the EOF, this indicates we've hit the repeating measure of the drums. It sends a message to M which indicates the second noise channel EXA needs to play one measure, then the other EXA sends a message back over M when it's done, this EXA counts down from 40, sending the other one repeating instructions to keep doing that measure, and once it's done the song starts over. Using this sort of back-and-forth with M was the best way I could figure out to keep these two EXAs in sync. Here is the other noise channel EXA: code:
As a final touch I created some pixel art, consisting of four sprites. It doesn't do anything, it isn't animated, but at least the screen isn't completely empty during the demo. This code doesn't do much, it just moves the sprite into the right position and then gets into an infinite loop so the EXA stays alive. And that's all of the code. I wonder, have you figured out yet which song I decided to recreate in the Redshift? Well, there's no delaying it any longer. Here it is, the recording I made in 2018. https://www.youtube.com/watch?v=sP3sPc0oHu0&t=37s My rendition of the song starts at 37 seconds. The bit before is me scrolling through all the code so you can get a sense of how much work it was putting together those data files. Here is a link to the sheet music I used. And finally, here's the game disc so you can play it for yourself. Wait what? Yes, the Redshift has an export system. It exports games as PNGs of a disc that contain the code. If you drag it into the Redshift view in EXAPUNKS, it will load the game for you. This has got to be the coolest save export system I've ever seen. You can either drag that image of the disc into this screen, or if you don't own the game, download the EXAPUNKS TEC Redshift Player for free on Steam to play the demo. The Steam Discussion Boards for the Redshift Player are also a decent place to find other solutions, including actual games you can run in the Player. They might seem like simple games but the amount of coding that went into them is impressive. EXAPUNKS really doesn't have a language that's friendly for complex programs. When you leave the Redshift dev kit, the game will ask you if you actually made a game (the best Zachtronics can do without building some sort of Star Trek AI that can magically tell if a program is a game or not). The level will count as completed if you hold this button. Congratulations! You did it. What does it feel like to be a game developer? We immediately go to the next thread vote. Time for some research. Human physiology, human morality... And the intro for the next assignment. Carbon dioxide fucked around with this message at 13:11 on Jul 2, 2022 |
# ? Mar 26, 2022 18:09 |
|
GuavaMoment posted:Start at 967 By the way I didn't want to bring it up in the update but I'm wondering how you managed to count down from here while silentsnack's solutions hardcode a check up till 990. Or do those do the digits in different orders?
|
# ? Mar 26, 2022 18:26 |
|
Ah, that's music to my ears alright. It's Great Your usual Topics
|
# ? Mar 26, 2022 18:43 |
|
Carbon dioxide posted:I wonder, have you figured out yet which song I decided to recreate in the Redshift? Ra Ra Rasputin, obviously
|
# ? Mar 26, 2022 19:16 |
|
Hah, that version was made by Quackles. Here's the original upload, which shows off all of his code. https://www.youtube.com/watch?v=dZVrbpQoqg0 So, funny story, I finished A Secret to Everybody while Quackles was in the middle of his "secret project" and we hadn't seen anything except maybe a couple screenshots. At the time I had no idea his Shenzhen I/O secret project was ALSO a song. So mine came first - but Ra Ra Rasputin's code and design is probably a factor of magnitude more complex than Secret To Everybody.
|
# ? Mar 26, 2022 19:23 |
|
... Did I copy/paste from the wrong tab? I copy/pasted from the wrong tab.
|
# ? Mar 26, 2022 19:26 |
|
Considering the decade this game takes place in, I think you should take a shot at Smells Like Teen Spirit. Also, berryjon posted:It's Great
|
# ? Mar 26, 2022 19:38 |
|
Carbon dioxide posted:Hah, that version was made by Quackles. Here's the original upload, which shows off all of his code. That thing took me, IIRC, TWO MONTHS to finish, and another bunch of time to actually write up. https://lparchive.org/SHENZHEN-IO/Update%2063/ Here's the writeup that details how it all works, with detailed code.
|
# ? Mar 26, 2022 21:14 |
|
Carbon dioxide posted:By the way I didn't want to bring it up in the update but I'm wondering how you managed to count down from here while silentsnack's solutions hardcode a check up till 990. Or do those do the digits in different orders? No idea. Spacechem has different properties on different platforms, so maybe he's not on windows?
|
# ? Mar 27, 2022 00:20 |
|
GuavaMoment posted:No idea. Spacechem has different properties on different platforms, so maybe he's not on windows? Nope. Copypasting CO2's 2918-cycle solution gives the same statistics, which should mean in the slowest run both our machines count up to the same highest value of 990. Assuming all three of us are running the same version of the game with the same pseudorandom seed; did you maybe mean "1967" in your post and/or skip a trivial detail in your explanation? The former would roll over from 1000 to 999 and SWIZ 321 is effectively MODI 1000 but as for the latter... SWIZ 1967 321 X = SWIZ 967 321 X = 967 SWIZ -1 321 X = -1 MODI 1967 1000 X = MODI 967 X = 967 MODI -1 1000 X = 999 ...MODI behaves differently with negative numbers.
|
# ? Mar 27, 2022 01:14 |
|
Ok, I see I swizzle in the order 1, 3, 2 from 976, so I input 796, 696, 596....096, 995, 895... Why do I do this? I don't know, but it works. I guess I'm a real computer engineer!
|
# ? Mar 27, 2022 01:38 |
|
Part 20 - Digital Library Project === Trash World Inbox === As I expected, Quackles' rendition of Ra Ra Rasputin in Shenzhen I/O came up in the thread. Because it's very impressive, here's a link to the Youtube video and a detailed write-up. Note that the write-up continues in the next part of that LP. === Digital Library Project === Congratulations! You did it. What does it feel like to be a game developer? One vote for "Pain" which I feel, yeah. It's though work. I prefer doing other kinds of programming. Anyway, two votes went to "great". The reward can make it worth the effort. It's great. Yeah? At least there's one thing you can enjoy. I'm not sure I fully understand it, but there you go. Before we continue, a voiced cutscene with Ember. Okay. I have a real question to ask you. Say there's a trolley on a track heading towards five people. Three of those five people are vegetarians. Once again, for the voice-acted parts, dialog choices really make no difference. Not this again... There's a switch you can throw that will shut down a meat packing facility that is located down the road. Unfortunately, the switch will also prevent the train from stopping, because... Because... Wait. I may have reversed something. Recalibrating. There are too many variables here. Okay. Let's return to this later. I need more data first. And I need more processing power. Well, that was a complete waste of time. I have two assignments available now. Let's start with the first, hacking a library. Ook! Time for some research. Human physiology, human morality... An unanimous vote. Your usual topics. Yeah, I guess so. Wait. Am I really that predictable? I'll have to change things up soon. Let's get those books. OST: Behind the Scenes We're in the Palo Alto digital library project. Looks like a quite complicated network. The assignment: - Books are stored in the host corresponding to the first digit of their call number, while a book's file ID is 200 plus the last two digits of the call number. For example, book 512 would be stored in the host 500-599 as file 212. - Duplicate each of the books requested by EMBER-2 and bring them back to your host. - The call numbers for the books EMBER-2 wants are available in the file 300. - Note that EMBER-2 will never request more than one book from the same host. Alright, let's nose around a bit first. File 300 contains Ember's shopping list. To my knowledge there's no way to reach that EXA holding a file on the far left. As for the books, here's all of them. Did you know you can use that little button with the right arrow in a file or EXA's title bar to pop it out of the left column so you can drag and drop it anywhere? I feel some of these books might not be very trustworthy, but if Ember wants them, we'll get them for her I guess. Since you can't steal from a library (that would be evil!) I'll need to copy the books. First of all, getting to them. This icon seems to indicate that to get deeper into the network, I always need to use LINK 800, and to get back home it's -1. My first attempt to get to the files looks like this: code:
code:
Since we're going to need communications between EXAs and since a lot of them will be writing in parallel, I think it's a good idea to have my single initial EXA (from which the others are replicated) start in local communication mode and just keep each WRITER in the same host as its corresponding reader. With the writer and reader code in place, the replicated EXAs start copying their files. The READER will send a 0 once it reaches EOF. After that, it conveniently self-destructs when it tries to run the MAKE instruction while already holding a file. Using 0 as EOF indicator means the WRITER can simply use the T register as an intermediate, since ALL non-0 values are considered true for the purpose of a TJMP, including keywords. All that's left is getting our EXAs back home. That can be done in a very simple way: code:
By the way, now that I got the second zine, here's a full explanation of the @REP macro. If you didn't know about the performance increase of unrolls, the zine also explains it here. And this is my first working solution. I had to compress this gif to not make it too huge. It's playing at double speed now. 290/38/74. Top percentile scores are 218, 26 and 10 respectively. Honestly, my solution isn't bad - I'm already below tenth percentile for cycles. But let's see how this can be improved. A slow part of this solution is the check if the file is done every cycle. The files have a minimum size: 34. That means if we step into the check cycle after 33 steps we're fine. I unrolled both loops to 33 direct COPYs - but it didn't quite fit. So I added some code so each does a 16 unroll twice. I set up a countdown in T for that, and had to remove some of the final LINK unroll because it didn't fit otherwise. code:
The next thing I thought of was removing the test from one of the loops entirely. The result was not an improvement but I'll share it anyway in case it inspires someone. code:
I didn't get a better score than 232 cycles, so I'll leave the further improvements to the thread. As for reducing the size, the trick is that file IDs are always globally unique. I don't need to keep track of where to go if I just simply try grabbing the correct file in every host. Don't forget merging the COPY from 300 with the first MODI, which is now possible since we don't need the hundreds digit for anything anymore. code:
Finally, activity. It's possible to get that all the way down to 10. Can you see how? To get to 10 activity I can't LINK back even once. I need to send one EXA out that communicates the data back via global M. That'll be a single file at a time so it will be slow. Also, I need to grab the files in order starting from the lowest, otherwise I'd need to track back. In other words - I'm going to need to apply some kind of sorting to file 300. It is very annoying to sort a file with EXAs. With only two registers per EXA, one which is overwritten whenever you test which value is greater, and with the fact that there's only an overwrite instruction, not an insert one, I'm not even sure if it can be done with a single EXA. Luckily we don't need to actually store the sorted file. All we need is an EXA that outputs the values of file 300 in order from low to high. And, after that, since we can't use KILL instructions, some smart handling of EXAs so that they don't get in each others way. I came up with a solution that's not that easy to understand, so I'll go through it bit by bit. It starts with three EXAs. XA sorts file 300. XB writes the new files. And XC goes visit the library. Here's the top part of XA: code:
After this, XA has some logic to send the file to the XC, my reader EXA. I'll skip that for the moment. To complete the sorting algorithm, after doing so (and while XC is busy copying a file), XA executes this: code:
Let's look at XC next. code:
It starts by getting a file ID from M, and doing the same logic as before to get the actual filename. There's a DIVI inserted so the EXA can quickly die when the program is done. Otherwise it LINKs to the next host (this is always safe, since it starts in the gateway, and Ember never needs two files in the same host), and makes a replicated EXA (FIND to see if the file is there. If it is, the replica immediately communicates over local M (message LD), which causes the MRD in the original XC EXA to be true. In that case it has to VOID LD to allow the replicated FIND EXA to continue, otherwise it jumps to NEXTHOST and tries again. If the file is found, the original has another VOID which won't be triggered for a while. The bottom half switches back to GLOBAL mode, and starts sending the file's content, ending with a 0 (GF). Then it changes mode back to LOCAL, sends message LF, which tells the original XC it should continue. At that point it switches back to GLOBAL mode and waits for the next file ID. This whole switcharoo is necessary because, for example, if you leave XC in GLOBAL mode, it will keep stealing file data that's supposed to go to XB. Speaking of which, it's time to look at the whole thing and see how XB fits into the picture. XB starts by sending a message over LOCAL M (LA). This is basically it waiting for someone to read it. XA is the one to do so, directly after the MARK FOUND. At that point, XA quickly switches to GLOBAL mode, sends the file ID to XC (GB, which we already saw from XC's point of view), then switches back and tells XB to get ready to receive data. This order is important - if XA informed XB before XC, XB might already be in global mode, stealing the file ID that XC needs. Anyway, XB switches to GLOBAL mode, and starts writing the data to a new file. Once it gets a zero (tested by using the T registry as intermediate and with FJMP ENDFILE, it drops the file, switches to LOCAL mode, and tells XA it's ready to start receiving the next file. By that time XA has already found the next lowest value, so the complicated game of telephone repeats. Once XA runs out of file IDs to send, it executes its bottom two lines: placing the special value 0 in X and then jumping to FOUND, which holds the communication protocol. It sends the 0 to both XB and XC, which will both die because of this. XA then dies itself with the DIVI 1 X T. And with that, all files are written. I probably could have done without XB, but that would mean XA repeatedly dropping its file to make another one and then pick it up again. The result is 1200/70/10. One file after another makes it slow but that's the only way to get the activity all the way down. Processing. Yes, this is what I wanted. And with that, we're at the first thread vote for today. I've been analyzing television and radio broadcasts. And I have a few questions. First of all, why do some things become popular while others don't? And the second vote.
|
# ? Apr 2, 2022 18:03 |
|
My fastest was 251 cycles, so you've done better. My lowest size was 31 but was functionally identical to your 26 line solution, it only required a tiny bit of tweaking. I was still checking if my exas were in the correct place instead of YOLOing trying to grab non-existent files. So I have nothing to add. Never ask an indie musician why their parents names are blue on wikipedia.
|
# ? Apr 2, 2022 19:18 |
|
A/C As for solution optimizations you can reduce size a bit more by dropping the EOF test code:
And faster solutions are possible if you leverage the fact that all the files have >34(?) entries, and save lines for the unroll by squeezing some control operations into cycles where the receiver is waiting for the next M signal. code:
|
# ? Apr 2, 2022 19:54 |
|
I'm gonna guess this is a vote for the Ember scenes?
|
# ? Apr 2, 2022 20:06 |
|
Carbon dioxide posted:I'm gonna guess this is a vote for the Ember scenes? ayup
|
# ? Apr 2, 2022 20:08 |
|
For the activity-10 version, I had the reader EXA send back the shelf ID it was in, plus 100. Then the control EXA in my host finds the first number in its list that is less than that number, and sends it to mean 'grab that book'. So it's a granular sort that sorts in buckets, even if the process of scanning the list is a bit inefficient each time the next book needs to be queued. The control EXA also tells the reader EXA to go to the next shelf if it doesn't find anything. Reader EXA: code:
code:
I vote for You read them all already? and Good work finds its fans.
|
# ? Apr 2, 2022 22:17 |
|
voting "happy to help" and "corporate is a gently caress" and i don't want to scroll up for the actual phrases
|
# ? Apr 2, 2022 23:08 |
|
silentsnack posted:
Huh? The heck is this for? code:
|
# ? Apr 2, 2022 23:12 |
|
I haven't started my pay through yet, but I was definitely considering how SWIZ could be used to help get the number of jumps to a book.
|
# ? Apr 3, 2022 20:28 |
|
Nth Doctor posted:I haven't started my pay through yet, but I was definitely considering how SWIZ could be used to help get the number of jumps to a book. both SWIZ X 3 T or DIVI X 100 T would accomplish that. but if you want an EXA that specifically goes to the right host, instead of just blindly spamming clones, there are multiple ways to go about it. Here's a sample code that only goes to pick up the first file in the list: code:
edit: and as usual some completely unrelated random thing reminded me go back and take another look at the Phage/Heart solution, because it kinda bugged me to have 3 separate control structures redundantly running independent countdowns of the same number. And it turns out the suspicion that there should be a better way was correct, it just required approaching the timer from a different angle. Previous best time was 62/50/45. code:
code:
silentsnack fucked around with this message at 23:03 on Apr 6, 2022 |
# ? Apr 3, 2022 22:51 |
|
Part 21 - EXA-Blaster Modem - Radio Station hack === Trash World Inbox === I ended the last update with top scores of 232, 26, and 10. Let's see what you came up with. silentsnack posted:
So, imagine you start with a file ID 512. According to the assignment, the GRAB instruction needs 212 (200 plus the last two digits). The 5 tells us what host it's in but because we try every host, we don't strictly need it. First we add 2000 to 512 with the ADDI. That's 2512. Next, we do SWIZ 2512 421. It looks more complex than it is. The second operand, 421, just says "take the fourth digit from the right, then the second, and then the first", so [2]512, 25[1]2, 251[2], forming 212, which is the actual number we need. silentsnack posted:
Then it uses a REPL setup to just send a copy of itself to every node to go look for the file - that's faster than checking if you're in the right host. There doesn't seem to be a big problem with the hosts getting too crowded because the EXAs die immediately if they can't find the file and don't all start moving in the same cycle. If it finds the file it makes a WRITER EXA and starts copying. The writer starts with a countdown from 15 which runs every 2 writes. This is all done in the spare cycles between the writes. After the internal timer runs out, it then starts doing a somewhat slower write where it checks if a separate TIMER EXA is done each write. This is necessary because without it it would block endlessly once the reader is done. The TIMER runs for a set time which corresponds to the longest file in the test set. That seems slow, but remember, only the slowest test counts so this works out very well. By the way, you can drop it to 185 cycles by moving over the SWIZ to directly below MARK SKIP. Quackles posted:For the activity-10 version, I had the reader EXA send back the shelf ID it was in, plus 100. Then the control EXA in my host finds the first number in its list that is less than that number, and sends it to mean 'grab that book'. So it's a granular sort that sorts in buckets, even if the process of scanning the list is a bit inefficient each time the next book needs to be queued. Finally, silentsnack has an update to the Mitzuzen HDI-10 Heart level (update 15 of this LP). silentsnack posted:and as usual some completely unrelated random thing reminded me go back and take another look at the Phage/Heart solution, because it kinda bugged me to have 3 separate control structures redundantly running independent countdowns of the same number. And it turns out the suspicion that there should be a better way was correct, it just required approaching the timer from a different angle. Previous best time was 62/50/45. === TEC EXA-Blaster™ Modem === Processing. Yes, this is what I wanted. Two votes for the first option, one for the second. Glad it's helping. I love ingesting a good corpus... Not that that's all I'm doing. I read the same way any normal human reads. By analyzing patterns of word recurrence and deriving correlations between concepts implicit in statistically significant word clusters. Excuse me? lmao Anyway, speaking of hungry, the zine has some new recipes for y'all to try. Mmm, sounds like another 5 star experience. For the new assignment, we have to influence the media. I've been analyzing television and radio broadcasts. And I have a few questions. First of all, why do some things become popular while others don't? One vote for "Good work finds its fans", but two for the one about big media. Big media conglomerates push some artists and abandon others. So it comes down to corporate agendas? We should test this. Think we could pick a random pop song and make it a hit? Okay, let's. OST: Code and Registers The assignment: - Connect to each radio station and replace every song in the playlist (file 200) with CAN'T (NOT) GET OVER YOU by ME2U (file 300). Each song in a playlist consists of two keywords: the song name and the artist name. - A list of phone numbers for the radio stations is available in file 301. - Note that the EXAs in global mode can only communicate if there is a path of links connecting them. - For more information see "Hacker Skills: Modem Control at the Direct Level" in the second issue of the zine. Manually operating a modem? It's been a while. If I send the 11-digit number to the #DIAL register, the modem will make a connection. Sending -1 will make the modem hang up and reset, and you can dial again. That one note in the assignment is important though. You can't communicate between EXAs if they're in completely separate networks. If an EXA needs to send a message from a radio host to elsewhere you better keep the link open. There's one more thing: Even though the modem is ours, leaving a file in the modem host (the one with the #DIAL register) will fail the assignment because for some reason that counts as leaving a trace. With a max of 100 lines we have plenty of space to play around. Let's start with the dialer. code:
The song is exactly two values (name and artist), so theoretically that should fit in the registers. Let's create a second EXA and give that a try. code:
Now I have to overwrite each song in the playlist with Ember's song. But I shouldn't add anything to the playlists, so I need to keep track of the length. That is going to require a register. We need a trick. code:
Finally, the EXA SEEKs to the start of the file, grabs the song title, and writes it over the 0s in another loop. The only thing that's left are copies of XB still replicating in the modem host. That's easily solved by just adding a couple of KILL instructions at the end of XA. Not the cleanest solution, but it works. Top percentile scores are 129, 32 and 9. Let's get closer to them. The first thing I can do is unroll the loop of the file writer, making use of the fact that a playlist never has less than 6 songs. This immediately drops the cycle count from 185 to 159, with 55 cycles and 15 activity. For some reason, changing the speed of the file writer means XA needs more KILL instructions at the end. I can use another trick to get it down a bit more to 154 cycles. code:
By the way, just to clean up the code a bit, putting a NOOP after the MARK TRY is just as fast, but XA only needs a single KILL at the end now. Of course, since the WRITE2 loop has no conditional logic anymore, it is trivial to unroll. code:
And since I have plenty of spare lines, the dialing sequence can be unrolled as well. It's manual, though, since you can't nest @REPs. 138/90/11 Conveniently, I can fit 4 dial actions. That way, the EOF test lines up perfectly after the second iteration of the outer loop. And that's the best I can come up with... or so I thought at first. I then realized I can make use of the fact the slowest case needs three repeats at the end of XB. code:
No need to do any tests in that last loop, all I need to do is seek back 3 songs from the end and run it exactly three times. Worst case, I overwrite some artist names twice with the same value. To prevent the need to SEEK back to the start to get the artist name, I just have a REPL hold it and send it to me. But there's more. If I know a playlist is at least 6 songs and at most 9, and I can overwrite data, I don't need an EOF test at all. Write six values from the start, 3 from the end. Worst case there's a bit of overlap. 122/85/11, several cycles under par. The low activity score is trickier than it seems. It's easy to get it down to 10: just merge XA and XB so you only LINK from home to the modem once. To get it down to 9 you need to remove the KILL for the ever-replicating original XB, though. The problem is you don't have much space for testing anything in XB, because you need both registers to hold the song info. I came up with a solution where XB starts with only the song title. XA sends the artist name over M twice, every time it dials a number. It sends a zero when it's done. XB waits for M, and as soon as it sees something it first tests if it's zero (in which case it stops). If it's not zero, it reads M again to store the result in T - which can now safely be done because the test is complete. Other than that it works the same as before. code:
Since I spent a lot of time getting the cycles down to 122, I'll leave the low size optimization to the threads. That was surprisingly easy. People are requesting the single, humming it to themselves, buying the album... Just because they've heard it before. Is that really all it takes? The first thread vote. And for next time... Theory: The inconsistency of ratings depends on context. We made a hit by picking a generic pop song and artificially boosting its exposure. But there are other domains where this isn't possible. For example, you couldn't change people's behavior by giving a Last Stop store a five-star rating in a restaurant guide. That would be ridiculous.
|
# ? Apr 9, 2022 16:52 |
|
Urgh. Awkard Buffet are such complete sell-outs. They only get radio play because they kiss rear end in all the right spots. I change the station every time I hear that drat "Let's Hang Out" song. Now, Blood On The Stairs I will evangelize until the end of time. First three albums are stone cold classics. Shame what happened to the lead singer, but this new guy's not too bad. Mass media is a sham and You never know...
|
# ? Apr 9, 2022 17:05 |
|
Reality is more Complex You never know God, some songs that get played all the time should never be played once, they're just bad...
|
# ? Apr 9, 2022 20:07 |
|
Mass media is a sham and You never know...
|
# ? Apr 9, 2022 21:42 |
|
Carbon dioxide posted:By the way, now that I got the second zine, here's a full explanation of the @REP macro. code:
Nth Doctor posted:Mass media is a sham and You never know... Nth Doctor posted:Lol I quoted Junpei and removed the tag for my post. Guess it would have been funnier to keep the meta-joke going by directly copying instead? silentsnack fucked around with this message at 02:29 on Apr 10, 2022 |
# ? Apr 9, 2022 23:14 |
|
|
# ? Jun 9, 2024 14:30 |
|
Lol I quoted Junpei and removed the tag for my post.
|
# ? Apr 10, 2022 00:26 |