Discussion:
TextFall - a 'Matrix digital rain' style game
(too old to reply)
ladislau szilagyi
2023-08-03 12:12:59 UTC
Permalink
You may find-it here: https://github.com/Laci1953/RC2014-CPM/tree/main/textfall

It needs a VT100 compatible terminal

Ladislau
Mike Douglas
2023-08-04 12:57:08 UTC
Permalink
Post by ladislau szilagyi
You may find-it here: https://github.com/Laci1953/RC2014-CPM/tree/main/textfall
It needs a VT100 compatible terminal
Ladislau
Does this require a Z80?
ladislau szilagyi
2023-08-04 13:21:45 UTC
Permalink
Post by Mike Douglas
Post by ladislau szilagyi
You may find-it here: https://github.com/Laci1953/RC2014-CPM/tree/main/textfall
It needs a VT100 compatible terminal
Ladislau
Does this require a Z80?
yes, it works only on Z80
bill
2023-08-04 13:55:06 UTC
Permalink
Post by ladislau szilagyi
Post by Mike Douglas
Post by ladislau szilagyi
You may find-it here: https://github.com/Laci1953/RC2014-CPM/tree/main/textfall
It needs a VT100 compatible terminal
Ladislau
Does this require a Z80?
yes, it works only on Z80
It's written in C. Would it really be that hard to convert the two
stub assembler bits to 8080 from Z80? Unless, of course, there is
no existing 8080 C compilers left. :-)

bill
ladislau szilagyi
2023-08-04 14:04:37 UTC
Permalink
Post by ladislau szilagyi
Post by Mike Douglas
Post by ladislau szilagyi
You may find-it here: https://github.com/Laci1953/RC2014-CPM/tree/main/textfall
It needs a VT100 compatible terminal
Ladislau
Does this require a Z80?
yes, it works only on Z80
It's written in C. Would it really be that hard to convert the two
stub assembler bits to 8080 from Z80? Unless, of course, there is
no existing 8080 C compilers left. :-)
bill
Why not, the only obstacle would be to find a good 'set-seed-value' (_xrndseed) routine for the random number generator (rand.as) ...
The Z80 routine uses the R register.
dxforth
2023-08-05 05:02:53 UTC
Permalink
Post by ladislau szilagyi
Post by Mike Douglas
Post by ladislau szilagyi
You may find-it here: https://github.com/Laci1953/RC2014-CPM/tree/main/textfall
It needs a VT100 compatible terminal
Ladislau
Does this require a Z80?
yes, it works only on Z80
It's written in C.  Would it really be that hard to convert the two
stub assembler bits to 8080 from Z80?  Unless, of course, there is
no existing 8080 C compilers left.  :-)
Don't C compilers already come with reasonable RNGs? IIRC Turbo-C
used a decent LCG (not least because it had multiply). I'd be
surprised if the Z80 RNG beat it for quality. Speed without quality
is meaningless.
ladislau szilagyi
2023-08-05 07:01:50 UTC
Permalink
Don't C compilers already come with reasonable RNGs? IIRC Turbo-C
used a decent LCG (not least because it had multiply). I'd be
surprised if the Z80 RNG beat it for quality. Speed without quality
is meaningless.
The George Marsaglia's XOR Shift algorithm is as good as other "classic" RNG's, but much faster, and John Metcalf's assembler implementation is accurate. The "R register" based 'set-seed-value' routine is just an useful add-on from me.

Please see https://wiki.freepascal.org/Marsaglia%27s_pseudo_random_number_generators for an extended explanation.

Ladislau
Russell Marks
2023-08-05 21:43:21 UTC
Permalink
Post by dxforth
Don't C compilers already come with reasonable RNGs?
Well... an old draft of the C11 standard I saw linked on Wikipedia [1]
had this memorable footnote regarding rand():

"There are no guarantees as to the quality of the random sequence
produced and some implementations are known to produce sequences with
distressingly non-random low-order bits."

I remember noticing that myself in the 90s, so I expect it was fairly
common knowledge even then.

Anyway, I believe Hitech C (presumably most relevant here) uses what I
think is the old ANSI C example implementation - though the routine
seems to date back at least as far as V7 in 1979 - multiply by
1103515245, add 12345, and return bits 30-16. From a quick look I
think lcg16of32_extended in PractRand does something very similar,
with results like this when tested:

