*
; $VER: shuffle.a 1.91 (08.20.94)
;
; Shuffle algorithm and stats algorithm for Black Jack
;  Written by John Corigliano 1994
*

*------Includes

    INCLUDE "intuition/intuition.i"



*------Equates

ADECK               EQU     104     ; 52 * 2 (sizeof(UWORD))
Card_sizeof         EQU     14      ; 1 UBYTE and 3 PTRS + pad

; Exec
_LVOAllocMem        EQU     -$C6
_LVOFreeMem         EQU     -$D2

; Gfx
_LVOVBeamPos        EQU     -$180
_LVOSetAPen         EQU     -$156
_LVOMove            EQU     -$F0
_LVOText            EQU     -$3C


*------Macros

LIBCALL     MACRO
            movea.l _\2,a6
            jsr     _LVO\1(a6)
            ENDM


*------Externals

        XDEF    @shuffle
        XDEF    @showStats

        XREF    _SysBase
        XREF    _GfxBase

        XREF    @wText
        XREF    @gauge
        XREF    _pNum
        XREF    _win_offset

        XREF    _num_decks          ;UBYTE
        XREF    _deck               ;PTR-PTR to struct Card
        XREF    _dealt              ;UWORD
        XREF    _p_crd              ;PTR to UBYTE
        XREF    _d_crd              ;PTR to UBYTE
        XREF    _stat_win           ;PTR to window
        XREF    _jdeck              ;PTR to struct Card


*------Code

        SECTION text,CODE

@shuffle:
        movem.l d0-d7/a0-a6,-(a7)

        move.w  #0,_dealt
        lea     s_text,a0
        jsr     @wText
        
        clr.l   d2
        move.b  _num_decks,d2       ; d2 = number of decks
        mulu    #ADECK,d2           ; d2 = 52 * 2 * number of decks
        move.l  d2,d0
        clr.l   d1                  ; MEMF_ANY
        LIBCALL AllocMem,SysBase
        move.l  d0,a5               ; a5 points to memory
        beq.w   done                ; quit if no mem
 
        move.l  d0,a0               ; Find end of mem block
        move.l  d0,a1
        add.l   d2,a0
setmem:
        move.l  #$FFFFFFFF,(a1)+    ; setmem (LONG WORD)
        cmp.l   a0,a1
        beq.s   cards
        bra.s   setmem

cards:  
        move.l  #12,d0              ; for 13 cards
        lea     _p_crd,a0           ; Player's 'cards'
        lea     _d_crd,a1           ; Dealer's 'cards'
s_loop:
        clr.b   (a0)+
        clr.b   (a1)+
        dbra    d0,s_loop

mix:    
        move.l  a5,a0
        subq    #2,a0
        move.l  a5,a1
        add.l   d2,a0
        divu    #2,d2
        subq    #1,d2

        LIBCALL VBeamPos,GfxBase
        move.l  d0,d7               ; rand seed

get_rand:
        mulu    #5,d7               ; multiplier
        add     #12479,d7           ; increment
        divu    #32768,d7           ; modulus
        clr.w   d7                  ; only need remainder
        swap    d7                  ; remainder
        move.w  d7,d0               ; return value in d0
        andi.w  #$1FF,d0            ; only need low 7 bits - max = 416
dec:
        cmp.w   d2,d0               ; is d0 > num cards
        ble.s   check
        divu    d2,d0
        clr.w   d0
        swap    d0
        bra.s   dec
check:  
        cmp.w   (a1),d0             ; is it in the array already
        bne.s   is_good
        move.l  a5,a1               ; it's in the array!
        bra.s   get_rand            ; try new number
is_good:
        cmp.w   #$FFFF,(a1)         ; haven't got this far yet
        beq.s   go_on               ; put it in the array!
        addq    #2,a1               ; pnt to next element of array
        bra.s   check
go_on:
        move.w  d0,(a1)             ; copy d0 to array
        cmp.l   a1,a0               ; end of array?
        beq.s   sort
        move.l  a5,a1               ; go back to start of array
        bra.s   get_rand

sort:
        move.l  _deck,a1            ; 1st element of array of PTR to Card

        move.l  a5,a0
