SyntaxBoom

Miscellaneous => Retro Corner => Topic started by: Jackdaw on Jul 21, 2025, 01:19 PM

Title: AI generated pseudo random number generator
Post by: Jackdaw on Jul 21, 2025, 01:19 PM
This popped up on my Youtube feed today. I wonder what the results would be for other CPU's.
Title: Re: AI generated pseudo random number generator
Post by: Jackdaw on Jul 21, 2025, 06:02 PM
Tested out NinjaTech AI (https://www.ninjatech.ai/product/ai-code-generator)
Z80 Random number generator range 0-255
; Z80 Random Number Generator (0-255 range)
; Uses 16-bit Linear Congruential Generator with 8-bit output

        ORG     8000h

; 16-bit seed storage
RND_SEED:   DEFW    1234h       ; Initial seed value

;==============================================================================
; Initialize random number generator
; Input: HL = 16-bit seed value
; Destroys: None
;==============================================================================
RND_INIT:
        LD      (RND_SEED), HL
        RET

;==============================================================================
; Generate random number 0-255
; Output: A = random number (0-255)
; Destroys: HL, DE
;==============================================================================
RANDOM:
        LD      HL, (RND_SEED)  ; Load current seed
       
        ; LCG formula: next = (a * seed + c) mod 65536
        ; Using a = 75 (good multiplier for 16-bit)
        LD      D, H            ; Copy seed to DE
        LD      E, L
       
        ; Multiply by 75 using shifts and adds (75 = 64 + 8 + 2 + 1)
        ADD     HL, HL          ; HL = seed * 2
        LD      BC, HL          ; Save seed * 2
       
        ADD     HL, HL          ; HL = seed * 4
        ADD     HL, HL          ; HL = seed * 8
        ADD     HL, BC          ; HL = seed * 10
       
        ADD     HL, HL          ; HL = seed * 20
        ADD     HL, HL          ; HL = seed * 40
        ADD     HL, DE          ; HL = seed * 41
       
        ADD     HL, HL          ; HL = seed * 82
        SUB     HL, DE          ; HL = seed * 81
        SUB     HL, DE          ; HL = seed * 80
        SUB     HL, DE          ; HL = seed * 79
        SUB     HL, DE          ; HL = seed * 78
        SUB     HL, DE          ; HL = seed * 77
        SUB     HL, DE          ; HL = seed * 76
        SUB     HL, DE          ; HL = seed * 75
       
        ; Add constant c = 74
        LD      DE, 74
        ADD     HL, DE
       
        ; Store new seed
        LD      (RND_SEED), HL
       
        ; Return high byte for better distribution
        LD      A, H
        RET

;==============================================================================
; Alternative simpler version using XOR shift
; Output: A = random number (0-255)
; Destroys: HL
;==============================================================================
RANDOM_XOR:
        LD      HL, (RND_SEED)
       
        ; XOR shift algorithm
        LD      A, L
        XOR     H
        LD      L, A
       
        LD      A, H
        RRA
        RRA
        RRA
        XOR     L
        LD      H, A
       
        LD      A, L
        RLA
        XOR     H
        LD      L, A
       
        ; Store new seed
        LD      (RND_SEED), HL
       
        ; Return low byte
        LD      A, L
        RET

;==============================================================================
; Fast 8-bit LCG (most efficient)
; Output: A = random number (0-255)
; Destroys: None
;==============================================================================
RND_SEED8:  DEFB    1           ; 8-bit seed

RANDOM8:
        LD      A, (RND_SEED8)  ; Load 8-bit seed
       
        ; Multiply by 5 (shift left twice + original)
        LD      B, A            ; Save original
        ADD     A, A            ; A = seed * 2
        ADD     A, A            ; A = seed * 4
        ADD     A, B            ; A = seed * 5
       
        ; Add constant 1
        INC     A
       
        ; Store new seed
        LD      (RND_SEED8), A
       
        RET

;==============================================================================
; Get random number in specific range 0 to N-1
; Input: B = upper limit (N, where result will be 0 to N-1)
; Output: A = random number (0 to N-1)
; Destroys: HL, DE, C
;==============================================================================
RANDOM_RANGE:
        CALL    RANDOM          ; Get random 0-255
       
        ; Simple modulo using repeated subtraction
        LD      C, 0            ; Counter
RANGE_LOOP:
        CP      B               ; Compare with limit
        JR      C, RANGE_DONE   ; If A < B, we're done
        SUB     B               ; A = A - B
        INC     C               ; Increment counter
        JR      RANGE_LOOP
       
RANGE_DONE:
        RET                     ; A now contains result

;==============================================================================
; More efficient range function using multiplication method
; Input: B = upper limit (1-255)
; Output: A = random number (0 to B-1)
; Destroys: HL, DE
;==============================================================================
RANDOM_RANGE_FAST:
        CALL    RANDOM          ; Get random 0-255 in A
       
        ; Multiply A * B, then take high byte
        LD      H, 0
        LD      L, A            ; HL = random value
        LD      D, 0
        LD      E, B            ; DE = range
       
        ; 16-bit multiplication HL = HL * DE
        CALL    MULTIPLY16
       
        ; Take high byte as result (gives good distribution)
        LD      A, H
        RET

;==============================================================================
; 16-bit multiplication helper: HL = HL * DE
; Destroys: BC
;==============================================================================
MULTIPLY16:
        LD      BC, 0           ; Initialize result
        LD      A, 16           ; 16 iterations
       
MULT_LOOP:
        ADD     HL, HL          ; Shift HL left
        JR      NC, MULT_SKIP   ; Skip if no carry
        ADD     BC, DE          ; Add DE to result
       
MULT_SKIP:
        DEC     A
        JR      NZ, MULT_LOOP
       
        LD      H, B            ; Move result to HL
        LD      L, C
        RET

;==============================================================================
; Demo/Test program
;==============================================================================
DEMO:
        ; Initialize with seed
        LD      HL, 12345
        CALL    RND_INIT
       
        ; Generate some random numbers
        CALL    RANDOM          ; A = random 0-255
        CALL    RANDOM          ; A = another random 0-255
       
        ; Generate random number 0-9 (for dice, etc.)
        LD      B, 10
        CALL    RANDOM_RANGE    ; A = random 0-9
       
        ; Generate random number 0-99
        LD      B, 100
        CALL    RANDOM_RANGE_FAST ; A = random 0-99
       
        RET

;==============================================================================
; Utility: Get a "random" seed from user timing
; Call this after user presses a key, uses timing for entropy
; Output: HL = pseudo-random seed
;==============================================================================
GET_TIMING_SEED:
        LD      HL, 0
TIMING_LOOP:
        INC     HL
        ; Check for keypress (system-specific)
        ; This is a placeholder - replace with your system's key check
        IN      A, (0)          ; Replace with actual port
        AND     1               ; Check key bit
        JR      Z, TIMING_LOOP  ; Keep counting until key pressed
       
        RET                     ; HL contains timing-based seed

        END


; Initialize
LD      HL, 54321
CALL    RND_INIT

; Get random byte (0-255)
CALL    RANDOM          ; Result in A

; Get random number 0-9
LD      B, 10
CALL    RANDOM_RANGE    ; Result in A

; Get random number 0-99 
LD      B, 100
CALL    RANDOM_RANGE_FAST ; Result in A
I'll test this out later.