home *** CD-ROM | disk | FTP | other *** search
/ Dave Lowe: Devpac Amiga 1 / Lowe_DevpacAmiga1.adf / lottery.asm < prev    next >
Encoding:
Assembly Source File  |  1995-03-26  |  8.9 KB  |  370 lines

  1.         TTL    "Getting better lottery program"
  2. ;
  3. ; =========================
  4. ; Amiga Shopper Assembly Language Course: Part VIII
  5. ;
  6. ; Lottery-Mungus!
  7. ;
  8.         section    PrintString,code
  9. ;
  10. ENTRY_POINT:    bra.s    START            ; Call start of program.
  11. ;
  12. ; ---- Embedded version string: ....
  13. VERSION:    dc.b    0,"$VER: lottery.asm 1.03 (25.3.95)",0
  14. ;
  15. ; ---- Include files ....
  16. ; ** POINT THIS NEXT LINE (incdir) TO WHERE YOUR INCLUDE FILES
  17. ;    ARE STORED. (Normally 'include:' or 'inc:') ***
  18.         incdir    "inc:"            
  19.         include    "exec/exec.i"
  20.         include    "exec/funcdef.i"    ; You may not need this.
  21.         include    "exec/exec_lib.i"
  22.         include    "dos/dos.i"
  23.         include    "dos/dos_lib.i"
  24.         include    "intuition/intuition.i"
  25.         include    "intuition/intuition_lib.i"    ; THIS IS ON THE COVERDISK IF YOU DON'T HAVE IT
  26.         include    "utility/tagitem.i"
  27. ;
  28. ; ---- Equates ....
  29. _EXECBASE:    equ    $04            ; exec.library base.
  30. TRUE:        equ    -1
  31. FALSE:        equ    0            ; TRUE/FALSE definitions
  32. NULL:        equ    0            ; Definition for NULL
  33. ;
  34. ; ---- Macro Definitions ....
  35. SYS:        macro
  36.         move.l    _EXECBASE,a6
  37.         jsr    _LVO\1(a6)        ; exec.library access macro
  38.         endm
  39.  
  40. DOS:        macro
  41.         move.l    DosBase,a6
  42.         jsr    _LVO\1(a6)        ; dos.library access macro
  43.         endm
  44.  
  45. INT:        macro
  46.         move.l    IntBase,a6
  47.         jsr    _LVO\1(a6)        ; intuition.library access macro
  48.         endm
  49. ;
  50. ; ---- Main Program: ....
  51. START:        lea    DosName(pc),a1
  52.         moveq    #$00,d0
  53.         SYS    OpenLibrary
  54.         move.l    d0,DosBase
  55.         beq    ST_Failed_Dos    ; Quit if no DOS.
  56. ;
  57. ; ---- Open intuition.library ....
  58.         lea    IntName(pc),a1
  59.         moveq    #$00,d0
  60.         SYS    OpenLibrary
  61.         move.l    d0,IntBase
  62.         beq    ST_Failed_Int    ; Quit if no INT.
  63. ;
  64. ; ---- Now open our window ....
  65.         suba.l    a0,a0
  66.         lea    WindowTags(pc),a1
  67.         INT    OpenWindowTagList
  68.         move.l    d0,WindowPtr
  69.         beq    ST_Failed_Win    ; Couldn't open window....
  70. ;
  71. ; ---- Find STDOUT: ....
  72.         DOS    Output
  73.         move.l    d0,STDOUT
  74. ;
  75. ; ---- Seed the random number generator ....
  76.         bsr    Init_Seed
  77. ;
  78. ; ---- Initialise variables for our main loop ....
  79.         moveq    #$05,d1
  80.         lea    Lottery_Guesses(pc),a0
  81. ;
  82. ; ===========================================================================
  83. ;
  84. ; ---- Pick 6 numbers with no duplicates ....
  85. ST_Get49:    moveq    #49,d0
  86.         bsr    Random_Number
  87.         addq.w    #$01,d0        ; Ensure the number is at least 1
  88.         cmp.w    #49,d0
  89.         bhi.s    ST_Get49    ; Loop around if it is > 49
  90. ;
  91. ; ---- Check if we've already picked this number ....
  92.         lea    Lottery_Guesses(pc),a1
  93.         moveq    #$05,d2
  94. ST_Check:    cmp.b    (a1)+,d0
  95.         beq.s    ST_Get49
  96.         dbra    d2,ST_Check
  97. ;
  98. ; ---- Store this number out in our list and continue till we're
  99. ;    done ....
  100.         move.b    d0,(a0)+
  101.         dbra    d1,ST_Get49
  102. ;
  103. ; ===========================================================================
  104. ;
  105. ; ---- Now sort the numbers into numerical order using a bubble
  106. ;    sort algorithm ....
  107. ;
  108. ; 1. Point to the first pair.
  109. BS_Sort:    lea    Lottery_Guesses(pc),a0
  110.         moveq    #$00,d2        ; Our swap counter
  111.         moveq    #$04,d3        ; Our loop counter (Total swaps to do)
  112. ;
  113. ; 2. If the first number in the pair is the greater, swap:
  114. BS_Bubble_Loop:    move.b    (a0),d0
  115.         move.b    1(a0),d1    ; Fetch both numbers
  116.         cmp.b    d1,d0
  117.         bls.s    BS_No_Swap    ; No need to swap.
  118. ;
  119. ;    So swap them and count a swap:
  120.         move.b    d0,1(a0)
  121.         move.b    d1,(a0)
  122.         addq.w    #$01,d2        ; Increment swap counter
  123. ;
  124. ; 3 & 4. Point to the next pair:
  125. BS_No_Swap:    addq.w    #$01,a0
  126.         dbra    d3,BS_Bubble_Loop ; Swap all pairs
  127. ;
  128. ; 5. If we had any swaps, keep going:
  129.         tst.w    d2
  130.         bne.s    BS_Sort        ; Keep sortin'
  131. ;
  132. ; ===========================================================================
  133. ;
  134. ; ---- Now create the string for PrintIText ....
  135.         moveq    #$05,d1
  136.         lea    Lottery_Guesses(pc),a2
  137.         lea    OurText(pc),a0    ; Place we're creating our string
  138. ST_Show_Loop:    moveq    #$00,d0
  139.         move.b    (a2)+,d0
  140.         bsr    ShowDecimal5
  141.         move.b    #' ',(a0)+    ; A space between each one...
  142.         dbra    d1,ST_Show_Loop
  143.         clr.b    (a0)        ; A zero at the end.
  144. ;
  145. ; ---- Now show lottery guesses in our window ....        
  146.         move.l    WindowPtr,a0
  147.         move.l    wd_RPort(a0),a0
  148.         lea    WindowText(pc),a1
  149.         moveq    #30,d0        ; Pixels across...
  150.         moveq    #30,d1        ; Pixels down...
  151.         INT    PrintIText
  152. ;
  153. ; ---- Finally wait for user to click on close gadget ....
  154. ST_Wait_Close:    move.l    WindowPtr,a0
  155.         move.l    wd_UserPort(a0),a0
  156.         SYS    WaitPort    ; Wait for message to arrive...
  157. ;
  158. ; ---- Loop through and process any messages present ....
  159. ST_MoreMsgs:    move.l    WindowPtr,a0
  160.         move.l    wd_UserPort(a0),a0
  161.         SYS    GetMsg        ; Get message
  162.         tst.l    d0
  163.         beq.s    ST_Wait_Close    ; Thats it, no more messages
  164. ;
  165. ; ---- Got one, process it ....
  166.         move.l    d0,a1
  167.         move.l    im_Class(a1),d0
  168.         cmp.l    #IDCMP_CLOSEWINDOW,d0
  169.         beq.s    ST_Quit        ; Yes! The close gadget pressed
  170. ;
  171. ; ---- Reply to it ....
  172.         SYS    ReplyMsg
  173.         bra.s    ST_Wait_Close
  174. ;
  175. ; ===========================================================================
  176. ;
  177. ; ---- Close librarys and exit: ....
  178. ST_Quit:    SYS    ReplyMsg    ; Ensure it is replied to
  179.         move.l    WindowPtr,a0
  180.         INT    CloseWindow    ; Close window
  181. ;
  182. ST_Failed_Win:    move.l    IntBase,a1
  183.         SYS    CloseLibrary    ; Close intuition
  184. ;
  185. ST_Failed_Int:    move.l    DosBase,a1
  186.         SYS    CloseLibrary    ; Close dos
  187. ;
  188. ST_Failed_Dos:    moveq    #$00,d0        ; Return no error code.
  189.         rts
  190. ;
  191. IntName:    dc.b    "intuition.library",0
  192. DosName:    dc.b    "dos.library",0    
  193. IntBase:    dc.l    0        ; Storage for intuition.library base
  194. DosBase:    dc.l    0        ; Storage for dos.library base
  195. STDOUT:        dc.l    0        ; Storage for STDOUT file handle
  196. ;
  197. Lottery_Guesses:dc.b    0,0,0,0,0,0
  198. ;
  199. ; ---- This is our openwindow taglist ....
  200. WindowTags:    dc.l    WA_Width,400
  201.         dc.l    WA_Height,100
  202.         dc.l    WA_CloseGadget,TRUE
  203.         dc.l    WA_SizeGadget,TRUE
  204.         dc.l    WA_DepthGadget,TRUE
  205.         dc.l    WA_DragBar,TRUE
  206.         dc.l    WA_Title,wt_WindowTitle
  207.         dc.l    WA_IDCMP,IDCMP_CLOSEWINDOW
  208.         dc.l    TAG_DONE
  209. ;
  210. wt_WindowTitle:    dc.b    "Lottery Window!",0
  211. ;
  212. WindowPtr:    dc.l    0        ; struct Window *... Our window ID.
  213. ;
  214. ; ---- Our IntuiText structure ....
  215. WindowText:    dc.b    1,0        ; Pens to draw in, front and back
  216.         dc.b    RP_JAM1
  217.         dc.w    0,0
  218.         dc.l    NULL
  219.         dc.l    OurText
  220.         dc.l    NULL
  221. ;
  222. OurText:    ds.b    100        ; Reserve 100 bytes of text
  223. ;
  224. ; .....................................
  225. ;
  226. ;    ShowDecimal5():
  227. ;
  228. ;    Converts decimal to ASCII. The ASCII is stored out at
  229. ;    whereever A0 points to. Leading zeros are supressed
  230. ;
  231. ShowDecimal5:    movem.l    a1/d0-d2,-(sp)
  232.         moveq    #$04,d1
  233.         lea    SD5_Dividors(pc),a1
  234.         moveq    #TRUE,d3    ; Supress Zero flag
  235. ;
  236. ; ---- Create our number string ....
  237. SD5_Loop:    move.l    (a1)+,d2
  238.         divu    d2,d0        
  239.         add.b    #$30,d0        ; Turn result to ASCII number
  240. ;
  241.         cmp.b    #$30,d0        ; Is it a zero?
  242.         bne.s    SD5_NotZero
  243.         tst.w    d3
  244.         beq.s    SD5_Continue
  245.         bra.s    SD5_Skip
  246. ;
  247. SD5_NotZero:    moveq    #FALSE,d3    ; No more zero supression
  248. ;
  249. SD5_Continue:    move.b    d0,(a0)+    ; Put character to output buffer
  250. SD5_Skip:    swap    d0
  251.         and.l    #$ffff,d0    ; Get remainder.
  252. ;
  253.         dbra    d1,SD5_Loop    ; Loop round doing all digits.
  254.         movem.l    (sp)+,d0-d2/a1
  255.         rts
  256. ;
  257. ; ---- Dividor table & data for the decimal routine ....
  258. SD5_Dividors:    dc.l    10000,1000,100,10,1
  259. ;
  260. ; .....................................
  261. ;
  262. ;    PrintString():
  263. ;
  264. ;    Shows the string pointed to by A0 to STDOUT. This routine assumes
  265. ;    STDOUT has already been obtained and filled out. Registers on exit
  266. ;    are undefined.
  267. ;
  268. PrintString:    move.l    a0,d2
  269.         bsr    StringLength    ; Get length of string
  270.         move.l    d0,d3
  271.         move.l    STDOUT,d1
  272.         DOS    Write        ; Show string on STDOUT
  273.         rts
  274. ;
  275. ; .....................................
  276. ;
  277. ;    StringLength():
  278. ;
  279. ;    Returns the length of the string pointed to by A0 in D0. On exit,
  280. ;    A0 points to the end of the string.
  281. ;
  282. StringLength:    moveq    #-1,d0
  283. SL_Count:    addq.l    #$01,d0
  284.         tst.b    (a0)+
  285.         bne.s    SL_Count    ; Count string till we reach the end
  286.         rts
  287. ;
  288. ; ===========================================================================
  289. ;        Psuedo Random Number Generator
  290. ; ...........................................................................
  291. ;    %%%%
  292. ;    void Init_Seed(void)
  293. ;
  294. ;    This code was used in a similar form in the Aquatic Games.
  295. ;
  296. ;    No inputs, No outputs, Registers Preserved.
  297. ;    %%%%
  298. ;
  299. IR_M:        equ    65535
  300. IR_B:        equ    8821
  301. ;
  302. Init_Seed:    movem.l    d0-d1/a0,-(sp)
  303.         moveq    #$00,d0
  304. IS_Re_Do:    move.w    $dff006,d0        ; get random seed
  305.         tst.w    d0
  306.         beq.s    IS_Re_Do
  307.         moveq    #64-1,d1
  308.         lea    RandomBuffer,a0
  309. IS_Loop:    mulu    #IR_B,d0
  310.         addq.w    #1,d0
  311.         divu    #IR_M,d0        ;do seed=(seed*b+1) mod m
  312.         swap    d0
  313.         move.w    d0,(a0)+        ;insert into array.
  314.         dbra    d1,IS_Loop
  315.         movem.l    (sp)+,d0-d1/a0
  316.         rts
  317. ;
  318. ; ...........................................................................
  319. ;    %%%%
  320. ;    uword Random_Number(uword Max_Number)
  321. ;     d0             d0
  322. ;
  323. ;
  324. ;    This function returns a number between 0 and d0-1. It returns
  325. ;    the value in d0.    
  326. ;    This code was used in a similair form in the Aquatics.
  327. ;
  328. ;    Inputs:
  329. ;        Max_Number     The maximum number to return + 1
  330. ;
  331. ;    Outputs:
  332. ;        random        The random number from 0 to Max_Number-1
  333. ;
  334. ;    Registers preserved.
  335. ;    %%%%
  336. ;
  337. Random_Number:    movem.l    d1-d3/a0,-(sp)
  338.         tst.w    d0
  339.         bne.s    RN_Fine
  340.         moveq    #$00,d0
  341.         movem.l    (sp)+,d1-d3/a0
  342.         rts
  343. ;
  344. RN_Fine:    lea    RandomBuffer,a0
  345.         addq.w    #2,RandomSeed
  346.         moveq    #$00,d1
  347.         move.w    RandomSeed,d1
  348.         and.w    #63*2,d1
  349.         moveq    #23*2,d3
  350.         add.w    d1,d3
  351.         and.w    #63*2,d3
  352.         move.w    0(a0,d3.w),d2
  353.         moveq    #54*2,d3
  354.         add.w    d1,d3
  355.         and.w    #63*2,d3
  356.         move.w    0(a0,d3.w),d3
  357.         eor.w    d3,d2            ;could be add.w    d1,d2 also! (seems to work!)
  358.         move.w    d2,0(a0,d1.w)        ;insert back into table
  359.         move.w    d2,d1            ;return rand in d0.w
  360.         divu.w    d0,d1
  361.         swap    d1
  362.         moveq    #$00,d0
  363.         move.w    d1,d0
  364.         movem.l    (sp)+,d1-d3/a0        
  365.         rts
  366. ;
  367. RandomBuffer:    dcb.w    64
  368. RandomSeed:    dc.w    0            ; Random # generator seed/bfr
  369.         END
  370.