loop1:
        lea     _jdeck,a2           ; 1st of 13 PTRs to Card
        clr.l   d0
        clr.l   d1
        move.w  (a0),d1             ; 1st element (0-51)
        divu    #52,d1
        swap    d1
        clr.w   d1                  ; integer division
        swap    d1                  ; num = temp[i] / 52
        mulu    #52,d1              ; num = num * 52
        move.w  (a0)+,d0
        sub.w   d1,d0               ; num = temp[i] - num
        mulu    #Card_sizeof,d0     ; offset from jdeck[0]
        add.l   d0,a2
        move.l  a2,(a1)+
        dbra    d2,loop1

free_mem:
        movea.l a5,a1
        clr.l   d0
        move.b  _num_decks,d0       ; d2 = number of decks
        mulu    #ADECK,d0           ; d2 = 52 * 2 * number of decks
        LIBCALL FreeMem,SysBase

done:
        lea     ok_text,a0
        jsr     @wText
        jsr     @gauge
        bra.s   stat

@showStats:
        movem.l d0-d7/a0-a6,-(a7)

stat:
        movea.l _stat_win,a0
        cmp.l   #0,a0
        beq.w   exit

        clr.l   d0
        clr.l   d1
        clr.l   d2
        clr.l   d3
        clr.l   d4
        clr.l   d7
        move.l  wd_RPort(a0),a1         ; win->RPort in a1
        move.b  #1,d0
        LIBCALL SetAPen,GfxBase

        move.b  _num_decks,d2
        lsl.b   #2,d2                   ; total in d2
        move.b  #12,d3                  ; d3 = x
        move.b  #21,d4                  ; d4 = y
        lea     _p_crd,a2
        lea     _d_crd,a3

calc:
        clr.l   d5
        move.b  (a2),d5                 ; d5 = perc
        add.b   (a3),d5
        mulu    #100,d5
        divu    d2,d5
        swap    d5
        clr.w   d5
        swap    d5
        lea     str,a0

        clr.l   d0                      ; Convert decimal to letter
        cmp.b   #10,(a2)
        bge.s   .b1
        move.b  #32,(a0)+
        move.b  (a2)+,(a0)
        addi    #48,(a0)+
        bra.s   .b2
.b1     move.b  (a2)+,d0
        divu    #10,d0
        move.b  d0,(a0)
        addi    #48,(a0)+
        swap    d0
        move.b  d0,(a0)
        addi    #48,(a0)+

.b2     move.b  #32,(a0)+
        move.b  #32,(a0)+
        clr.l   d0
        cmp.b   #10,(a3)
        bge.s   .b3
        move.b  #32,(a0)+
        move.b  (a3)+,(a0)
        addi    #48,(a0)+
        bra.s   .b4
.b3     move.b  (a3)+,d0
        divu    #10,d0
        move.b  d0,(a0)
        addi    #48,(a0)+
        swap    d0
        move.b  d0,(a0)
        addi    #48,(a0)+

.b4     move.b  #32,(a0)+
        move.b  #32,(a0)+
        cmp.b   #100,d5
        bne.s   br_01
        move.b  #'-',(a0)+
        move.b  #'-',(a0)+
        bra.s   print_it
br_01   cmp.b   #9,d5        
        ble.s   br_02
        divu    #10,d5
        move.b  d5,(a0)
        addi    #48,(a0)+
        swap    d5
        move.b  d5,(a0)
        addi    #48,(a0)+
        bra.s   print_it
br_02   move.b  #32,(a0)+
        move.b  d5,(a0)
        addi    #48,(a0)+

print_it:
        movea.l _stat_win,a4
        move.l  wd_RPort(a4),a1         ; win->RPort in a1
        move.b  #0,(a0)
        move.l  #30,d0
        move.l  d4,d1
        add.b   _win_offset,d1
        LIBCALL Move,GfxBase
        move.l  #10,d0
        lea     str,a0
        LIBCALL Text,GfxBase
        add.b   #10,d4
        dbra    d3,calc

exit:
        movem.l (a7)+,d0-d7/a0-a6
        rts


*------Variables

        SECTION  mem,BSS

str     ds.b    11


        SECTION data,DATA

s_text  dc.b    'Shuffling....',0
ok_text dc.b    'Okay...',0

    end
