Posts ID:803473 Favorites Creations Medals
ID:803473

(See the best response by DarkCampainger.)
Code:
 ```var const MODE1 = 1 MODE2 = 2 MODE3 = 4var modes = MODE1 | MODE2 | MODE3 // variesvar tmp/mode = 1 // variableproc/next_mode() ... ```

Problem description:
I'm trying to use bit flags and cycle through them in the fashion: 1, 2, 4, 1, 2, 4, etc., depending on the available modes (i.e. if modes = MODE1 | MODE3, the cycle is 1, 4, 1, 4). My concern is, what is the best way to determine if it has reached the final mode? What is the best way to loop it back to the smallest mode?

This could easily be done using a list, but I want to try it with a number instead.
This would work with C++, not sure about BYOND.

If your bits are in order: 1, 2, 4, 8, 16, etc... Then you can simply increase mode by 1 and check if it's not over

 ```var const MODE1 = 1 << 0 MODE2 = 1 << 1 MODE3 = 1 << 2 MAXMODE = 1 << 3proc/next_mode(mode) mode++ if(mode == MAXMODE) mode = 1 return mode ```
In response to Zaoshi (#1)
I don't think you understood my question, so I'll explain again.

'mode' is the current mode of the object.
'modes' is the available modes that 'mode' can be.
When next_mode() is called, 'mode' goes to the next available mode.

e.g.
 ```modes = MODE1 | MODE2 | MODE3 == 7mode = MODE1 == 1next_mode(): mode == MODE2 == 2next_mode(): mode == MODE3 == 4next_mode(): mode == MODE1 == 1modes = MODE1 | MODE3 == 5mode = MODE1 == 1next_mode(): mode == MODE3 == 4next_mode(): mode == MODE1 == 1 ```

Ideally, modes can be any number of 2^n ORed together.

Using a list makes things simpler to me:
 ```var L[] = list("a", "b", "c")var item = L[1]proc/next_item() . = L.Find(item) + 1 item = L[. <= L.len ? . : 1] ```

But there could potentially be a lot of lists made, so I don't want to use them.
 #3 Jun 7 2012, 10:44 pm In response to Zaoshi (#1) You want to shift the mode (mode << 1), not add to it (or you'll end up with a value like 3, which is a combination of MODE1 and MODE2)
Best response
If you need to be able to skip over flags, this seems to work pretty well:

 ```var/const flagA = 1<<0 flagB = 1<<1 flagC = 1<<2 flagD = 1<<3 flagE = 1<<4 flagF = 1<<5proc/cycleBitFlag(v, flags) // Supports up to 16 bits ASSERT(v < 65536) // Check that v is actually in flags if(!(v & flags)) // Start it at the first value if not return ( flags & ~(flags-1) ) // Get only the lowest bit (incase multiple flags are in v) v = ( v & ~(v-1) ) // Create a mask of the current bit and all bits below it v = v | (v - 1) // Apply mask to flags "list" to leave only more significant bits than previous value v = (flags & ~v) if(v) // Get only the lowest remaining bit return ( v & ~(v-1) ) else // Wrap around return ( flags & ~(flags-1) )mob var/flag = flagA verb/Test() flag = cycleBitFlag(flag, flagA | flagC | flagF) src<

Keep in mind that BYOND only supports emulating up to 16 bits.

<edit>
Thought of much better way to create the mask. Doh. Fixed code.