;/***************************************************************************
; *                                                                         *
; * Module  : arand.s                                                       *
; *                                                                         *
; * Purpose : A random number generator using the lagged additive method    *
; *                                                                         *
; * Version : 1, January 11 1998                                            *
; *                                                                         *
; * Author  : Luc Van den Borre ( Homepage : NOC.BASE.ORG )                 *
; *                                                                         * 
; **************************************************************************/       

        .include        "..\..\lib\global.s"
        .include        "rndglob.s"

        .area   _BSS
.randarr:
        .ds     55
.raxj:
        .ds     0x1
.raxk:
        .ds     0x1

        .area   _CODE

        ;; arand() operates on an array of 55 arbitrary values (here : bytes). It adds two values of the array
        ;; together, replaces one of the values with the result, and returns the result.
        ;; At start, the indices into the array refer to the 55th and 24th element. After each call, 
        ;; each index is decreased, and looped around if necessary.
        ;; This kind of works, but the values produces are less good than those by rand(), mainly because
        ;; it operates on bytes instead of words.
        ;; Ref : D. E. Knuth, "The Art of Computer Programming" , Volume 2
        ;;
        ;; Exit conditions
        ;;   DE = Random number (byte!)
        ;;
        ;; Registers used: 
        ;;   all
        ;;
_arand::
        PUSH    BC
        LD      D, #0
        LD      HL, #.randarr-1
        LD      A, (.raxj)
        LD      E, A
        DEC     A               ; decrease the pointer
        JP      NZ, arand1
        LD      A, #55
arand1: LD      (.raxj), A
        ADD     HL, DE
        LD      B, (HL)

        LD      HL, #.randarr-1   ; ooh...
        LD      A, (.raxk)
        LD      E, A
        DEC     A               ; decrease the pointer
        JP      NZ, arand2
        LD      A, #55
arand2: LD      (.raxk), A
        ADD     HL, DE
        LD      A, (HL)

        ADD     A, B
        LD      (HL), A         ; store new value

        POP     BC

        LD      D, #0
        LD      E, A
      
        ret


        ;; _initarand calls the _rand function to fill the array with random values
        ;; Note that this also sets the seed value of the _rand function first, like _initrand
        ;;
        ;; Exit conditions
        ;;   DE = #0
        ;;
        ;; Registers used: 
        ;;   all
        ;;
_initarand::        
        LDA     HL,2(SP)    ; set the seed value
        LD      A, (HL+)
        LD      (.randlo), A        
        LD      A, (HL)
        LD      (.randhi), A

        PUSH    BC
        LD      A, #55
        LD      HL, #.randarr        
1$:           
        DEC     A
        LD      (.raxj), A  
        LD      B, H
        LD      C, L
        CALL    _rand 
        LD      H, B
        LD      L, C

        LD      (HL), D
        INC     HL
        LD      (HL), E        
        INC     HL
        
        LD      A, (.raxj)
        CP      #0
        JP      NZ, 1$      
                            ; now the array has been filled, set the pointers        
        LD      A, #24
        LD      (.raxj), A
        LD      A, #55
        LD      (.raxk), A

        POP     BC
        LD      DE, #0
        RET
        

        ret
       