Bitwise operators?
|
Jack Lambert
Registered User
Join date: 4 Jun 2004
Posts: 265
|
03-10-2005 06:05
Hi guys... Let's jump right into my question  integer CIRCLE = 1 integer SQUARE = 2; integer TRIANGLE = 4; integer RED = 8; integer GREEN = 16; integer BLUE = 32;
default { state_entry() { integer iShape = 33; // BLUE CIRCLE;
if (iShape & CIRCLE) llSay(0, "This is a circle..."); if (iShape & BLUE) llSay(0, "It is blue."); } } OK I realise that is oversimplified but my question is this: How can I make a RANDOM binary number (which will become decimal) that is only ONE of the three shapes and ONE of the three colors? I know there is a finite limit (9 different variations) of results that are valid. Basically I want to randomize for either 001, 010, 100 AND also for either 1000, 10000, 100000 (plus add them and covert to decimal, obviously). In my actual code I am using more than 6 bits... lets say for the sake of argument the first four bits are a shape, the next three are a color, the next five are various properties (wood, light, etc) ... But each shape can have only one of each "bit grouping" (that is: 1 shape, 1 color, 1 property) ... how can I make a random binary number (and translate it to decimal) that is valid? Sorry if I'm not making sense, it's still early LOL --Jack Lambert
_____________________
---------------------------- Taunt you with a tree filled lot? hahahahahahaha. Griefer trees! Good lord you're a drama queen. Poor poor put upon you.
-Chip Midnight
|
McWheelie Baldwin
Registered User
Join date: 9 Apr 2004
Posts: 154
|
03-10-2005 07:10
Off the top of my head, the easiest way I can think of is to do something like this:
//First bit field for a given grouping of options integer beg = 1; //Last bit field for a given grouping of options integer end = 4; //Variable to hold final value in integer results = 0;
results += llPow( 2, llRound( llFrand( end- beg ) + beg ) ); beg = 5; end = 12; results += llPow( 2, llRound( llFrand( end- beg ) + beg ) ); etc...
you could also split out the routine into a function:
integer getOption(integer beg, inetger end) { return llPow( 2, llRound( llFrand( end- beg ) + beg ) ); }
Then just call that from your main code.
Of course, it's early, and I have no clue if this would actually work. Would require some testing, and you still have to specify the offsets for each given grouping of bit options. Just an idea.
McW
|
Eggy Lippmann
Wiktator
Join date: 1 May 2003
Posts: 7,939
|
03-10-2005 07:53
Here's a thought. Your valid numbers are 001, 010, and 100. You have three of them, so call them 0, 1, 2... or rather... 2^0, 2^1, 2^2  So what you now need is a random integer between 0 and 2. Generate two of them separately, then combine them with a bitshift. e.g you draw 001 and 010, so you need to do 001000 + 010. Something like this? integer RandomBitField(integer n) { integer a; integer b; a = llFloor(llFRand(n)); b = llFloor(llFRand(n)); a = a << n; a += b; return a; }
|
gene Poole
"Foolish humans!"
Join date: 16 Jun 2004
Posts: 324
|
03-10-2005 08:13
I said it before, and I'll say it again -- bit shifts: << and >>Alright, fine, I didn't say it before, but that's the ticket. First, come up with a bitmap. Let's say you have 3 types of shapes, and 13 colours. Now, 3 can be enumerated from 0..2, so we need enough bits to represent decimal (base 10) values from 0..2 -- that's 2 bits. For the colours, 0..12 takes minimum 4 bits, right? Okay, so here's our bitmap, going from MSB to LSB: [...] [c3] [c2] [c1] [c0] [s1] [s0] Where c3 is bit3 of colour, and s0 is bit0 of shape. So, let's say a square has a value of '01', and red has a code of '0010'. Then, the combined code is, in binary, is: [...] [0010] [01] or 001001 or 1001 Right, now how to generate this randomly? Well, to generate the colour code, we need to produce a random number between 0 and (1 - max colour index), and then we need to bitshift that left x number of bits. What's x? Well, since we designed our bitmap to use the two least significant bits for the shape code, we must shove our colour code left by two bits. We can generate our shape code, and then OR-mask our two codes together to get the final code. So: integer MAX_SHAPES = 3; integer MAX_COLOURS = 13; integer shapeBits = llRound(llFrand(0, 1.0) * (MAX_SHAPES - 1)); integer colourBits = llRound(llFrand(0, 1.0) * (MAX_COLOURS - 1)); integer combinedCode = (colourBits << 2) | shapeBits; Comments: I used possible superfluous parentheses to ensure that the meaning is clear. Also, pedants will note that the distribution for the pseudo-random numbers is not quite uniform, as llFrand returns a number x where 0 <= x < 1.0 -- to that, I say "whocaaaaaares?". Now, if you want to be more "safe" or "cool", you can determine the number of bits to shift-left programmatically, so that if you change MAX_SHAPES or MAX_COLOURS, etc, everything else reflects the changes properly, rather than relying on your brain/memory to fix the shift(s) or whatever. You can probably figure out the complementary process (that is, how to decode the combined code) on your own... (if not, please ask)
|
gene Poole
"Foolish humans!"
Join date: 16 Jun 2004
Posts: 324
|
03-10-2005 08:16
From: Eggy Lippmann Here's a thought. ... a = a << n; ... } A pox on you, Eggy, for stealing my thunder! 
|
Jack Lambert
Registered User
Join date: 4 Jun 2004
Posts: 265
|
03-10-2005 09:40
Yay, that's perfect guys! Thanks ever so much, I can finally go back to my dark laboratory *grins* Sorry about the pox Eggy  --Jack Lambert
_____________________
---------------------------- Taunt you with a tree filled lot? hahahahahahaha. Griefer trees! Good lord you're a drama queen. Poor poor put upon you.
-Chip Midnight
|
Lex Neva
wears dorky glasses
Join date: 27 Nov 2004
Posts: 1,361
|
03-10-2005 10:06
Uh, I still haven't seen a good, clean, correct solution to this posted so far. McWheelie's on the right track, but using Pow and + is unnecessary. Eggy's doesn't compile  and uses +. Gene packed all the values into the least number of bits possible, rather than using the bitfield the original poster asked for. Arguably, gene's more correct, since something can't be a square and a circle at the same time... but if you're going to go gene's route, you may as well store the shape and the color in a separate integer. Anyway, to generate a random shape/color as per the original specs, try this: integer bitfield; integer shape; integer color;
shape = llFloor(llFrand(3.0)); // shape is a random number from 0 to 2 shape = 1 << shape; // shape is now a bitfield, 001, 010, or 100
color = llFloor(llFrand(3.0)); // same deal color = 1 << color;
// first, shift shape over 3 bits, so it's now 001000, 010000, or 100000 // next, bitwise-or it with color, which, in this case, just combines the two // binary numbers together bitfield = (shape << 3) | color;
Adding does do the same thing in this case, but bitwise or is much more efficient.
|
Jack Lambert
Registered User
Join date: 4 Jun 2004
Posts: 265
|
03-10-2005 10:26
From: Lex Neva --SNIP--- bitfield = (shape << 3) | color;
Adding does do the same thing in this case, but bitwise or is much more efficient. I'm not sure I follow the | at the end there? That wouldn't work if the parameter count were more than 2, would it? (like shape, color, property)
_____________________
---------------------------- Taunt you with a tree filled lot? hahahahahahaha. Griefer trees! Good lord you're a drama queen. Poor poor put upon you.
-Chip Midnight
|
Tiger Crossing
The Prim Maker
Join date: 18 Aug 2003
Posts: 1,560
|
03-10-2005 10:28
integer random_shape_and_color = (1 << ( llFloor( llFrand( num_colors ) + num_shapes )) | ( 1 << llFloor( llFrand( num_shapes ) )); Untested, but now that I'm looking at the other answers, it should work fine.
_____________________
~ Tiger Crossing ~ (Nonsanity)
|
Lex Neva
wears dorky glasses
Join date: 27 Nov 2004
Posts: 1,361
|
03-11-2005 10:08
From: Jack Lambert I'm not sure I follow the | at the end there? That wouldn't work if the parameter count were more than 2, would it? (like shape, color, property) Well, you'd need to shift the shape bits over enough to get past the number of bits used for the color. Actually, I should have done this: bitfield = (color << 3) | shape;
because you wanted the shape in the lower bits. Anyway, if you had property in there too, you'd need to shift property over 6 spaces, to get past the bits used for shape and color. If you're not picking this up intuitively, I have to ask why you're even bothering to use bitfields. This doesn't seem like a good time to use them -- just use 3 integer variables and assign constants. All this bitshifting will probably end up obfuscating your code, and you may well find that, while you can understand it now, you can't understand it in a month or two when you want to change it. About the only good reason I can see for wanting to keep all the information in one variable is so that you can pass it around between scripts in the integer of a linkmessage. You can instead pass around a list of integers using llList2CSV and llCSV2List, or, if you really get desperate and only have 3 parameters, you can store your 3 integers in the x/y/z of a vector. As long as you're using low integers, you won't lose anything to floating-point rounding... but this is kind of a hack. Anyway, I just think it might be a good idea to re-evaluate why you're using bitfields in the first place.
|