I want to do some bitwise operations in the ZILF game I’m working on, but I’m not 100% sure how I’d do this. Am I right in thinking that I can do bitwise AND with <BAND a b>
and bitwise OR with <BOR a b>
? What does BCOM
(mentioned, but not defined, in Learning ZIL) do? Is it the bitwise NOT? Last, but not least, am I right in thinking that the engine does not have a bitwise XOR operation and that I’ll want to do <BAND <BOR a b> <NOT <BAND a b>>>
(and what should I put where NOT
is?)
I went ahead and wrote some code (line numbers added for clarity):
01 ;"implement XOR-mapped rotation in ZIL."
02
03 ;"Forward XOR map values: 2083, 4166, 8332, 16664, 33329, 3136, 6273, 12546, 25092, 50185, 32817, 2113, 4226, 8452, 16904, 33809."
04 <CONSTANT FORWARDXORTABLE
05 <TABLE 2083 4166 8332 16664 -32207 3136 6273 12546 25092 -15351 -32719 2113 4226 8452 16904 -31727>
06 >
07
08 ;"Reverse XOR map values: 40033, 14530, 29060, 58120, 50704, 4161, 8322, 16644, 33288, 1040, 37953, 46307, 27078, 54156, 42776, 20016."
09 <CONSTANT REVERSEXORTABLE
10 <TABLE -25503 14530 29060 -7416 -14832 4161 8322 16644 -32248 1040 -27583 -19229 27078 -11380 -22760 20016>
11 >
12
13 ;"Powers of two, signed."
14 <CONSTANT POWERSOFTWO
15 <TABLE 1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 -32768>
16 >
17
18 ;"Compute the forward XOR-mapped rotation."
19 <ROUTINE FORWARDXOR (INPUT "AUX" (XORBIT 0) (OUTPUT 0) (CURRENTXORENTRY 0))
20 <REPEAT ()
21 <COND (<BAND .INPUT <GET POWERSOFTWO .XORBIT>>)
22 <SET CURRENTXORENTRY <GET FORWARDXORTABLE .XORBIT>>
23 <SET OUTPUT <BAND <BOR .OUTPUT .CURRENTXORENTRY> <BCOM <BAND .OUTPUT .CURRENTXORENTRY>>>>
24 >
25 <COND (<IGRTR? XORBIT 15>) <RETURN>>
26 >
27 <RETURN .OUTPUT>
28 >
Explaining what it’s supposed to do is a bit complicated, but I can if that’d be useful. I’m making a more elementary error, though, as reported by ZILF:
[warning ZIL0507] ..\..\Broad But Shallow Sea.zil:23: COND: condition is always true
[warning ZIL0505] ..\..\Broad But Shallow Sea.zil:21: COND: clauses after else part will never be evaluated
[warning ZIL0507] ..\..\Broad But Shallow Sea.zil:27: COND: condition is always true
I’m sure it’s something simple and silly, but I’m still learning. What’m I doing wrong?
The Z-Machine unfortunately does not have an XOR opcode. I don’t know ZIL so can’t help with the rest.
BCOM
stands for Bitwise COMplement: in other words, flipping every bit in a word (like C’s ~
operator).
So yes, <BAND <BOR ,X ,Y> <BCOM <BAND ,X ,Y>>>
gets you a bitwise XOR in four instructions, which I think is the best you can do on the Z-machine (and is honestly fast enough that, if it’s becoming a problem, you have bigger fish to fry).
Bonus: I think the equivalent in Inform assembly syntax would be:
@and x y -> sp;
@not sp -> sp;
@or x y -> sp;
@and sp sp -> sp;
But I haven’t done Inform assembly in a while, and when I have it’s usually been for Glulx, which just has a straight-up @xor
opcode.
@bitxor actually ;). That assembly looks right. You can do it as a statement in Inform 6 too.
Okay, so I had the right idea. I’m still having those warnings when I compile, though. Where’d I go wrong?
Oh, you just have some mistakes in your COND
syntax. COND
works like this:
<COND
(predicate1 expr expr expr)
(predicate2 expr expr)
(predicate3 expr expr expr expr)
>
In other words, the expressions have to be inside the LIST
with the condition. In your case, you want something like:
<COND
( <BAND something> <SET something> <SET something> )
>
<COND
( <IGRTR? something> <RETURN> )
>
Thank you kindly!