2.1 Numbers / 2.2 Signed operations / 2.3 Arithmetic errors / 2.4 Random number generator

In the Z-machine, numbers are usually stored in 2 bytes
(in the form most-significant-byte first, then least-significant)
and hold any value in the range **$0000** to **$ffff** (0 to 65535
decimal).

These values are sometimes regarded as signed, in the range -32768 to 32767. In effect -n is stored as 65536-n and so the top bit is the sign bit.

The operations of numerical comparison, multiplication,
addition, subtraction, division, remainder-after-division and
printing of numbers are signed; bitwise operations are unsigned.
(In particular, since comparison is signed, it is unsafe to compare
two addresses using simply **jl** and **jg**.)

Arithmetic errors:

It is illegal to divide by 0 (or to ask for remainder after division by 0) and an interpreter should halt with an error message if this occurs.

Formally it has never been specified what the result of an
out-of-range calculation should be. The author suggests that the
result should be reduced modulo **$10000**.

The Z-machine needs a random number generator which at any time has one of two states, "random" and "predictable". When the game starts or restarts the state becomes "random". Ideally the generator should not produce identical sequences after each restart.

When "random", it must be capable of generating a uniformly random integer in the range 1 <= x <= n, for any value 1 <= n <= 32767. Any method can be used for this (for instance, using the host computer's clock time in milliseconds). The uniformity of randomness should be optimised for low values of n (say, up to 100 or so) and it is especially important to avoid regular patterns appearing in remainders after division (most crudely, being alternately odd and even).

The generator is switched into "predictable" state with a seed value. On any two occasions when the same seed is sown, identical sequences of values must result (for an indefinite period) until the generator is switched back into "random" mode. The generator should cope well with very low seed values, such as 10, and should not depend on the seed containing many non-zero bits.

The interpreter is permitted to switch between these states on request of the player. (This is useful for testing purposes.)

It is dangerous to rely on the older ANSI C random number routines (rand() and srand()), as some
implementations of these are very poor. This has made some games (in
particular, 'Balances') unwinnable on some Unix ports of **Zip**.

The author suggests the following algorithm:

**1.** In "random" mode, the generator uses the host computer's
clock to obtain a random sequence of bits.

**2.** In "predictable" mode, the generator should store the
seed value *S*. If *S* < 1000 it should then internally generate

1, 2, 3, ..., *S*, 1, 2, 3, ..., *S*, 1, ...

so that **random n** produces the next entry in this sequence modulo n.
If *S* >= 1000 then *S* is used as a seed in a standard seeded
random-number generator.

(The rising sequence is useful for testing, since it will produce all possible values in sequence. On the other hand, a seeded but fairly random generator is useful for testing entire scripts.)

Note that version 0.2 of this standard mistakenly asserted that division
and remainder are unsigned, a myth deriving from a bug in **Zip**. Infocom's
interpreters do sign division (this is relied on when calculating
pizza cooking times for the microwave oven in 'The Lurking Horror'). Here
are some correct Z-machine calculations:

-11 / 2 = -5 -11 / -2 = 5 11 / -2 = -5 -13 % 5 = -3 13 % -5 = 3 -13 % -5 = -3

Section 1 / 2 / 3 / 4 / 5 / 6 / 7 / 8 / 9 / 10 / 11 / 12 / 13 / 14 / 15 / 16

Appendix A / B / C / D / E / F