Monday, January 23, 2012

Gnarlers are about to become my favorite critter

I was trying to make a video showcasing the progress on the Garden Box, only to discover than my microphone has finally died, and I can't explain it as well with text-captions. So in the meantime, have something cute:

Thursday, January 12, 2012

Counting the Images in a Sprite File

This is it, my friends.
These are these obscene lengths we go to to completely screw with the engine in ways it was probably never meant to be used, to get some pointless little piece of information out of it.

Dear, dear C2E developers. Why did it not occur to you to include a command to list how many images are in a sprite file? Even a modification of SNAX to check if a particular pose existed would have been lovely. No, instead it comes to this, scripts in which ERRORS ARE VOLUNTARILY THROWN to find out something so, so simple.

Le sigh.

So I'm sure this breaks every Best Practice for coding... but the basic idea behind the code is this.

We create an agent, that, upon being mesg wrt+'d a sprite filename, creates a test agent with that sprite file.
It then turns autokill on to avoid the inevitable errors, and then prompts the text agent to increase its pose.
After each pose increase, it checks to see if it's still there (and hasn't autokilled itself).
It keeps count of the pose increases and, when the agent does error and autokill, it outputs the last post increase that worked, and thus the last image in the file.

I'm ...fairly certain autokill is not meant to be used this way. And I'm not sure what the consequences might be of running scripts like this constantly, ones that create and hide errors. I'm not a fan of using autokill to cover up mistakes or problems that could be solved by better coding. But I think this is the only choice in this case.

What would you guys call this? Clever error handling, or a dirty trick?

View the cosfile here, and make whatever use of it that you wish. Edit, copy, re-purpose, whatever.

Injecting the code itself will do nothing at first-- here is how you use it:

If you're just testing it from the command line:
rtar 1 1 22932 mesg wrt+ targ 1000 "[FILENAME]" "_hand" 0
Will make the hand-bubble output the number of images.

If an agent is prompting it, you can do it one of two ways:

rtar 1 1 22932 mesg wrt+ targ 1000 "[FILENAME]" "[STRING]" 0
This will have the agent set the [string] as a NAME variable in the FROM agent as an integer containing the count. So if your string is "spritecount" then the agent will setv NAME "spritecount" to equal the number of images so the agent can access the number later.

rtar 1 1 22932 mesg wrt+ targ 1000 "[FILENAME]" [INTEGER] 0
This will tell the agent to MSG WRT+ the script of the given [integer] of FROM agent, with _p1_ being the results of the image count.

Since the image-counting agent takes several ticks to count through, the output won't be available for use immediately, hence the second option.

A couple of thoughts on this whole thing:

The notion of creating a dummy/test agent is something I came across while writing the Garden Box. As I was pretty much re-writing the agent injector, I referenced it a lot and found that the injector has a similar mechanism-- it actually creates a "dummy" injector that injects the agent, and if it throws any errors, collects and displays them in the injector window. This way the agent injector doesn't autokill itself. Granted, the agent injector doesn't turn autokill on and try to create errors.

I'm sure this system, dirty as it is, could be applied to discover things other than counting images, I'm just not sure what.

And intentional error throwing aside, the actual way this agent works is something I've been wanting to try for a while-- you mesg wrt+ something to it and it returns a variable-- so the agents sort of talk to each other. I think maybe systems like this could be used to implement really primitive functions. Unfortunately it's not something that can be done instantly, but it might have some use down the line.

I sometimes think I'm completely losing my mind in this stuff. I question enough on a daily basis why exactly I continue to dig so deeply into a coding language that maybe a hundred or so people in the world, tops, will ever gain any benefit from. And now in cases like this, I'm not even coding for the sake of making the game better; I'm coding for the joy of solving problems that no one even needs solved.

I should get back to working on the garden box. Actually the garden box itself has been done for weeks, it's just that I was writing the patch plant scripts and got sick of coding dialogue boxes and went off to find a way to make that easier and started poking in PHP and I don't even know when I decided to try and find a way to count sprite files. But maybe I'll get back on track now. Kind of. I still need to develop a decent dialogue box system; that's going to take time.

I still can't believe there's no command for counting images. Knowing me though, there probably is, and I'm just blind to it, and went through all this agony to make myself look ridiculous.

It was fun agony, though.

Wednesday, January 11, 2012

CAOS Notes: WOLF

From the CAOS documentation:

WOLF (integer) kanga_mask (integer) eeyore_mask (integer)
Provides various functions to distort space-time and otherwise help with wolfing runs. Set an AND and an EOR mask, to control the following bits:
1 - Display rendering. Turning it off speeds the game up.
2 - Fastest ticks. The game usually runs at a maximum of 20 frames per second. If this is set, it instead runs as fast as it can.
4 - Refresh display at end of tick. If set, then the display is updated at the end of the tick, and the flag is cleared.
8 - Autokill. If set, agents which generate run errors are automatically killed, as the command line option.

This can be a pretty confusing command to understand. It seems, just by glancing at the bits that this would work something like ATTR, wherein, say, if you wanted to have both autokill and fast ticks on, it would total to 10. But knowing that, where do these "kanga" and "eeyore" masks come in?

It's a little complex, but once you get the hang of how this works, it's really pretty neat. In fact, I kind of wish ATTR and BHVR worked this way-- you could accomplish more in fewer lines of code.

The thing about WOLF is that it's an integer, not a command. You can't set WOLF by just entering WOLF 8 or whatever, like you would with ATTR and BHVR. You have to actually set it as though it were a variable to alter it.

To find out what your game's WOLF currently is, open the command line and enter outv wolf 15 0. Why 15 and 0? We'll get to that.

Depending on your autokill status, your game probably returned 1 or 9. 1 being on for display rendering, and 8 being added to that if your autokill is on.

So here's a bit of mental review; WOLF only has four traits to worry about, so it's easy to take an output value and do the math in your head. So if your WOLF returned 15, what traits would be "on"? What if it returned 12? 7? 0? You'll have to have a decent grasp on this to understand how WOLF works.

15 would mean, yes, that all four traits, Display (1), Fast Ticks (+2), Refresh (+4), and Autokill (+8) are on. 12 would mean only Refresh (4) and Autokill (+8) are on, and 7 means Display (1), Fast Ticks (+2), and Refresh (+4) are on. 0 implies that no traits are on at all. This might be elementary to you by now from working with similar constructs in ATTR and BHVR.

Bear with me-- let's repeat the exercise looking for different answers. If WOLF returned 15, what traits would be "off"? What of 12, 7, or 0?

I'm sure you're clever enough to figure out the answers are the opposite of the above-- if a trait isn't on, it's obviously off. So 15 would have no "off" traits, 12 would have Display and Fast Ticks off, 7 means Autokill is off, and 0 means that all four traits are off.

I hope this exercises aren't totally fruitless-- the point that when you glance at a WOLF number, you need to think of it in terms of both what traits are off, as well on.

So now that your WOLF deciphering muscles are working, let's dive into the hard stuff: The masks.

These four "rules" here are all you need to know to decipher what your AND ("Kanga") and OR ("Eeyore") masks need to be:

1. If a trait is off in the AND mask and on in the OR mask, the resulting trait will be on.
2. If a trait is off in the AND mask and off in the OR mask, the resulting trait will be off.
3. If a trait is on in the AND mask and off in the OR mask, the resulting trait will be the same.
4. If a trait is on in the AND mask and on in the OR mask, the resulting trait will be the opposite.


Using these masks, then, you will essentially be able to, in one line, set your wolf controls any way you want them, even taking into account what they already are.

Let's go back to the line we used: outv wolf 15 0.
In this case, 15 is the AND mask, and 0 is the OR mask. That means that all the traits are on in the AND mask and off in the OR mask, which, according to rule 3, the traits will remain the same, unchanged, and the output will be the current WOLF value.

But let's say we wanted to turn all the traits on. To turn a train on, we have to follow rule 1, and make sure all the traits are off in the AND mask (making it 0) and on in the OR mask (making it 15). So we would outv wolf 0 15, which should return 15 and, depending on your computer, may make your world look like it's in super-speed mode (due to both fast ticks and rendering being on).

Before I go any further I need to address something odd before all sorts of questions come up. WOLF is a little bit odd in that 1 (Display) and 4 (Refresh) cannot be on at the same time. If the game is displaying rendering, there's obviously then no reason to refresh the display as it's already being refreshed. So if you set WOLF to 15, 5, 7, or any value that sets both Display and Refresh to on, the engine will automatically turn refresh back off after setting it. So even if you use outv wolf 0 15 to set the WOLF to 15, if you enter outv wolf 15 0 to check it, you'll get back 11, since refresh has been turned off. As far as I can tell, Display always overrides Refresh, not vice versa.

