home *** CD-ROM | disk | FTP | other *** search
- TTL "Getting better lottery program"
- ;
- ; =========================
- ; Amiga Shopper Assembly Language Course: Part VIII
- ;
- ; Lottery-Mungus!
- ;
- section PrintString,code
- ;
- ENTRY_POINT: bra.s START ; Call start of program.
- ;
- ; ---- Embedded version string: ....
- VERSION: dc.b 0,"$VER: lottery.asm 1.03 (25.3.95)",0
- ;
- ; ---- Include files ....
- ; ** POINT THIS NEXT LINE (incdir) TO WHERE YOUR INCLUDE FILES
- ; ARE STORED. (Normally 'include:' or 'inc:') ***
- incdir "inc:"
- include "exec/exec.i"
- include "exec/funcdef.i" ; You may not need this.
- include "exec/exec_lib.i"
- include "dos/dos.i"
- include "dos/dos_lib.i"
- include "intuition/intuition.i"
- include "intuition/intuition_lib.i" ; THIS IS ON THE COVERDISK IF YOU DON'T HAVE IT
- include "utility/tagitem.i"
- ;
- ; ---- Equates ....
- _EXECBASE: equ $04 ; exec.library base.
- TRUE: equ -1
- FALSE: equ 0 ; TRUE/FALSE definitions
- NULL: equ 0 ; Definition for NULL
- ;
- ; ---- Macro Definitions ....
- SYS: macro
- move.l _EXECBASE,a6
- jsr _LVO\1(a6) ; exec.library access macro
- endm
-
- DOS: macro
- move.l DosBase,a6
- jsr _LVO\1(a6) ; dos.library access macro
- endm
-
- INT: macro
- move.l IntBase,a6
- jsr _LVO\1(a6) ; intuition.library access macro
- endm
- ;
- ; ---- Main Program: ....
- START: lea DosName(pc),a1
- moveq #$00,d0
- SYS OpenLibrary
- move.l d0,DosBase
- beq ST_Failed_Dos ; Quit if no DOS.
- ;
- ; ---- Open intuition.library ....
- lea IntName(pc),a1
- moveq #$00,d0
- SYS OpenLibrary
- move.l d0,IntBase
- beq ST_Failed_Int ; Quit if no INT.
- ;
- ; ---- Now open our window ....
- suba.l a0,a0
- lea WindowTags(pc),a1
- INT OpenWindowTagList
- move.l d0,WindowPtr
- beq ST_Failed_Win ; Couldn't open window....
- ;
- ; ---- Find STDOUT: ....
- DOS Output
- move.l d0,STDOUT
- ;
- ; ---- Seed the random number generator ....
- bsr Init_Seed
- ;
- ; ---- Initialise variables for our main loop ....
- moveq #$05,d1
- lea Lottery_Guesses(pc),a0
- ;
- ; ===========================================================================
- ;
- ; ---- Pick 6 numbers with no duplicates ....
- ST_Get49: moveq #49,d0
- bsr Random_Number
- addq.w #$01,d0 ; Ensure the number is at least 1
- cmp.w #49,d0
- bhi.s ST_Get49 ; Loop around if it is > 49
- ;
- ; ---- Check if we've already picked this number ....
- lea Lottery_Guesses(pc),a1
- moveq #$05,d2
- ST_Check: cmp.b (a1)+,d0
- beq.s ST_Get49
- dbra d2,ST_Check
- ;
- ; ---- Store this number out in our list and continue till we're
- ; done ....
- move.b d0,(a0)+
- dbra d1,ST_Get49
- ;
- ; ===========================================================================
- ;
- ; ---- Now sort the numbers into numerical order using a bubble
- ; sort algorithm ....
- ;
- ; 1. Point to the first pair.
- BS_Sort: lea Lottery_Guesses(pc),a0
- moveq #$00,d2 ; Our swap counter
- moveq #$04,d3 ; Our loop counter (Total swaps to do)
- ;
- ; 2. If the first number in the pair is the greater, swap:
- BS_Bubble_Loop: move.b (a0),d0
- move.b 1(a0),d1 ; Fetch both numbers
- cmp.b d1,d0
- bls.s BS_No_Swap ; No need to swap.
- ;
- ; So swap them and count a swap:
- move.b d0,1(a0)
- move.b d1,(a0)
- addq.w #$01,d2 ; Increment swap counter
- ;
- ; 3 & 4. Point to the next pair:
- BS_No_Swap: addq.w #$01,a0
- dbra d3,BS_Bubble_Loop ; Swap all pairs
- ;
- ; 5. If we had any swaps, keep going:
- tst.w d2
- bne.s BS_Sort ; Keep sortin'
- ;
- ; ===========================================================================
- ;
- ; ---- Now create the string for PrintIText ....
- moveq #$05,d1
- lea Lottery_Guesses(pc),a2
- lea OurText(pc),a0 ; Place we're creating our string
- ST_Show_Loop: moveq #$00,d0
- move.b (a2)+,d0
- bsr ShowDecimal5
- move.b #' ',(a0)+ ; A space between each one...
- dbra d1,ST_Show_Loop
- clr.b (a0) ; A zero at the end.
- ;
- ; ---- Now show lottery guesses in our window ....
- move.l WindowPtr,a0
- move.l wd_RPort(a0),a0
- lea WindowText(pc),a1
- moveq #30,d0 ; Pixels across...
- moveq #30,d1 ; Pixels down...
- INT PrintIText
- ;
- ; ---- Finally wait for user to click on close gadget ....
- ST_Wait_Close: move.l WindowPtr,a0
- move.l wd_UserPort(a0),a0
- SYS WaitPort ; Wait for message to arrive...
- ;
- ; ---- Loop through and process any messages present ....
- ST_MoreMsgs: move.l WindowPtr,a0
- move.l wd_UserPort(a0),a0
- SYS GetMsg ; Get message
- tst.l d0
- beq.s ST_Wait_Close ; Thats it, no more messages
- ;
- ; ---- Got one, process it ....
- move.l d0,a1
- move.l im_Class(a1),d0
- cmp.l #IDCMP_CLOSEWINDOW,d0
- beq.s ST_Quit ; Yes! The close gadget pressed
- ;
- ; ---- Reply to it ....
- SYS ReplyMsg
- bra.s ST_Wait_Close
- ;
- ; ===========================================================================
- ;
- ; ---- Close librarys and exit: ....
- ST_Quit: SYS ReplyMsg ; Ensure it is replied to
- move.l WindowPtr,a0
- INT CloseWindow ; Close window
- ;
- ST_Failed_Win: move.l IntBase,a1
- SYS CloseLibrary ; Close intuition
- ;
- ST_Failed_Int: move.l DosBase,a1
- SYS CloseLibrary ; Close dos
- ;
- ST_Failed_Dos: moveq #$00,d0 ; Return no error code.
- rts
- ;
- IntName: dc.b "intuition.library",0
- DosName: dc.b "dos.library",0
- IntBase: dc.l 0 ; Storage for intuition.library base
- DosBase: dc.l 0 ; Storage for dos.library base
- STDOUT: dc.l 0 ; Storage for STDOUT file handle
- ;
- Lottery_Guesses:dc.b 0,0,0,0,0,0
- ;
- ; ---- This is our openwindow taglist ....
- WindowTags: dc.l WA_Width,400
- dc.l WA_Height,100
- dc.l WA_CloseGadget,TRUE
- dc.l WA_SizeGadget,TRUE
- dc.l WA_DepthGadget,TRUE
- dc.l WA_DragBar,TRUE
- dc.l WA_Title,wt_WindowTitle
- dc.l WA_IDCMP,IDCMP_CLOSEWINDOW
- dc.l TAG_DONE
- ;
- wt_WindowTitle: dc.b "Lottery Window!",0
- ;
- WindowPtr: dc.l 0 ; struct Window *... Our window ID.
- ;
- ; ---- Our IntuiText structure ....
- WindowText: dc.b 1,0 ; Pens to draw in, front and back
- dc.b RP_JAM1
- dc.w 0,0
- dc.l NULL
- dc.l OurText
- dc.l NULL
- ;
- OurText: ds.b 100 ; Reserve 100 bytes of text
- ;
- ; .....................................
- ;
- ; ShowDecimal5():
- ;
- ; Converts decimal to ASCII. The ASCII is stored out at
- ; whereever A0 points to. Leading zeros are supressed
- ;
- ShowDecimal5: movem.l a1/d0-d2,-(sp)
- moveq #$04,d1
- lea SD5_Dividors(pc),a1
- moveq #TRUE,d3 ; Supress Zero flag
- ;
- ; ---- Create our number string ....
- SD5_Loop: move.l (a1)+,d2
- divu d2,d0
- add.b #$30,d0 ; Turn result to ASCII number
- ;
- cmp.b #$30,d0 ; Is it a zero?
- bne.s SD5_NotZero
- tst.w d3
- beq.s SD5_Continue
- bra.s SD5_Skip
- ;
- SD5_NotZero: moveq #FALSE,d3 ; No more zero supression
- ;
- SD5_Continue: move.b d0,(a0)+ ; Put character to output buffer
- SD5_Skip: swap d0
- and.l #$ffff,d0 ; Get remainder.
- ;
- dbra d1,SD5_Loop ; Loop round doing all digits.
- movem.l (sp)+,d0-d2/a1
- rts
- ;
- ; ---- Dividor table & data for the decimal routine ....
- SD5_Dividors: dc.l 10000,1000,100,10,1
- ;
- ; .....................................
- ;
- ; PrintString():
- ;
- ; Shows the string pointed to by A0 to STDOUT. This routine assumes
- ; STDOUT has already been obtained and filled out. Registers on exit
- ; are undefined.
- ;
- PrintString: move.l a0,d2
- bsr StringLength ; Get length of string
- move.l d0,d3
- move.l STDOUT,d1
- DOS Write ; Show string on STDOUT
- rts
- ;
- ; .....................................
- ;
- ; StringLength():
- ;
- ; Returns the length of the string pointed to by A0 in D0. On exit,
- ; A0 points to the end of the string.
- ;
- StringLength: moveq #-1,d0
- SL_Count: addq.l #$01,d0
- tst.b (a0)+
- bne.s SL_Count ; Count string till we reach the end
- rts
- ;
- ; ===========================================================================
- ; Psuedo Random Number Generator
- ; ...........................................................................
- ; %%%%
- ; void Init_Seed(void)
- ;
- ; This code was used in a similar form in the Aquatic Games.
- ;
- ; No inputs, No outputs, Registers Preserved.
- ; %%%%
- ;
- IR_M: equ 65535
- IR_B: equ 8821
- ;
- Init_Seed: movem.l d0-d1/a0,-(sp)
- moveq #$00,d0
- IS_Re_Do: move.w $dff006,d0 ; get random seed
- tst.w d0
- beq.s IS_Re_Do
- moveq #64-1,d1
- lea RandomBuffer,a0
- IS_Loop: mulu #IR_B,d0
- addq.w #1,d0
- divu #IR_M,d0 ;do seed=(seed*b+1) mod m
- swap d0
- move.w d0,(a0)+ ;insert into array.
- dbra d1,IS_Loop
- movem.l (sp)+,d0-d1/a0
- rts
- ;
- ; ...........................................................................
- ; %%%%
- ; uword Random_Number(uword Max_Number)
- ; d0 d0
- ;
- ;
- ; This function returns a number between 0 and d0-1. It returns
- ; the value in d0.
- ; This code was used in a similair form in the Aquatics.
- ;
- ; Inputs:
- ; Max_Number The maximum number to return + 1
- ;
- ; Outputs:
- ; random The random number from 0 to Max_Number-1
- ;
- ; Registers preserved.
- ; %%%%
- ;
- Random_Number: movem.l d1-d3/a0,-(sp)
- tst.w d0
- bne.s RN_Fine
- moveq #$00,d0
- movem.l (sp)+,d1-d3/a0
- rts
- ;
- RN_Fine: lea RandomBuffer,a0
- addq.w #2,RandomSeed
- moveq #$00,d1
- move.w RandomSeed,d1
- and.w #63*2,d1
- moveq #23*2,d3
- add.w d1,d3
- and.w #63*2,d3
- move.w 0(a0,d3.w),d2
- moveq #54*2,d3
- add.w d1,d3
- and.w #63*2,d3
- move.w 0(a0,d3.w),d3
- eor.w d3,d2 ;could be add.w d1,d2 also! (seems to work!)
- move.w d2,0(a0,d1.w) ;insert back into table
- move.w d2,d1 ;return rand in d0.w
- divu.w d0,d1
- swap d1
- moveq #$00,d0
- move.w d1,d0
- movem.l (sp)+,d1-d3/a0
- rts
- ;
- RandomBuffer: dcb.w 64
- RandomSeed: dc.w 0 ; Random # generator seed/bfr
- END
-