;   Worm, The Latest Version
;   © 1991/1992 Ducksoft
;   We apologize for the somewhat silly comments --
;   this was coded late at night.

            incdir  "include:
            include "exec/exec_lib.i"
            include "graphics/graphics_lib.i"
            include "intuition/intuition_lib.i"
            include "intuition/intuition.i" ;hate to do this, but...
            include "libraries/dos_lib.i"

    ; Deal with the system: open Graphics, snog sprites 2-7 and die
    ; gracefully if we can't get 'em all.

grabsprites move.l  4,a6
            lea     gname,a1
            moveq.l #0,d0
            jsr     _LVOOpenLibrary(a6)
            move.l  d0,a6
            move.l  d0,GLib
            moveq.l #2,d6
            lea     ImgLst,a4
.1          move.w  d6,d0
            move.l  (a4)+,a0            ;List of sprite structs
            jsr     _LVOGetSprite(a6)   ;Snog!
            cmp.b   d0,d6               ;Did we get the one we wanted?
            bne     ls.1                ;Nope. Die real quietly.
            addq.l  #1,d6
            cmp.b   #8,d6
            bne.s   .1

    ; Ok, got my dirty li'l paws on the sprites. Now it's time to open up
    ; my little window.

            move.l  4,a6
            lea     dname,a1
            moveq.l #0,d0
            jsr     _LVOOpenLibrary(a6)
            move.l  d0,DLib
            lea     iname,a1
            moveq.l #0,d0
            jsr     _LVOOpenLibrary(a6)
            move.l  d0,a6
            move.l  d0,ILib
            lea     windowdef,a0
            jsr     _LVOOpenWindow(a6)
            move.l  d0,WPtr
            beq     closeint        ;Couldn't open window?
            move.w  d0,Random       ;Good as any for random seed...
            move.l  d0,a0
            move.l  wd_WScreen(a0),a0
            move.l  a0,Scrn         ;save window's screen
            lea     sc_ViewPort(a0),a0
            move.l  a0,Vyew         ;and screen's view
    ; And now for brute force setting of the colors.
    ; There's GOTTA be a better way, but until I find one...
            move.l  GLib,a6
            moveq.b #21,d0
            moveq.b #5,d1
            moveq.b #5,d2
            moveq.b #13,d3
            jsr     _LVOSetRGB4(a6)
            moveq.b #25,d0
            moveq.b #5,d1
            moveq.b #5,d2
            moveq.b #13,d3
            jsr     setcol
            moveq.b #29,d0
            moveq.b #5,d1
            moveq.b #5,d2
            moveq.b #13,d3
            jsr     setcol
            moveq.b #22,d0
            moveq.b #1,d1
            moveq.b #1,d2
            moveq.b #11,d3
            jsr     setcol
            moveq.b #26,d0
            moveq.b #1,d1
            moveq.b #1,d2
            moveq.b #11,d3
            jsr     setcol
            moveq.b #30,d0
            moveq.b #1,d1
            moveq.b #1,d2
            moveq.b #11,d3
            jsr     setcol
            moveq.b #23,d0
            moveq.b #1,d1
            moveq.b #1,d2
            moveq.b #6,d3
            jsr     setcol
            moveq.b #27,d0
            moveq.b #1,d1
            moveq.b #1,d2
            moveq.b #6,d3
            jsr     setcol
            moveq.b #31,d0
            moveq.b #1,d1
            moveq.b #1,d2
            moveq.b #6,d3
            jsr     setcol
            move.b  #4,rndfu

    ; And now, at last, we can get on with the main loop.
main
            jsr     rnd                 ;Play with pseudo-random number
            jsr     ckmouse             ;If too near mouse, turn away.
            jsr     pushworm            ;Move worm ahead.
            jsr     putworm             ;Actual sprite moving code
            move.l  WPtr,a0             ;Hello? Is Bernie there?
            move.l  wd_UserPort(a0),a0  ;Hello? Is Bernie there?
            move.l  4,a6                ;Hello? Is Bernie there?
            jsr     _LVOGetMsg(a6)      ;Hi, this is Bernie, any messages
            tst.l   d0                  ;                         for me?
            bne     gobyebye    ;we got a message, which musta been CLOSE.
            move.l  GLib,a6
            jsr     _LVOWaitTOF(a6)     ;Wait 'til next frame
            jsr     _LVOWaitTOF(a6)     ;Blow off another frame
            subq.b  #1,rndfu
            bne.s   main
            move.b  #5,rndfu
            eor.b   #$FF,Random+1
            bra.s   main                ;an' do it again

    ;Rnd: does things to the random number.