Anyway, now that that's out of the way.

Quiz time again: What would outv wolf 0 0 do?

Since all traits are off in both AND and OR masks, we would look to rule 2, which tells us all the traits will be off. Thus the above command would set your WOLF to 0. It will also sort of freeze up your game, since Display is off-- opening and closing Wolf Control will reset it to normal.

But let's get down to practical information now-- if you're coding something interesting, chances are you're not looking to turn everything on and off at once. Let's try a line that toggles fast ticks on and off. This will really only be apparent on machines that are fast enough to benefit from fast ticks with the display still running-- you might want to try it in a clean and undocked DS world if you're not seeing the difference.

outv wolf 15 2

Enter that once and watch your game spaz out. Enter it again and watch it return to normal.
Can you decipher why this works? This table might help explain exactly what's going on in this command:

AND OR Rule Result
Value 15 2 * *
1 - Display ON OFF 3 Same
2 - Fast Ticks ON ON 4 Opposite
4 - Refresh ON OFF3Same
8 - Autokill ON OFF 3 Same

So setting up the masks this way allows for all the other traits to stay the way they are, while fast ticks is set to toggle (turn off if it was already on, turn on if it was off). In fact, you could use this table as a tool to work backwards from to find the masks for virtually anything you want to accomplish.

Say you want to make a switch that turns Display on, toggles Fast Ticks, turns Refresh off, and leaves Autokill the way it is. You would start with a table like this, putting in your own desired results.

AND OR Rule Result
Value ? ? * *
1 - Display ? ? ? On
2 - Fast Ticks ? ? ? Opposite
4 - Refresh ? ??Off
8 - Autokill ? ? ? Same

Next you look at the rules that would give you those desired results. I'm going to paste them again so you don't have to scroll all the way back up:

1. If a trait is off in the AND mask and on in the OR mask, the resulting trait will be on.
2. If a trait is off in the AND mask and off in the OR mask, the resulting trait will be off.
3. If a trait is on in the AND mask and off in the OR mask, the resulting trait will be the same.
4. If a trait is on in the AND mask and on in the OR mask, the resulting trait will be the opposite.

So if you want Display to be on, you'll have to find the rule that gives you the on result. Since that is rule one, you'll want to follow it, setting the trait off in the AND mask and on in the OR mask:

AND OR Rule Result
Value ? ? * *
1 - Display OFF ON 1 On
2 - Fast Ticks ? ? ? Opposite
4 - Refresh ? ??Off
8 - Autokill ? ? ? Same

Now just fill in the rest of the chart, following the rules reversely.
To get opposite fast ticks, follow rule 4 and set both masks to on
To turn refresh off, follow rule 2 and set both masks to off.
Finally, to keep autokill the same, follow rule 3 to set AND to on and OR to off.
In the end, you should have something like this:

AND OR Rule Result
Value ? ? * *
1 - Display OFF ON 1 On
2 - Fast Ticks ON ON 4 Opposite
4 - Refresh OFF OFF2Off
8 - Autokill ON OFF 3 Same

What does that leave? Just adding up the values of your on traits. Fast ticks (2) and Autokill (8) are on in your AND mask, totally to 10, while Display (1) and Fast Ticks (2) are on in your OR mask, totaling 3.

AND OR Rule Result
Value 10 3 * *
1 - Display OFF ON 1 On
2 - Fast Ticks ON ON 4 Opposite
4 - Refresh OFF OFF2Off
8 - Autokill ON OFF 3 Same

And that means, to set these values via the command line, outv wolf 10 3.

And that, my friends, is how you spend 14 hours using WOLF to set some settings you will probably never use.

You're probably going to pull your eyes out of your head and cry when I reveal the absolutely trivial purpose I have behind working all this out.

TL;DR:
I don't blame you. Screw it, I'll just write up a WOLF calculator someday.

CAOS Notes: ORRV

 Let's say you want to make everything in your world carryable by the hand.

This is actually a terrible idea and a great way to screw up your world, but let's throw all that to the wind and have ourselves some chaos.


enum 0 0 0
    setv va00 attr
    orrv va00 2
    attr va00
next


Yes, 0 0 0. If this kills your game you may want to filter it a bit.

