Jump to content
IGNORED

Magic with rand and &


Random Terrain

Recommended Posts

Here's some magic that batari posted:

 

http://www.atariage.com/forums/index.php?s...t&p=1503409

ballx=(rand&127)+16

bally=(rand&63)+8

 

OK, it's not magic, but I don't understand this stuff, so it's magic to me. I played around with what batari posted and it's pretty cool. For most numbers, you get a random number between 0 and the number that you used. For example, (rand&15) gives you a random number between 0 and 15 and (rand&10) gives you a number between 0 and 10. But if you use 2, 4, 8, 16, 32, 64, or 128, you don't get a random number between 0 and one of those numbers. For example, if you use (rand&16), you only get one of two random numbers, 0 or 16, there is nothing in between. This is a good thing to know. I'm sure it will be useful.

 

Adding a number at the end changes the starting position from 0 to whatever number that you used, but you can also multiply by 2 in case you need to skip every other number. So (rand&15)*2 gives you 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30. And (rand&15)*2+1 gives you 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31. I'm sure that will also be useful one day for some type of game.

 

Because it cuts out the need for extra if/then statements, this stuff slightly reminds me of modular arithmetic that I read about in RUN magazine and RUN's The Best of Magic and used on my Commodore 64. Here's something from page 43 of RUN's The Best of Magic:

 

Modular arithmetic counts to a limit, then circles back. An example is the arithmetic found on clocks: even though hours increase forever, they are never registered beyond 12. A clock counts . . . 10, 11, 12, 1, 2 . . . and so on, in a method called modulo 12 addition. There are several ways of doing this on a computer, the most obvious being to increment a variable, then test it with an If . . . Then statement. The following line does it all at once, in one easy statement.

 

10 X=(X+1)-INT(X/12)*12

 

Here's a more general form of doing the same thing for different modulos:

 

20 DEF FNM(X) = (X+1)-INT(X/MAX)*MAX

 

The variable MAX should be the last number allowed before the counter rolls over to 1. Unlike much computer counting, modulo counting starts at 1, rather than 0.

 

~Dave Straub, Petaluma, CA

 

To avoid using unnecessary if/then statements, I also used stuff like this on my Commodore 64:

 

C=-((C=0)*11+(C=11)*12+(C=12)*15+(C=15))

 

C=-((C=1)*15+(C=15)*12+(C=12)*11+(C=11)*0)

 

X=(J=4)*8-(J=8)*8

 

Do you think batari Basic can or will ever be able to do modular arithmetic and the stuff I posted above?

Edited by Random Terrain
Link to comment
Share on other sites

Clairification:

The & operator instructs what value of bits to keep. So it's not necessarily an odd number that you should use for a full range of values...&15 is just keeping bits 3 to 0 of the random number (which add up to a value of 15 when they are all on) - 8+4+2+1. If you use &16, the only value that is kept is that of bit 4...16 if on, 0 if off. &14 would keep an even number between 14 and zero, for example. &120 would be a multiple of 8 less than 128.

Link to comment
Share on other sites

Clairification:

The & operator instructs what value of bits to keep. So it's not necessarily an odd number that you should use for a full range of values...&15 is just keeping bits 3 to 0 of the random number (which add up to a value of 15 when they are all on) - 8+4+2+1. If you use &16, the only value that is kept is that of bit 4...16 if on, 0 if off. &14 would keep an even number between 14 and zero, for example. &120 would be a multiple of 8 less than 128.

Thanks. As I said, I don't understand this stuff, so I don't understand most of your explanation. Are you saying that there are some even numbers we can use that will spit out more than two numbers?

Link to comment
Share on other sites

That is correct (if bB is treating the & operator the same way that other Basics do). Here are the values of the 8 bits when on...

 

bit 7 = 128

bit 6 = 64

bit 5 = 32

bit 4 = 16

bit 3 = 8

bit 2 = 4

bit 1 = 2

bit 0 = 1

Now I see what you mean. I was using those even numbers you listed and skipped over other even numbers such as 10 and 12. It's like I developed a blind spot for even numbers that weren't 2, 4, 8, 16, 32, and so on. Weird. :dunce:

 

Thanks. I'll edit my original post so it won't confuse people.

Link to comment
Share on other sites

And is a bit logic operator. The truth table is:

 

for each bit:

 

0 and 0 = 0

1 and 1 = 1

0 and 1 = 0

1 and 0 = 0

 

Both bits have to be a one, or the result is zero! That's what and does.

 

An 8 bit number has 8 bits in it, and goes from 0 to 255. When you and it with another number, you are keeping only the bits from both that both equal 1.

 

eg:

 

00001011

00000111

 

00000011 <--- Result of and

 

The bits each equal a power of two, and that's the chart above my post.

 

One very easy way to use this function is to just take the closest power of two, say 8, then subtract 1 to get all the bits set up to that particular power of two, then use that to and with another number to get a result that will always be within that range.

 

eg:

 

