dMZX Forums: Self-Assembling Robotic - dMZX Forums

Jump to content

Page 1 of 1

Self-Assembling Robotic

#1 User is offline   CJA 

  • «≡larch bucket≡»
  • PipPipPipPipPipPip
  • Group: Members
  • Posts: 3,262
  • Joined: 23-June 05
  • Gender:Male
  • Location:......@.c....

Posted 06 September 2014 - 01:20 AM

With the advent of file access and robot saving/loading as text, we can do some special things with files that go beyond the ability to clone engines from board to board, etc. We can use psuedo-functions across robots and do even more with self-assembling robotic. It's useful for breaking up a very large robot into many chunks; for having one basic robot structure do many things using component-based principles. Mostly, this is useful for code organization with large projects; editing many files is easier for myself than having to handle one big file, as an engine can be split by function (much better than navigating a robot in the Editor with PageUp/PageDown, IMO). There are also other possibilities with code reuse, which is generally unheard of in my MZXing so far. The basic principle is exceedingly simple: have a loader robot string together two or more Robotic text files, then load that code in that robot. Gone is the loader robot and the newly compiled robot takes its place, ready to go.

Let's say we have a piece of code, such as this, stored in "ammo1.txt":
. "ammo1.txt"
inc "ammo" by 1


And this one in ammo5.txt:
. "ammo5.txt"
inc "ammo" by 5


Let's say for a weird example that we want to give the player 6 ammo in a super-fancy way. What we have to do in order to string these two together (since we want both of them to execute in this example) goes like so:
  • Open the temporary destination file
  • For each file to be compiled
    • Copy all bytes from source file to end of destination file
    • Write a seperator to "pad" between the files
    • Close the source file
  • After all files are copied, close the destination file
  • Load the destination file into the robot.


We get some code that looks like this:

set "temp.txt" to "FWRITE_OPEN"

. "First file"
set "ammo1.txt" to "FREAD_OPEN"
goto "#link"

. "Second file"
set "ammo5.txt" to "FREAD_OPEN"
goto "#link"

set "" to "FWRITE_OPEN"
set "temp.txt" to "LOAD_ROBOT"
& "Error loading robot!"
end

. "link: Transfer the open reading file to the open writing file, followed by linebreak"
: "#link"
goto "#getLength"
. "Transfer each byte by reading the file to a string, then writing the string to the file"
set "$temp" "fread&length&"
set "$temp" "fwrite&length&"
. "Append \r\n, just in case."
set "FWRITE" to 13
set "FWRITE" to 10
. "Close the file"
set "" to "FREAD_OPEN"
goto "#return"

. "#getLength: Get the length of a file."
: "#getLength"
. "This will seek to the end of the file."
set "FREAD_POS" to -1
set "length" to "FREAD_POS"
. "Move back to beginning of file"
set "FREAD_POS" to 0
goto "#return"


Why is \r\n appended after every file? Well, if the .txt file does not end with a line break, and the next file doesn't begin with a line break, the two lines will run together and MegaZeux will fail to load the .txt as a valid Robot, of course. Using \r\n, and not just one of those chars, will be fairly platform independent, as I'm quite sure that MZX will just convert or ignore if it needs to. I'm not entirely sure though. You may also want to append many linebreaks to make it very clear where the files start and end, if you want to open up the compiled txt (for debug purposes, etc).

Why not store the list of files as an array of strings (such as $file0, $file1, $file2, etc.)? Well of course you can do that! Just be careful with loopcount conflicts when you implement your own version. Use soft (label-goto) loops. In fact, you could even load that list of files from a text file, sort of like a makefile, that instructs the compiler what to compile and where.

Why would you ever need to use this? Well, good question. That depends heavily on your coding style. I like to chunk out my robotic files from thing to thing and often I find myself having a slew of robots doing menial tasks. By having this compiler do something like load all of the files as subroutines into a single robot, and then create a loop full of hooks to each of these files automatically, I can basically cram a bunch of stuff into one robot. Again, I don't expect many people to utilize this, but hey, that's OK because this is sort of geared towards projects that are super robot heavy; projects for people that basically want to code in a scopeless hell of a thing like Robotic instead of something else.

Why .txt? MZX is not used frequently enough to warrant a new de facto text format, and these files ARE just text. Besides, MZX natively imports non-bytecode Robots as .txt in its built-in save/load function in the Robot editor.

Why post this? Self-reference for later, maybe starting conversation on the forums, having a free hour in the evening.