ORRV is another weird little command. If you ORRV an ATTR or BHVR value, it will, similar to ANDV, spit out a number that will tell you if the value you're checking is set or not. Only if the value is set, instead of spitting out the value you're checking, it'll spit out your original attr/bhvr.

So in our last lesson:
     setv va00 bhvr
    andv va00 16

If va00 = 16, the eatable bhvr is set.

You can do the same thing with ORRV:
     setv va00 bhvr
    orrv va00 16

But va00 will equal bhvr, not 16, if that bhvr is set. (doif va00 = bhvr...)

There's always a thousand ways to code the same thing, so just do whatever you want.
ORRV, however, has this neat little side effect, you see. If the value you're checking for is not set, ORRV will return the ATTR or BHVR value that your agent would have if it was it set.

So if you want to set an agent as invisible, suffering physics, or whatever, ORRV it, and then just ATTR the value. If it's already set, it'll have no effect, and it if it's not, it will be.

Of course, you could accomplish the same with ANDV, it would just take more lines than necessary:

enum 0 0 0
    setv va00 attr
    andv va00 2
    doif va00 ne 2
        setv va00 attr
        addv va00 2
        attr va00
    endi
next


ORRV is just easier in this case.

Avoid using this to set BHVR values, since those, unlike ATTR values, actually need certain scripts to run and will throw errors if you don't have them. Also remember that if you set an agent to suffer physics, you'll actually have to give it some physics for it to mean anything (ACCG, ELAS, FRIC, etc).

So ORRV is nice for setting attributes an agent doesn't already have, but if you wanted to, say, make all your agents unmovable (to restrain yourself from interfering in a wolfling run, maybe), you'd still have to subtract the value manually:

enum 0 0 0
    setv va00 attr
    orrv va00 2
    doif va00 eq attr
        subv va00 2
        attr va00
    endi
next


Anyway, hopefully by now you have the hang of using ANDV and ORRV for your ATTR/BHVR checking and changing needs. I'm still grasping it myself, so if you're a wiser sort and see anything that I'm missing, do share the knowledge for the benefit of all!

CAOS Notes: Can I eat this?

Ever want to use CAOS to check if an object is edible? Invisible? Pickup-able by the hand?

Deciphering ATTR and BHVR values at a glace isn't the easiest thing in the world, and it's not exactly glaringly obvious how one would do so with CAOS, either. This is just a really simple script that teleports everything in the world that is edible by creatures to the hand, to demo how you might go about identifying BHVR or ATTR values in an agent.

enum 2 0 0
    setv va00 bhvr
    andv va00 16
    doif va00 = 16 and movs = 0
        mvsf mopx mopy

        velo 0 0
    endi
next


(Yes, this enums through everything in family 2. In big worlds, on slower machines, you might not want to run this script as it may lag you to oblivion and back. Try a clean DS-standalone world if you're having problems.)

It's really difficult to explain exactly how ANDV works if you have no background knowledge of bitwise operators. Heck, I confuse myself with it. But what you really need to know is this:

If you ANDV an agent's ATTR/BHVR value with the ATTR/BHVR value you're checking for, it will return that same value if it is valid.

Say you want to find out if an agent is set to Suffer Physics (ATTR number 128), you would set the ATTR in a variable and ANDV it 128. If it returns 128, the agent does indeed suffer physics. If it returns anything else, it does not.

So in this above example you can see that we've taken the BHVR number that declares the creature can eat said agent, 16, and ANDV'd it to the BHVR. If it returns 16 (and movs = 0, to stop it from trying to move items in vehicles and throwing errors), it is indeed edible, and thus is moved.

If you run this script, assuming your pointer is in a valid spot, all the edible objects in the world should come spewing forth from your fingertip. You'll notice this includes edible critters, including fish from your ponds and pests. Go on and try it!

You did try it, right?

You've probably noticed then, depending on what you've got in your world, that some of the agents weren't the sort of thing the game intended on having moved. Apples and blossoms may hang in midair, as well as other fruits that had been growing on plants. As an exercise, you might try altering the script to check for physics and collisions as well,

Here's a hint-- you can add the values together that you want to check for. For example, if you wanted to check if a creature could push (BHVR 1) and hit (BHVR 8) an agent, you can add those two and simply ANDV the BHVR 9. If it returns 9, both conditions are true.

I know this is supposed to be a tutorial, but I am having way too much fun spewing food and critters all over the place, so I will have to come back to this later. I am sure you more mature developers out there can actually find something useful to do with these commands.