***@wedge:1938:/home/rus>RNG_test lcg16of32_extended
RNG_test using PractRand version 0.95
RNG = lcg16of32_extended, seed = 0xf050291b
test set = core, folding = standard (16 bit)

rng=lcg16of32_extended, seed=0xf050291b
length= 64 megabytes (2^26 bytes), time= 3.2 seconds
Test Name Raw Processed Evaluation
TMFn(2+0):wl R=+258.3 p~= 2e-148 FAIL !!!!!
TMFn(2+1):wl R=+127.4 p~= 1e-69 FAIL !!!!
[Low4/16]DC6-9x1Bytes-1 R=+109.1 p = 7.3e-63 FAIL !!!!
[Low4/16]Gap-16:A R=+220.2 p = 4.0e-173 FAIL !!!!!!
[Low4/16]Gap-16:B R=+348.2 p = 1.6e-314 FAIL !!!!!!
[Low4/16]FPF-14+6/16:all R= -7.0 p =1-1.9e-6 suspicious
[Low1/16]BCFN(2+0,13-6,T) R= +83.5 p = 5.1e-29 FAIL !!!
[Low1/16]BCFN(2+1,13-6,T) R=+132.0 p = 1.2e-45 FAIL !!!
[Low1/16]BCFN(2+2,13-6,T) R=+151.7 p = 2.2e-52 FAIL !!!!
[Low1/16]BCFN(2+3,13-6,T) R= +72.7 p = 2.5e-25 FAIL !!
[Low1/16]BCFN(2+4,13-7,T) R= +78.5 p = 3.0e-24 FAIL !!
[Low1/16]BCFN(2+5,13-8,T) R= +73.8 p = 1.1e-19 FAIL !
[Low1/16]BCFN(2+6,13-8,T) R= +42.0 p = 1.3e-11 VERY SUSPICIOUS
[Low1/16]DC6-9x1Bytes-1 R=+898.4 p = 3.1e-506 FAIL !!!!!!!
[Low1/16]Gap-16:A R= +1948 p = 2e-1567 FAIL !!!!!!!!
[Low1/16]Gap-16:B R= +2300 p = 3e-1735 FAIL !!!!!!!!
[Low1/16]FPF-14+6/16:(0,14-2) R= +78.6 p = 1.6e-68 FAIL !!!!
[Low1/16]FPF-14+6/16:(1,14-3) R= +54.8 p = 8.6e-48 FAIL !!!
[Low1/16]FPF-14+6/16:(2,14-4) R= +33.2 p = 4.4e-27 FAIL !!
[Low1/16]FPF-14+6/16:(3,14-5) R= +22.9 p = 8.3e-19 FAIL !
[Low1/16]FPF-14+6/16:(4,14-5) R= +41.5 p = 3.0e-34 FAIL !!!
[Low1/16]FPF-14+6/16:(5,14-6) R= +23.9 p = 2.3e-18 FAIL !
[Low1/16]FPF-14+6/16:(6,14-7) R= +15.3 p = 5.0e-12 VERY SUSPICIOUS
[Low1/16]FPF-14+6/16:(7,14-8) R= +17.9 p = 6.2e-13 VERY SUSPICIOUS
[Low1/16]FPF-14+6/16:(8,14-8) R= +12.3 p = 6.5e-9 very suspicious
[Low1/16]FPF-14+6/16:(9,14-9) R= +9.0 p = 5.6e-6 unusual
[Low1/16]FPF-14+6/16:(10,14-10) R= +18.1 p = 3.2e-10 very suspicious
[Low1/16]FPF-14+6/16:all R=+117.2 p = 3.6e-105 FAIL !!!!!
...and 118 test result(s) without anomalies

Perhaps it's better than a plain xorshift in some ways - I doubt I'm
the best person to make that call. But it does seem to have flaws of
its own. :-)

-Rus.

[1] From here, an interesting page in itself not least for the list of
"Parameters in common use", and I can only applaud any list which
sees fit to include the Sinclair ZX81 in that context:

https://en.wikipedia.org/wiki/Linear_congruential_generator
ladislau szilagyi
2023-08-06 03:30:07 UTC
Permalink
Post by Russell Marks
Perhaps it's better than a plain xorshift in some ways - I doubt I'm
the best person to make that call. But it does seem to have flaws of
its own. :-)
-Rus.
You can check the results of a Dieharder test here: https://wiki.freepascal.org/Marsaglia%27s_pseudo_random_number_generators