rnd
            move.b  Random,d0
            move.b  Random+1,d1
            rol.b   #1,d0
            eor.b   d0,d1
            ror.b   #1,d1
            addq.b  #1,Random+1
            add.b   Random+1,d1
            bvc     .1
            addq.b  #1,Random+1
.1          move.b  d1,Random
            rts

    ;Pythag: calculates distance between mouse pointer and worm's head.
    ;Expects D0.w,D1.w=Px,Px; D2.w,D3.w=Wx,Wy; D4.b=vec;
    ;returns dist in D5.L
pythag
            move.w  d2,-(a7)    ;Preserve old worm X
            move.w  d3,-(a7)    ;Preserve old worm y
            add.b   d4,d4
            lea     xmov,a0
            add.w   0(a0,d4.w),d2   ;Get worm's future X
            add.w   32(a0,d4.w),d3  ;and y
            sub.w   d0,d2       ;Find X distance
            sub.w   d1,d3       ;Find Y distance
            muls.w  d2,d2       ;Apply the theorem of Pythagoras
            muls.w  d3,d3       ;...sort of...
            add.l   d2,d3
            bvc.s   .1          ;If overflow, then max out distance!
            move.l  #$ffffffff,d3
.1          move.l  d3,d5
            move.w  d3,(a7)+    ;Pop worm X
            move.w  d2,(a7)+    ;Pop worm Y
            rts

    ;Ckmouse: checks for mouse proximity. If too close, turn away; if not,
    ;         take a random turn.
ckmouse
            move.l  Scrn,a0
            move.w  sc_MouseX(a0),d0    ;Get mouse XY
            move.w  sc_MouseY(a0),d1
            move.w  XTable,d2       ;Get worm XY
            move.w  YTable,d3
            add.w   d0,d0           ;Bong mouse XY into "proper" resolution
            add.w   d1,d1
            move.b  HeadVec,d4
            bsr.s   pythag
            cmp.l   #16384,d5       ;Is worm in "danger" from the mouse?
            bge.s   RandMove        ;No - do a random move.
            move.b  d4,d6
            addq.b  #1,d4
            and.b   #15,d4
            bsr.s   pythag          ;Check result of a left turn
            move.l  d5,d7           ;Save result
            move.b  d6,d4
            subq.b  #1,d4
            and.b   #15,d4
            bsr.s   pythag          ;Now check a right turn
            cmp.l   d5,d7           ;So, which one will be closer to mouse?
            blt.s   .1
            addq.b  #1,d6           ;Left turn
            bra.s   .2
.1          subq.b  #1,d6           ;Right turn
.2          and.b   #15,d6
            move.b  d6,HeadVec      ;Save result and end
            rts

RandMove    move.b  Random,d1
            move.b  HeadVec,d0
            and.b   #15,d1
            cmp.b   #1,d1
            bgt.s   .r1
            addq.b  #1,d0   ;25% to turn each way, 50% to go straight.
            jmp .end
.r1         cmp.b   #3,d1
            bgt.s   .end
            subq.b  #1,d0
.end        and.b   #15,d0  ;Mask off high nybble
            move.b  d0,HeadVec
            rts

    ;Pushworm: pushes X and Y table along, then moves worm ahead.
pushworm
            lea     GLib,a0
            lea     GLib-2,a1
            moveq.b #100,d0
.loop       move.w  -(a1),-(a0)
            dbra    d0,.loop
            move.w  YTable+2,YTable
            clr.w   d0
            move.b  HeadVec,d0
            add.b   d0,d0
            move.w  XTable,d1
            move.w  YTable,d2
            lea     xmov,a0
            add.w   0(a0,d0.w),d1
            bpl.s   .1          ;Positive #?
            move.w  #0,d1       ;No - keep on-screen
            bsr.s   XBounce     ;And bounce.
.1          cmp.w   #1220,d1     ;Greater than right edge?
            ble.s   .2          ;Nope; do Y stuff.
            move.w  #1220,d1     ;Yes - keep on-screen
            bsr.s   XBounce
.2          add.w   32(a0,d0.w),d2
            bpl.s   .3          ;Positive #?
            move.w  #0,d2       ;No - keep on-screen
            bsr.s   YBounce     ;And bounce.
.3          cmp.w   #740,d2     ;Greater than bottom edge?
            ble.s   .4          ;Nope; plop values.
            move.w  #740,d2     ;Yes - keep on-screen
            bsr.s   YBounce
.4          move.w  d1,XTable
            move.w  d2,YTable
            lsr.w   #1,d0
            move.b  d0,HeadVec
            rts

    ;Bounce routines. Used when worm reaches edge of screen...