Let's say 8, so that's 1000 in binary. (I've left off the upper 4 bits, which are zero) Now, subtract 1 to get 7. That's 0111 and is your bitmask.

 

Say there is a counter in your program that's always counting something and it's 8 bits. So it might contain this: 00010011

 

After the and, it's only going to contain a number between 0 and 7, because those are the only bits where a one result in both numbers can occur.

Link to comment
Share on other sites

Thanks, potatohead. I'm not quite sure what you were talking about near the end.

 

Based on what has been said so far, here is a modular arithmetic type of example using & that loops between 1 and 16:

 

x=(x+1)-(x&16)

 

I can replace the 16 with any number that Nukey Shay listed and it seems to loop between 1 and that number (2, 4, 8, 16, 32, 64, and 128). What could I do to that to make it work with other numbers such as 12?

 

 

Thanks.

Link to comment
Share on other sites

Doing a number, such as 12, isn't going to work with this simple operator. The problem is the way it works. Most numbers have a combination of ones and zeros that make the & operator useless. eg: 6 = 0110 When you apply the truth table, it's easy to see some numbers won't come through. The number 1 won't, because it's 0001, and that wouldn't get through the & 6 operator just discussed.

 

Really, this is just a limited kind of short cut that only works with numbers that have all ones in their binary representation. 11, 111, 1111, 11111, etc... Outside of that, it's better used for setting / resetting flags, pixel operations, and other logical kinds of things.

 

There is also boolean math ops. I used this kind of math in Atari basic and liked it. Used to do stuff like x = x + (x < 10). That would count x up until it equaled 10, then not count any more. Sweet. Really though, it was nothing that could not be done with an if, then statement.

 

bB is simple, but runs fast. So, why not just do the following?

 

if x < 13 then x = x + 1

if x = 13 then x = 0

 

This will count x up from 0 to 12, runs quick and just works.

 

Maybe do this also:

 

if x < 13 then x = x + 1 else x = 0

 

That one, if it works (and I'm not at a machine to check), does it in one line.

 

IMHO, it's all plenty fast. So, apply simple constructs first and get things working, then work on speed / space issues second. I don't think much is gained by trying to extend the & operator past what has been discussed here.

Edited by potatohead
Link to comment
Share on other sites

To avoid using unnecessary if/then statements, I also used stuff like this on my Commodore 64:

 

[bunch of nifty math here]

 

What you are doing is just expressing the decision in a different way. IMHO, it's also a harder to parse way too. That all depends on the reader and what their experience is.

 

When you do something like:

 

x = x + (x < 5), you are writing an if-then!

 

All just a matter of expression.

 

if x < 5 then x = x + 1

 

works the same way.

 

The meaning here is that the if-then is necessary. Really what is being discussed is a conditional program operation. How we get to that condition is just style and expression, but the condition IS NECESSARY, right?

 

Carrying that a bit farther then, we get to what the gain is. Does x = x + (x < 5) run faster than if x < 5 then x = x + 1? Maybe it takes less space. Could be that one is easier to think about than the other is.

 

If the function is there, and it's a gain, well then use it of course. If that function isn't there, kludging it is highly likely to not be a gain, so maybe not use it, or branch out and use what functions are there!

 

I'm working on the Propeller right now. It's a very interesting and different little CPU. Powerful little bugger, but it's a lot different from what I am used to on 6502, 6809, etc....

 

Kludging got me some familiarity, but it has held me back in some ways too. One biggie is that it does not have easy indirect indexing. That's like STA $50, X. Miss that. On the other it's got conditional instructions and those save lots of time as they don't have to be part of compare and branch loop constructs, making for denser and faster code.

 

bB is going to be like this when compared to the C64 basic. Some things are going to be really easy, others aren't. Better to see if there is really a gain overall before following a path too far.

Link to comment
Share on other sites

bB is simple, but runs fast. So, why not just do the following?

 

. . .

 

IMHO, it's all plenty fast. So, apply simple constructs first and get things working, then work on speed / space issues second. I don't think much is gained by trying to extend the & operator past what has been discussed here.

bB is going to be like this when compared to the C64 basic. Some things are going to be really easy, others aren't. Better to see if there is really a gain overall before following a path too far.

Thanks. There are some things that stick in my head from reading all of those Commodore 64 magazines back in the 1980s such as goto is evil, which isn't true when it comes to bB. I remember getting the idea that If/then was evil too, but the main reason for using the math versions of if/then statements back then was to save space. You could squeeze in the equivalent of a bunch of if/then statements into one, fairly short line and I think it ran faster than if/then statements too. But that BASIC wasn't compiled. I need to remember that bB converts my code, so if/then statements are no longer evil.

 

I naturally think in if/then statements in all areas of my life, so using if/then instead of math tricks is more than fine with me. I love if/then statements, so it's good to finally have 'permission' to use them.

Link to comment
Share on other sites

If/then statements make up the very basis of a program (unless it's simply a glorified book that always has 1 outcome), regardless of language. They are only "evil" if the program is written sloppy and contains overuse of redundancy for no good reason. The same can be said of a goto statement. If the program flows relatively linear, goto statements support the decision-making process. Redundancy is the real enemy.

 

 

Anyway, another solution is just to use the nearest equalivant supported by the & (like &15 for the case of a maximum of 12). If the result is over 12, subtract 12 and continue.

Edited by Nukey Shay
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...