XOR passes with zero failures...
ladislau szilagyi
2023-08-07 03:58:18 UTC
Permalink
Hi Russell,

I'm a matematician, I graduated from the university, at the faculty of mathematics.

I understand wery well the complexity of (pseudo-)random number generators and the issues of checking-it.

All I wanted to underline is that, for CP/M games running on Z80, I consider the 2 byte xorshift798 the best I know, in its class of 2 byte pseudo random number generators.

Why?

Because it returns a positive pseudo random 2 byte integer (good enough for the vast majority of Z80 games I know...), it's very fast, it starts with returning a non-constant (variable) initial value (very important asset for a game...), and is 64K periodic, covering nicely all the possible values (see the results of some tests in the "Random numbers generator on Z80" thread, comparing-it with other 2 byte random number generators...).

I kept a rather "practical" approach, but, of course, we can discuss also the subtleties of random number generation algorithms and how to test them, but I think this would be a boring academic debate for the vast majority of the participants in this Google group.

regards,
Ladislau
Russell Marks
2023-08-07 12:32:14 UTC
Permalink
Post by ladislau szilagyi
I'm a matematician, I graduated from the university, at the faculty of mathematics.
Nice. I do realise that random people online can have qualifications
they might not always mention.
Post by ladislau szilagyi
I understand wery well the complexity of (pseudo-)random number
generators and the issues of checking-it.
I see.
Post by ladislau szilagyi
All I wanted to underline is that, for CP/M games running on Z80, I
consider the 2 byte xorshift798 the best I know, in its class of 2
byte pseudo random number generators.
I mean, this seems like a step down from "perfect", but sure.
Post by ladislau szilagyi
Why?
Because it returns a positive pseudo random 2 byte integer (good
enough for the vast majority of Z80 games I know...), it's very fast,
it starts with returning a non-constant (variable) initial value (very
important asset for a game...), and is 64K periodic, covering nicely
all the possible values (see the results of some tests in the "Random
numbers generator on Z80" thread, comparing-it with other 2 byte
random number generators...).
Have you ever seen it return a zero?
Post by ladislau szilagyi
I kept a rather "practical" approach, but, of course, we can discuss
also the subtleties of random number generation algorithms and how to
test them, but I think this would be a boring academic debate for the
vast majority of the participants in this Google group.
I understand that in this context any half-decent RNG is likely fine.

-Rus.
ladislau szilagyi
2023-08-07 12:53:14 UTC
Permalink
Post by Russell Marks
Have you ever seen it return a zero?
Yes, it does return zero.

Check again the code fragment below; when HL = 8000H, it returns zero:

ld (_xrnd+1),hl
res 7,h ;make-it positive...
ret
Russell Marks
2023-08-07 14:28:44 UTC
Permalink
Post by ladislau szilagyi
Post by Russell Marks
Have you ever seen it return a zero?
Yes, it does return zero.
Not in the pre-existing xorshift798 algorithm - please check what was
being referring to.

-Rus.
ladislau szilagyi
2023-08-07 14:37:48 UTC
Permalink
Post by Russell Marks
Post by ladislau szilagyi
Post by Russell Marks
Have you ever seen it return a zero?
Yes, it does return zero.
Not in the pre-existing xorshift798 algorithm - please check what was
being referring to.
-Rus.
I'm really sorry, but we are discussing in this thread about the TextFall game.

More exactly, about a component of my TextFall game, the rand.as file, containing my version of xorshift, listed below:

psect text

GLOBAL _xrnd, _xrndseed

_xrnd:
ld hl,1 ; seed must not be 0
ld a,h
rra
ld a,l
rra
xor h
ld h,a
ld a,l
rra
ld a,h
rra
xor l
ld l,a
xor h
ld h,a
ld (_xrnd+1),hl
res 7,h ;make-it positive...
ret

_xrndseed:
ld a,r
ld l,a
ld a,r
ld h,a
or l ; HL must be not NULL
jr nz,1f
inc hl
1:
ld (_xrnd+1),hl
ret
Russell Marks
2023-08-07 19:18:34 UTC
Permalink
Post by ladislau szilagyi
Post by Russell Marks
Post by ladislau szilagyi
Post by Russell Marks
Have you ever seen it return a zero?
Yes, it does return zero.
Not in the pre-existing xorshift798 algorithm - please check what was
being [referred] to.
[...]
Post by ladislau szilagyi
I'm really sorry, but we are discussing in this thread about the TextFall game.
Here is the relevant context you previously removed:

"All I wanted to underline is that, for CP/M games running on Z80, I
consider the 2 byte xorshift798 the best I know, in its class of 2
byte pseudo random number generators."

That is clearly referring to the original algorithm, and so was I.

(It cannot plausibly be referring to your routine, as that cuts the
range of random numbers roughly in half, which is incompatible with
your "best I know" claim since you know of both.)

-Rus.
ladislau szilagyi
2023-08-08 04:08:21 UTC
Permalink
Post by Russell Marks
Post by ladislau szilagyi
Post by Russell Marks
Post by ladislau szilagyi
Post by Russell Marks
Have you ever seen it return a zero?
Yes, it does return zero.
Not in the pre-existing xorshift798 algorithm - please check what was
being [referred] to.
[...]
Post by ladislau szilagyi
I'm really sorry, but we are discussing in this thread about the TextFall game.
"All I wanted to underline is that, for CP/M games running on Z80, I
consider the 2 byte xorshift798 the best I know, in its class of 2
byte pseudo random number generators."
That is clearly referring to the original algorithm, and so was I.
(It cannot plausibly be referring to your routine, as that cuts the
range of random numbers roughly in half, which is incompatible with
your "best I know" claim since you know of both.)
-Rus.
Yes Russell, as always, you are right.
I wonder, how on earth are my programs working, I'm constantly wrong on something.
I must investigate this.
Russell Marks
2023-08-08 07:03:56 UTC
Permalink
Post by ladislau szilagyi
I wonder, how on earth are my programs working, I'm constantly wrong on something.
I must investigate this.
Point taken. :-) I apologise for what has perhaps been excessive and
overly pedantic posting.

-Rus.
Mark Lawler
2023-08-08 22:58:18 UTC
Permalink
On the Altair 8800 and IMSAI 8080 emulators I have built (highnibble and addwaterandstir) I wanted to generate random light patterns on the display for a better blinkenlights effect. Similar when I wanted to write my own textfall "matrix-like" screen display on my PDP-11 emulator (oscar's). On the Intel 8080 CP/M-based machines I use Manx Aztec C since that is what I used back in my Kapro II and 4 days. However, I could never seem to access the ran_ function out of the Manx Aztec C M.lib so I punted and stole this straight out of KIernighan & Ritchie until I could find something better:

/*
* int ran()
*
* Taken from the K&R C programming language book, page 46.
* Returns a psuedo-random integer of 0..32767. Written after
* not being able to access the ran_ function out of the Manx
* Aztec C M.Lib.
*
*/

long ran_next = 1;

int ran()
{
ran_next = ran_next * 1103515245 + 12345;
return ((unsigned)(ran_next / 65536) % 32768);
}

sran(seed)
unsigned int seed;
{
ran_next = seed;
}

Perhaps with this thread I have?

Best,
-Mark
ladislau szilagyi
2023-08-09 03:06:00 UTC
Permalink
Hi Mark,

Interesting, the rand() and srand() from the HiTech C v3.09 library LIBC.LIB are identical with these K&R routines...

It's obvious why... we all learned C from the Brian Kernighan & Dennis Ritchie's book :)

regards,
Ladislau
dxforth
2023-08-09 04:12:05 UTC
Permalink
Post by Mark Lawler
/*
* int ran()
*
* Taken from the K&R C programming language book, page 46.
* Returns a psuedo-random integer of 0..32767. Written after
* not being able to access the ran_ function out of the Manx
* Aztec C M.Lib.
*
*/
long ran_next = 1;
int ran()
{
ran_next = ran_next * 1103515245 + 12345;
return ((unsigned)(ran_next / 65536) % 32768);
}
sran(seed)
unsigned int seed;
{
ran_next = seed;
}
Perhaps with this thread I have?
IIRC early versions of Turbo-C took the modulus directly i.e.
the least random bits. Ideally one wants the highest order bits
in any reduction - which means using multiply rather than mod.
ladislau szilagyi
2023-08-09 18:19:25 UTC
Permalink
Hi,

I published also the Z80ALL version of the game, here: https://github.com/Laci1953/Software-for-Z80ALL-retro-computer/tree/main/textfall

Ladislau
ladislau szilagyi
2023-09-16 06:43:56 UTC
Permalink
Hi,

I just published an improved version for RC2014 (the cursor is hidden).

Ladislau

Loading...