XBounce
            lea     xboing,a1
            lsr.b   #1,d0
            move.b  0(a1,d0.w),d0
            add.b   d0,d0
            rts
YBounce
            lea     yboing,a1
            lsr.b   #1,d0
            move.b  0(a1,d0.w),d0
            add.b   d0,d0
            rts

    ;Putworm: does the actual job of moving the sprites
putworm
            moveq.b #0,d7   ;loop counter
            moveq.l #0,d6   ;offset into tables
            lea     XTable,a3
            lea     ImgLst,a5
            move.l  GLib,a6
.loop       move.w  0(a3,d6),d0         ;Grab X value
            move.w  102(a3,d6),d1       ;Grab Y value
            lsr.w   #2,d0               ;Scale 'em down
            lsr.w   #2,d1
            move.l  (a5)+,a1            ;Point to SimpleSprite
            move.l  #0,a0
            jsr     _LVOMoveSprite(a6)  ;Do it!
            addq.b  #1,d7
            cmp.b   #6,d7               ;Loop stuff
            beq     endput
            add.w   #8,d6              ;Next table entrys
            bra     .loop               ;More sprites to move.
endput      rts

setcol      move.l  Vyew,a0
            jsr     _LVOSetRGB4(a6)
            rts

    ; Free up stuff and exit. You wouldn't -believe- how long it took to
    ; find the moron mistake in setting up for that CloseLibrary. I was
    ; passing a pointer to the "graphics.library" text instead of a ptr to
    ; graphicsbase... Stupid, stupid. Hell, it's my first Amy code, I'm
    ; allowed to make braindead mistakes like that. And I'll remember...
gobyebye
            move.l  ILib,a6
            move.l  WPtr,a0
            jsr     _LVOCloseWindow(a6)
closeint    move.l  4,a6
            move.l  ILib,a1
            jsr     _LVOCloseLibrary(a6)
losespr     move.l  GLib,a6             ;Get Graphics.lib again
            moveq.l #7,d6               ;Free sprites in reverse order
ls.1        move.b  d6,d0
            jsr     _LVOFreeSprite(a6)
            subq.l  #1,d6
            cmp.b   #1,d6
            bne.s   ls.1
            move.l  4,a6
            move.l  GLib,a1
            jsr     _LVOCloseLibrary(a6)
            rts

    section Data,data

XTable      ds.w    51
YTable      ds.w    51
GLib        ds.l    1
ILib        ds.l    1
DLib        ds.l    1
WPtr        ds.l    1
Scrn        ds.l    1
Vyew        ds.l    1
Random      ds.b    2
rndfu       ds.b    1
HeadVec     dc.b    5

ImgLst      dc.l    SS0,SS1,SS2,SS3,SS4,SS5

SS0             dc.l    head
                dc.w    $10
                dc.w    1
                dc.w    1
                dc.w    0

SS1             dc.l    body0
                dc.w    $10
                dc.w    1
                dc.w    1
                dc.w    0

SS2             dc.l    body1
                dc.w    $10
                dc.w    1
                dc.w    1
                dc.w    0

SS3             dc.l    body2
                dc.w    $10
                dc.w    1
                dc.w    1
                dc.w    0

SS4             dc.l    body3
                dc.w    $10
                dc.w    1
                dc.w    1
                dc.w    0

SS5             dc.l    body4
                dc.w    $10
                dc.w    1
                dc.w    1
                dc.w    0

xmov    dc.w    0,5,8,11,12,11,8,5,0,-5,-8,-11,-12,-11,-8,-5
ymov    dc.w    12,11,8,5,0,-5,-8,-11,-12,-11,-8,-5,0,5,8,11
xboing  dc.b    $0,$f,$e,$d,$c,$b,$a,$9,$8,$7,$6,$5,$4,$3,$2,$1
yboing  dc.b    $8,$7,$6,$5,$4,$3,$2,$1,$0,$f,$e,$d,$c,$b,$a,$9

gname   dc.b "graphics.library",0,0   ;2nd 0 word-aligns.
iname   dc.b "intuition.library",0
dname   dc.b "dos.library",0

windowdef
        dc.w    100,100     ;x,y
        dc.w    120,10      ;width, height
        dc.b    -1,-1       ;default pens
        dc.l    $200        ;CLOSEWINDOW
        dc.l    $e          ;WINDOWDRAG!WINDOWDEPTH!WINDOWCLOSE
        dc.l    0,0         ;egad! no gads, no checkmark
        dc.l    wintitle    ;->title
        dc.l    0,0         ;no screen, no bitmap
        dc.w    0,0,0,0     ;minsize. no wife, no horse, no moustache.
        dc.w    $1          ;WBENCHSCREEN