Yer wrong, here's why! OK, let me know! I want to flesh out and/or abandon this concept to its logical conclusion.

This post has been edited by CJA: 25 September 2014 - 02:39 PM

Need a dispenser here.
3

#2 User is offline   Dr Lancer-X 

  • 電波、届いた?
  • Group: DigiStaff
  • Posts: 8,938
  • Joined: 20-March 02
  • Location:ur mom nmiaow

Posted 06 September 2014 - 01:58 AM

aww i thought this was a quine

But yeah, one of the things I've wanted in MZX was the ability to supply strings to atomic file access functions (like load_robot, load_bc, load charset / palette, put Image_file etc.) so that you'd be able to do this stuff but without the intermediary file.

EDIT:

Quote

loop start
set "FWRITE" to "FREAD"
loop for "('length'-1)"


Seriously don't.
set "$temp" "fread&length&"
set "$temp" "fwrite&length&"


So much faster.
Posted Image
<Malwyn> Yes, yes. Don't worry I'd rather masturbate with broken glass than ask you for help again. :(
1

#3 User is offline   KKairos 

  • not an actual chipmunk
  • PipPipPipPipPip
  • Group: Members
  • Posts: 2,245
  • Joined: 05-August 00
  • Gender:Male

Posted 19 September 2014 - 05:23 AM

CJA, I appreciated you for this. I also appreciated Lancer for his addendum.
darganflayer.net kaikairos.dev itch.io
0

#4 User is offline   CJA 

  • «≡larch bucket≡»
  • PipPipPipPipPipPip
  • Group: Members
  • Posts: 3,262
  • Joined: 23-June 05
  • Gender:Male
  • Location:......@.c....

Posted 25 September 2014 - 02:43 PM

Yeah, I always forget about that, and something didn't feel right when I made that loop, but it seemed like the most transparent way to do it. I changed it.

I'm considering adding on to this idea by making a self-test function before compile time. The tester will first write a label and set command into a file, then write the robot code and tell a dummy robot to load that piece of code and go to that label. If the robot doesn't respond (Because there was an error with loading the file), the problem can be isolated to that file. Then the compilation would proceed as normal.
Need a dispenser here.
0

#5 User is offline   Graham 

  • . "@Master Procrastinator"
  • PipPipPipPip
  • Group: Members
  • Posts: 625
  • Joined: 28-December 12
  • Gender:Male
  • Location:Oregon

Posted 13 October 2015 - 03:48 AM

Thanks for this CJA. I read this when you first posted it and made a mental note of it in case it ever proved useful. Tonight I remembered it as I was struggling to fix a difficult program. It was exactly the solution I needed, Thank you!!
Currently working on Servo for MegaZeux, I hope to complete it by the middle of 2015? Who knows...

"Before you criticize someone, you should walk a mile in their shoes. That way, when you criticize them, you’re a mile away and you have their shoes."
-Jack Handey
1

#6 User is offline   CJA 

  • «≡larch bucket≡»
  • PipPipPipPipPipPip
  • Group: Members
  • Posts: 3,262
  • Joined: 23-June 05
  • Gender:Male
  • Location:......@.c....

Posted 24 October 2015 - 07:00 PM

I'm surprsied and glad that this helped somebody

EDIT: also I forgot to mention that I'm using this for bombin' dude reloaded! All of the enemies are preprocessed to append a common core onto their code so they all interact with the engine the same way. Then later if I code some sort of weapon that, say, knocks them back three spaces, I can code that into a subroutine that does that in the common core code and they'll all react from that point forward. Each common core hook ALSO has a goto to a local interrupt, which means that if the enemy says "naw, I don't want to do that, I'm a giant three ton boulder!" then it'll have this label meant to cancel from that routine and return. It's a really awesome way to not code a lot, especially if you're someone like me that loves to make engines and hates to code enemies, pickups, etc.

This post has been edited by CJA: 24 October 2015 - 07:09 PM

Need a dispenser here.
0

#7 User is offline   Dr Lancer-X 

  • 電波、届いた?
  • Group: DigiStaff
  • Posts: 8,938
  • Joined: 20-March 02
  • Location:ur mom nmiaow

Posted 25 October 2015 - 05:21 AM

Come to think of it, I had something vaguely similar for Infinite Sky's scripting language - the main language was interpreted as-is, but it could also call "functions", which were written in Robotic. Both scripts and functions were stored in the same files, but to run a function the interpreter would paste the code for the function (along with some boilerplate) into the interpreter's code and load it - it would then execute this function and then return to interpreting. On subsequent calls the interpreter would check the currently-loaded function and just call it if it's already loaded.

Frequently used functions I pasted into the interpreter directly so it could be called as-is without needing to do this load (and without needing to invalidate whatever function was already loaded).

*dbgstuff*
giveequip(0, addeffect(addweapon("Uzi 9mm", WEP[FIREARM], 12, "t=mgun"), MOD[XMOVE], X[SWEEP-SPRAY]))
giveequip(0, addeffect(addweapon("Uzi 9mm", WEP[FIREARM], 12, "t=mgun"), MOD[XMOVE], X[RAPID-FIRE]))
addeffect(addweapon("Wakizashi", WEP[MELEE], 8, "t=sword,w=7,h=3,swing=sfx/swing1.ogg,slash=sfx/slash1.ogg,bg=15,fg=15"), MOD[TECHNIQUE], T[Fireball])
addeffect(addweapon("Wakizashi", WEP[MELEE], 8, "t=sword,w=7,h=3,swing=sfx/swing1.ogg,slash=sfx/slash1.ogg,bg=15,fg=15"), MOD[XMOVE], X[SNEAKATTACK])
giveitem(I[Medikit], 1)
giveitem(I[DBGItem], 1)

*@GiveEquip*
set "equip&$arg1&u" "$arg0"
goto "etype('equip&$arg1&type')"
: "etype0"
: "etype1"
set "equip('p&$arg0&eq_w2')u" -1
set "p&$arg0&eq_w2" "p&$arg0&eq_w1"
set "p&$arg0&eq_w1" "$arg1"

if "equip('p&$arg0&eq_w1')v3" = 1 "2h"
if "equip('p&$arg0&eq_w2')v3" = 1 "2h"
goto "fin"
: "2h"
set "equip('p&$arg0&eq_w2')u" -1
set "p&$arg0&eq_w2" 0
goto "fin"
: "etype2"
set "equip('p&$arg0&eq_a')u" -1
set "p&$arg0&eq_a" "$arg1"
goto "fin"
: "etype3"
set "equip('p&$arg0&eq_i')u" -1
set "p&$arg0&eq_i" "$arg1"
goto "fin"
: "etype4"
loop start
set "equip('p&$arg0&eq_e&loopcount&')u" -1
set "p&$arg0&eq_e&loopcount&" 0
loop 9
set "p&$arg0&eq_e0" "$arg1"
goto "fin"
: "fin"

*@AddEffect*
dec "$equip&$arg0&eff" 1
inc "$equip&$arg0&eff" "&$arg1& &$arg2& 0"
set "$return" "$arg0"

*@AddWeapon*
inc "equips" 1
set "$equip&equips&name" to "$arg0"
set "equip&equips&type" to "$arg1"
set "equip&equips&u" to -1
set "equip&equips&v" to "$arg2"
set "$equip&equips&b" to "$arg3"
set "equip&equips&v2" to 0
set "equip&equips&v3" to 0
set "equip&equips&mods" to 0
set "equip&equips&max" to 0
set "$equip&equips&eff" to "0"
if "args" >= 5 "dmgtype"
goto "fin"
: "dmgtype"
set "equip&equips&v2" to "$arg4"
if "args" >= 6 "2handed"
goto "fin"
: "2handed"
set "equip&equips&v3" to "$arg5"
: "fin"
set "$return" "&equips&"

*@GiveItem*
if "citems" > 0 "uadd"
: "ucont"
set "citem&citems&" "$arg0"
set "citem&citems&q" "$arg1"
set "citem&citems&alloc" 0
inc "citems" 1
goto "fin"
: "uadd"
loop start
if "citem&loopcount&" = "$arg0" "uadd2"
loop "('citems'-1)
goto "ucont"
: "uadd2"
inc "citem&loopcount&q" "$arg1"
: "fin"


A modern version of this approach would probably attempt to employ some form of smart caching, storing multiple code segments up to the per-robot limit and deciding which function to remove based on a policy. One complication is the need to mutate label names in functions, though, to prevent the namespaces of multiple simultaneously-loaded functions from colliding.
Posted Image
<Malwyn> Yes, yes. Don't worry I'd rather masturbate with broken glass than ask you for help again. :(
1

Share this topic:


Page 1 of 1


Fast Reply

  

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users