|A C H A N C E|
|E N C O U N T E R|
As luck would have it, Toni Baker has come up with an interesting way to access true random numbers - with a little help from machine code, of course.
As many of you will know, random
numbers on the Spectrum are not truly
random - they may appear to be random, but they are in fact totally
pre- determined. For instance, RANDOMIZE 42 followed by PRINT
RND,RND will always give the same
numbers: 0.049194336 and 0.69065857;
I haven't cheated by using the RANDOMIZE statement, I've just used it to
make the point easier to demonstrate -
RND does not rely on chance. |
RANDOM THOUGHTSNow when you play any sort of game which involves the throwing of dice or the tossing of coins, then one would usually agree that the outcome is truly random. (At this point, the philosophers amongst us may like to have a quick debate on the various merits of free will versus determinism.) Isaac Newton would tell us that if we knew all the variables involved (velocity of dice, density of air, etc) then we could work out in advance which number would get thrown; on the other hand, Schrodinger's Cat tells us differently. Maybe the world is flat after all.
So now you should be able to see the subtle difference between the formula INT (6*RND)+1 and throwing a dice. However many suitable tests for randomness you may care to think up, one overriding fact remains - that, whereas dice-rolling involves the mysterious hand of fate, the RND formula is completely predetermined. The outcome of a dice game is fixed before you even press RUN.
You can add a little bit of chance into the game by putting a RANDOMIZE statement into your program somewhere (without a number after RANDOMIZE). This will confuse the issue a bit, but it still won't stop the remainder of the game being just as predetermined as ever. What you could do instead is to precede every single use of RND by either an INPUT statement or a PAUSE 0 statement, followed by RANDOMIZE. For instance:
This will prevent the game from being predetermined by relying on the fact that a human player will not necessarily
wait the same number of TV frames before pressing a key; it'll load the random
number seed with a different value each
time and hence give you a different random number each time. |
A TRUE DEFINITIONBut I'd like introduce you to another approach. I'm going to define a user- defined function called FN R(X) (the number inside the bracket is important). Here's what happens when it's reached in the middle of a Basic statement. Firstly, control will PAUSE until a key is pressed, and then the computer will
select a random integer between one
and the number inside the brackets.
This new random number function is
not predetermined, and as in the above
example, its differing possible outcomes are strictly the result of human
Unlike the previous example, however, the determining factor is not how long you take to press a key - it's which key you press! In other words - suppose you used FN R(6) to represent throwing a dice. At this point the action would PAUSE. The human player would be aware that the outcome of this dice throw is determined only by which of the keys they decide to press, but does not know, and can never know,
which key gives which result. As in real
life, the human being determines their own fate, and synchronicity alone
choose the winners and losers. |
The algorithm I've used to define FN R is an almost direct rip-off of the RND feature in the ROM, except that I've added a bit to allow for human intervention. It's mostly a machine code routine, but the machine code only works out a random number between zero and 65535, and so a bit of multiplying, dividing and INTing is required to get it into range. See if you can write a new Basic DEF FN statement to define, say, FN S() as a random decimal between zero and one - you can use exactly the same USR call (that is, my machine code) as I've used for FN R(X) but you'll need to change the rest of the statement.
CHINESE CHANCEFor those of you with an inquiring mind (all of you, I hope) look carefully at how I've used the floating point calculator by bringing in the RST 28 instruction. You don't need to understand all the the calculator instruction codes (I'll admit that 348041000080 is a bit confusing) but if you can get the drift of how in principle the calculator instructions manipulate the calculator stack, then you're well on the way to the light at the end of the tunnel.
I've used a bit of computer jargon here,
which I'd better explain. We all know
that 15 divided by seven is two remainder
one. In fractions, it's 21/7, and in
decimals it's 2.142857 ... but let's just
stick to integers - it's easier. In
general, A divided by B is Q remainder
R. In computerese we can write 'A DIV
B' to mean Q, and 'A MOD B' to mean
R. Thus, in the above example 15 DIV 7
equals two, and 15 MOD 7 equals one.
Mathematically we can say that A DIV
B equals INT (A/B) - see if you can
work out what the mathematical formula for A MOD B is. Anyway, that
explains all the unknowns - let's move
on now to a bit of program. |
This is a Basic program for throwing
Chinese coins. The question marks in
the last line refer to the address of the
machine code routine labelled CHANCE, which is listed separately. See you
up there. |