wintitle    dc.b    "Worm",0

    section Images,data_c
head    dc.l  $00000000  ; Remember it's exactly $10 lines high.
        dc.l  $000007c0
        dc.l  $00001ff0
        dc.l  $00003ff8
        dc.l  $06C0793c
        dc.l  $0FE4701c
        dc.l  $0FE2f45e
        dc.l  $1FF6e44e
        dc.l  $9EF2e10e
        dc.l  $4016fffe
        dc.l  $A00Efffe
        dc.l  $541C7ffc
        dc.l  $6ABC7ffc
        dc.l  $35F83ff8
        dc.l  $1FF01ff0
        dc.l  $07C007c0
        dc.l  $00000000
imagelen    equ *-head

body0   dc.l  $00000000
        dc.l  $000007c0
        dc.l  $05001af0
        dc.l  $0E803178
        dc.l  $1D0862fc
        dc.l  $280457fc
        dc.l  $100Aeffe
        dc.l  $0006fffe
        dc.l  $800Afffe
        dc.l  $4016fffe
        dc.l  $A02Efffe
        dc.l  $555C7ffc
        dc.l  $6ABC7ffc
        dc.l  $35F83ff8
        dc.l  $1FF01ff0
        dc.l  $07C007c0
        dc.l  $00000000

body1   dc.l  $00000000
        dc.l  $000007c0
        dc.l  $05001af0
        dc.l  $0E803178
        dc.l  $1D0862fc
        dc.l  $280457fc
        dc.l  $100Aeffe
        dc.l  $0006fffe
        dc.l  $800Afffe
        dc.l  $4016fffe
        dc.l  $A02Efffe
        dc.l  $555C7ffc
        dc.l  $6ABC7ffc
        dc.l  $35F83ff8
        dc.l  $1FF01ff0
        dc.l  $07C007c0
        dc.l  $00000000

body2   dc.l  $00000000
        dc.l  $000007c0
        dc.l  $05001af0
        dc.l  $0E803178
        dc.l  $1D0862fc
        dc.l  $280457fc
        dc.l  $100Aeffe
        dc.l  $0006fffe
        dc.l  $800Afffe
        dc.l  $4016fffe
        dc.l  $A02Efffe
        dc.l  $555C7ffc
        dc.l  $6ABC7ffc
        dc.l  $35F83ff8
        dc.l  $1FF01ff0
        dc.l  $07C007c0
        dc.l  $00000000

body3   dc.l  $00000000
        dc.l  $000007c0
        dc.l  $05001af0
        dc.l  $0E803178
        dc.l  $1D0862fc
        dc.l  $280457fc
        dc.l  $100Aeffe
        dc.l  $0006fffe
        dc.l  $800Afffe
        dc.l  $4016fffe
        dc.l  $A02Efffe
        dc.l  $555C7ffc
        dc.l  $6ABC7ffc
        dc.l  $35F83ff8
        dc.l  $1FF01ff0
        dc.l  $07C007c0
        dc.l  $00000000

body4   dc.l  $00000000
        dc.l  $000007c0
        dc.l  $05001af0
        dc.l  $0E803178
        dc.l  $1D0862fc
        dc.l  $280457fc
        dc.l  $100Aeffe
        dc.l  $0006fffe
        dc.l  $800Afffe
        dc.l  $4016fffe
        dc.l  $A02Efffe
        dc.l  $555C7ffc
        dc.l  $6ABC7ffc
        dc.l  $35F83ff8
        dc.l  $1FF01ff0
        dc.l  $07C007c0
        dc.l  $00000000

body5   dc.l  $00000000
        dc.l  $000007c0
        dc.l  $05001af0
        dc.l  $0E803178
        dc.l  $1D0862fc
        dc.l  $280457fc
        dc.l  $100Aeffe
        dc.l  $0006fffe
        dc.l  $800Afffe
        dc.l  $4016fffe
        dc.l  $A02Efffe
        dc.l  $555C7ffc
        dc.l  $6ABC7ffc
        dc.l  $35F83ff8
        dc.l  $1FF01ff0
        dc.l  $07C007c0
        dc.l  $00000000

body6   dc.l  $00000000
        dc.l  $000007c0
        dc.l  $05001af0
        dc.l  $0E803178
        dc.l  $1D0862fc
        dc.l  $280457fc
        dc.l  $100Aeffe
        dc.l  $0006fffe
        dc.l  $800Afffe
        dc.l  $4016fffe
        dc.l  $A02Efffe
        dc.l  $555C7ffc
        dc.l  $6ABC7ffc
        dc.l  $35F83ff8
        dc.l  $1FF01ff0
        dc.l  $07C007c0
        dc.l  $00000000
