Bitwise Operations
Bitwise operations are used to perform an action on the bits (the 1's and 0's) of a number.
In this article a "binary" formatted number (which represents the "bits" of a number) will be written with a 2... and a decimal number with a 10
Contents
Limitations
In Sphere, numbers are stored in something called a "DWORD". The largest number a DWORD can store is constrained by the fact that a DWORD is 32 bits wide. That means the largest number it can store is 2^32-1.
- In Binary that's 11111111111111111111111111111111.
- In Hex it's FFFFFFFF.
- In Decimal that's 4294967295.
To store a 'signed' number in a DWORD (in other words, a number that can be positive or negative), the first bit is used to indicate the sign (a 1 is negative). Which means the largest 'signed' positive number is 2^31-1
- In Binary that's 01111111111111111111111111111111.
- In Hex it's 7FFFFFFF.
- In Decimal that's 2147483647.
In sphere script language, the EVAL function outputs a signed DWORD, and the UVAL outputs an unsigned DWORD.
[FUNCTION Mathtest] LOCAL.Number0=2147483647 LOCAL.Number1=4294967295 LOCAL.Number2=8589934588 SERV.LOG eval0=<EVAL <LOCAL.Number0>> eval1=<EVAL <LOCAL.Number1>> eval2=<EVAL <LOCAL.Number2>> SERV.LOG uval0=<UVAL <LOCAL.Number0>> uval1=<UVAL <LOCAL.Number1>> uval2=<UVAL <LOCAL.Number2>>
The output of this test is:
13:37:(test.scp,10)eval0=2147483647 eval1=-1 eval2=-4 13:37:(test.scp,11)uval0=2147483647 uval1=4294967295 uval2=4294967292
Notes:
- The output is limited to align with the limitation of the DWORD itself.
- Since there are 32 "bits" in a DWORD, there can only be 32 flags in a set.
- Be careful when manipulating flags using EVAL, because the 32nd flag could get lost.
Flags
In the Sphere server, quite a few concepts are implemented using "flags". You can see examples of flags being defined in the Sphere.ini file, or the sphere_defs.scp files. For example:
[DEFNAME attr_flags] attr_identified 01 attr_decay 02 attr_newbie 04 attr_move_always 08 attr_move_never 010 attr_magic 020 attr_owned 040 attr_invis 080 attr_cursed 0100 attr_cursed2 0200 attr_blessed 0400 attr_blessed2 0800 attr_forsale 01000 attr_stolen 02000 attr_can_decay 04000 attr_static 08000 attr_exceptional 010000 attr_enchanted 020000 attr_imbued 040000 attr_questitem 080000 attr_insured 0100000 attr_nodrop 0200000 attr_notrade 0400000 attr_lockeddown 0800000 attr_secure 01000000
Notice a pattern? Let's tip it on it's side and chart the first 8 flags:
Flag Name: | attr_invis | attr_owned | attr_magic | attr_move_never | attr_move_always | attr_newbie | attr_decay | attr_identified |
Binary Number: | 10000000 | 01000000 | 00100000 | 00010000 | 00001000 | 00000100 | 00000010 | 00000001 |
Hex Number: | 080 | 040 | 020 | 010 | 08 | 04 | 02 | 01 |
Decimal Number: | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
The OR Operator (inclusive OR)
A bitwise OR takes two bit patterns of equal length and performs the logical inclusive OR operation on each pair of corresponding bits. When you perform this operation, the result in each position is 0 if both bits are 0, and the result is 1 if either (or both) the bits were 1. For example:
0101 (decimal 5) OR 0011 (decimal 3) = 0111 (decimal 7)
In Sphere, this technique is commonly used to set a flag in a register, where each bit represents an individual Boolean state. Thus, 0010 (decimal 2) can be considered a set of four flags, where the first, third, and fourth flags are clear (0) and the second flag is set (1). The fourth flag may be set by performing a bitwise OR between this value and a bit pattern with only the fourth bit set:
0010 (decimal 2) OR 1000 (decimal 8) = 1010 (decimal 10)