org $1000 ; Speed equ 6000 ; Delay value bra Start ; Init_Maze defs 4 ; Init maze etc Cls defs 4 ; Clear screen Scan_Kbd defs 4 ; Read keys IM_Fill defs 4 ; Fill area Random defs 4 ; Random no Rand_Less_D0 defs 4 ; 0 .. d0 Out_It defs 4 ; Write to screen d6,d7 Show_Window defs 4 ; Page display Set_Display defs 4 ; Select display (d0) Set_Display_0 defs 4 Set_Display_1 defs 4 kZ equ $2C ; IBM key codes kX equ $2D ; kN equ $31 ; kM equ $32 ; kQ equ $10 ; kA equ $1E ; kO equ $18 ; kC equ $2E ; kL equ $26 ; kF equ $21 ; kK equ $25 ; kH equ $23 ; kD equ $20 ; kSpace equ $39 ; kShiftL equ $2A ; kShiftR equ $36 ; kEsc equ $01 ; kF1 equ $3B ; kF2 equ $3C ; kF3 equ $3D ; org $0 ; Monster offsets mDelay defs 2 ; mSpeed defs 2 ; mpMaze defs 4 ; mdHoriz defs 2 ; Constants for projectiles mdDiag defs 2 ; m_e defs 2 ; m_c1 defs 2 ; m_c2 defs 2 ; mpTarget defs 4 ; mRange defs 2 ; mdHoriz_2 defs 2 ; Constants for projectiles mdDiag_2 defs 2 ; m_e_2 defs 2 ; m_c1_2 defs 2 ; m_c2_2 defs 2 ; mpTarget_2 defs 4 ; mRange_2 defs 2 ; mX defs 2 ; Maze X mY defs 2 ; Maze Y mpDraw defs 4 ; mpUndraw defs 4 ; mpMove defs 4 ; mWounds defs 2 ; mWounds_A defs 2 ; mMagic defs 2 ; mMagic_A defs 2 ; mDirection defs 1 ; mFlags defs 1 ; ; BIT 0 = Moved flag on Man ; BIT 6 = Steaming ; BIT 7 = Dead mChar defs 2 ; mRandomness defs 1 ; mDoorCnt defs 1 ; Delay to close door mpDoor defs 4 ; Ptr to door mpScreen defs 4 ; Man pData mpKbd defs 4 ; " " mNumber defs 1 ; Which man mSteamCnt defs 1 ; Time to steam mScore defs 2 ; Score mScore_A defs 2 ; Demand score mProjCnt_0 defs 2 ; No. proj aimed at it mProjCnt_1 defs 2 ; mProjCnt_M defs 2 ; mnSwag defs 2 ; No. of objects carried mSwag defs 16 ; Objects carried lMon equ * ; org $0 ; Projectile offsets ppNext defs 4 ; Ptr to next proj pDelay defs 1 ; pSpeed defs 1 ; pSpeedDel defs 1 pFire_pCnt defs 1 ; 0,1 = Man : 2 = Monster ppSpeedTab defs 4 ; ptr to speed table ppMove defs 4 ; Move routine ppMaze defs 4 ; pdHoriz defs 2 ; pdDiag defs 2 ; p_e defs 2 ; p_c1 defs 2 ; p_c2 defs 2 ; ppTarget defs 4 ; pTarget "thing" pRange defs 2 ; Lifetime ppOwner defs 4 ; pOwner pStart_Cnt defs 1 ; Delay to active pUnderChar defs 1 ; Char under proj pFlags defs 1 ; Type flags pChar defs 1 ; lProj equ * org $0 ; Sight offsets sdHoriz defs 2 ; sdDiag defs 2 ; s_e defs 2 ; s_c1 defs 2 ; s_c2 defs 2 ; spTarget defs 4 ; sRange defs 2 ; lSight equ * SM_Start equ $10000 ; Below BM BM_Start equ $11000+BM_Max_X ; Big_Maze TL BM_Max_X equ 512 ; No. cells BM_Max_Y equ 401 ; (See Find_Blank) BM_Start_TLM equ BM_Start+7*BM_Max_X+7 ; BM_Start_TRM equ BM_Start_TLM+47*7 ; BM_Start_BLM equ BM_Start+48*7*BM_Max_X+7 ; BM_Start_BRM equ BM_Start_BLM+47*7 ; BM_Start_Maze equ BM_Start+8*7*BM_Max_X+8*7 ; nTreasure equ 580 ; Same density as halls nMagic equ 580 ; nMons equ 400 ; nProj equ 300 ; X_Range equ 40 ; Y_Range equ 40 ; Light_Dam equ 17 Fire_Dam equ 6 Dead_Magic equ $E0 ; Dead thing chars Dead_Dead_Magic equ $F6 ; Dead_Sword equ $DE ; Dead_Arrow equ $DF ; Dead_Man equ $F4 ; $F5 ; Cross ? SteamTime equ 0 ; Time to steam org $2000 ; Start moveq #1,d0 ; Select display 0 bsr Set_Display ; bsr Init_Maze ; Draw maze, etc move.l #-1,ScreenX_1 ; Load X,Y with illegal move.l #-1,ScreenX_2 ; bsr Init_Treasure ; Place treasure bsr Init_Magic ; Place magic bsr Init_Things ; Place monsters bsr Init_Projectiles ; Clear projectiles bsr Set_Display_0 ; bsr Init_Status ; "Score,wounds & magic" ; bsr Set_Display_1 ; ; bsr Init_Status ; "Score,wounds & magic" bsr Init_Sight ; Can't see anything Game_Lp bsr Random ; Randomise Quick rand xor d1,QRand_Seed ; swap d1 ; xor d1,QRand_Ptr ; bsr Scan_Kbd ; Get ptr (a0) move #Speed,d0 ; Slow tst.b kF1[a0] ; Slow ? bne.s Set_Pause ; Yes move #3200,d0 ; Normal tst.b kF2[a0] ; Normal ? bne.s Set_Pause ; Yes move #0,d0 ; Fast tst.b kF3[a0] ; Fast ? bne.s Set_Pause ; Yes move cSpeed,d0 ; Last Set_Pause move d0,cSpeed ; Pause Pause_Lp dbra d0,Pause_Lp ; Pause_Done bsr Scan_Kbd ; Get keys bsr Drive_About ; Set man move flags bsr Drive_Status ; Drive status displays bsr Move_Things ; Move monsters bsr Move_Projectiles ; Move projectiles bra.s Game_Lp ; Loop Init_Status lea Out_It,a6 ; Output routine move #24,d7 ; Y move #0,d6 ; X lea Stat_Data,a0 ; Data area IS_Lp move.b [a0]+,d0 ; Get byte beq.s IS_X ; End? yes jsr [a6] ; Display it addq #1,d6 ; Step X bra.s IS_Lp ; Loop IS_X rts ; Done Drive_Status lea Out_It,a6 ; Output routine bsr Set_Display_0 ; move.l #Monsters,a0 ; pMan 0 DS_Doit move #24,d7 ; Y move mScore[a0],d0 ; Get score cmp mScore_A[a0],d0 ; Same ? beq.s DS_Wounds ; Yes, ignore move d0,mScore_A[a0] ; Update actual score move #5,d6 ; X bsr.s DS_Score ; Print d0 in dec DS_Wounds move mWounds[a0],d0 ; Get score cmp mWounds_A[a0],d0 ; Same ? beq.s DS_Magic ; Yes, ignore move d0,mWounds_A[a0] ; Update move #18,d6 ; X bsr.s DS_BarGraph ; Print d0 as a bar DS_Magic move mMagic[a0],d0 ; Get score cmp mMagic_A[a0],d0 ; Same ? beq.s DS_Done ; Yes, ignore move d0,mMagic_A[a0] ; Update move #32,d6 ; X bsr.s DS_BarGraph ; Print d0 as a bar DS_Done rts ; d0 0 .. 319 to 0 .. 55 DS_BarGraph mulu #56,d0 ; Scale to new length divu #320,d0 ; move d0,d1 ; Length move #7-1,d2 ; Loop cnt move #$F0,d0 ; Full char DS_BG_Lp sub #8,d1 ; Full char ? bmi.s DS_BG_1 ; No, jump bsr.s DS_Print ; Display it dbf d2,DS_BG_Lp ; Loop rts ; Done DS_BG_1 add.b d1,d0 ; Calc char DS_BG_Lp1 bsr.s DS_Print ; Display it move #$E8,d0 ; Blank char dbf d2,DS_BG_Lp1 ; Loop rts ; Done DS_Score move.b #" ",d1 ; Char to print ext.l d0 ; Loose top bits divu #10000,d0 ; Try first bsr.s DS_S_1 ; divu #1000,d0 ; Try first bsr.s DS_S_1 ; divu #100,d0 ; Try first bsr.s DS_S_1 ; divu #10,d0 ; Try first bsr.s DS_S_1 ; or.b #"0",d0 ; Last digit DS_Print jsr [a6] ; Output it addq #1,d6 ; Step X rts ; Done DS_S_1 beq.s DS_Zero ; Print " " or "0" move.b #"0",d1 ; Zeros now on or.b #"0",d0 ; Show no. bsr.s DS_Print ; clr d0 ; swap d0 ; Restore remainder rts ; Done DS_Zero move.b d1,d0 ; Zero char bsr.s DS_Print ; clr d0 ; swap d0 ; Restore remainder rts ; Done Init_Sight move #$7F,Sight_WS_0+sRange.l; Sentinel move #$7F,Sight_WS_1+sRange.l; rts ; ;Look move.l #Monsters,a5 ; pMan ; move.l a5,a6 ; pFirst monster Look move.l #Sight_WS_0,a4 ; Monster vectors move.w #0,a2 ; Offset to proj const store tst.b mNumber[a6] ; beq.s Look_0 ; move.l #Sight_WS_1,a4 ; move.w #mdHoriz_2-mdHoriz,a2 ; Look_0 move.l a6,a5 ; pMan move.l #Monsters,a6 ; pMonsters move #$7F,sRange[a4] ; Sentinel move #nMons,d7 ; No. to scan move.l mpMaze[a5],d6 ; pMan move.l d6,a0 ; pStart of line sub.l #BM_Start,d6 ; move d6,d5 ; X and #$1FF,d5 ; ror.l #5,d6 ; Y ror.l #4,d6 ; move d5,d3 ; X sub #X_Range,d3 ; Min X add #X_Range,d5 ; Max X move d6,d4 ; Y sub #Y_Range,d4 ; Min Y add #Y_Range,d6 ; Max Y Look_Lp cmp.l a5,a6 ; Same one ? beq Look_Next ; Yes, do next btst #7,mFlags[a6] ; Dead ? bne Look_Next ; Yes, do next cmp mX[a6],d3 ; Min X bgt.s Look_Next ; Fail cmp mX[a6],d5 ; Max X blt.s Look_Next ; Fail cmp mY[a6],d4 ; Min Y bgt.s Look_Next ; Fail cmp mY[a6],d6 ; Max Y blt.s Look_Next ; Fail move.l mpMaze[a6],a1 ; a0..A1 movem.l d3-a0/a5,-[sp] move.l a5,mpTarget[a6,a2.w] ; Flag target of projectile move #$7F,mRange[a6,a2.w] ; move.l a6,a5 ; Ptr to monsters data move.w a2,-[sp] ; Save number offset bsr Look_Line ; Can see it ? move a2,d4 ; dHoriz move.w [sp]+,a2 ; Restore offset to a1 tst.b d5 ; Seen ? bne.s Look_Next1 ; No, Try next ; Modify a5 app move d6,m_e[a5,a2.w] ; Save values move d6,s_e[a4] ; move d1,m_c1[a5,a2.w] ; move d1,s_c1[a4] ; move d3,m_c2[a5,a2.w] ; move d3,s_c2[a4] ; move d4,sdHoriz[a4] ; neg d4 ; move d4,mdHoriz[a5,a2.w] ; move a3,d4 ; dDiag move d4,sdDiag[a4] ; neg d4 ; move d4,mdDiag[a5,a2.w] ; move d7,sRange[a4] ; Distance move d7,mRange[a5,a2.w] ; move.l a6,spTarget[a4] ; Monster add.l #lSight,a4 ; Step to next move #$7F,sRange[a4] ; Sentinel Look_Next1 movem.l [sp]+,d3-a0/a5 Look_Next add.l #lMon,a6 ; Step ptr dbf d7,Look_Lp ; Next one rts ; Done Look_Line move.l a0,d0 ; Start point sub.l #BM_Start,d0 ; move.l d0,d1 ; and #$1FF,d0 ; X ror.l #5,d1 ; ror.l #4,d1 ; Y move.l a1,d2 ; End point sub.l #BM_Start,d2 ; move.l d2,d3 ; and #$1FF,d2 ; X2 ror.l #5,d3 ; ror.l #4,d3 ; Y2 Line_D0D4 move.l #1,a2 ; dHoriz { right } move.l #512,a3 ; dVert { down } sub d0,d2 ; dX bpl.s Line_A ; dX +ve neg d2 ; Make dX +ve move a2,d7 ; neg d7 ; Step left move d7,a2 ; Line_A sub d1,d3 ; dY bpl.s Line_B ; dY +ve neg d3 ; Make dY +ve move a3,d7 ; neg d7 ; Step down move d7,a3 ; Line_B cmp d3,d2 ; dX > dY ? bhi Line_C ; Yes, continue move.l a2,d0 ; Swap dHoriz move.l a3,a2 ; dVert move.l d0,a3 ; move d2,d0 ; Swap dX move d3,d2 ; dY move d0,d3 ; Line_C add.l a2,a3 ; Make dDiag add d3,d3 ; 2dY { c2 } move d3,d0 ; 2dY sub d2,d0 ; 2dY - dX { e } move d0,d1 ; 2dY - dX sub d2,d1 ; 2dY - 2dX { c1 } move d0,d6 ; Save d0 move d2,d7 ; d2 clr d4 ; 0 subq #1,d2 ; Don't go whole way Line_Lp move.b [a0],d5 ; Test it cmp.b #" ",d5 ; Space ? beq.s Line_Lp_A ; Yes, Ok and.b #$FE,d5 ; Door ? cmp.b #$DC,d5 ; beq.s Line_Fail ; Stopped and #$F0,d5 ; Type cmp.b #$90,d5 ; Wall ? beq.s Line_Fail ; Stopped Line_Lp_A cmp d4,d0 ; e > 0 bgt.s Line_Lp1 ; add d3,d0 ; e := e + 2dY add.l a2,a0 ; dHoriz dbf d2,Line_Lp ; Loop clr.b d5 ; Line clear Line_Fail rts ; OK Line_Lp1 add d1,d0 ; e := e + 2dY - 2dX add.l a3,a0 ; dDiag dbf d2,Line_Lp ; Loop clr.b d5 ; Line clear MP_Exit rts ; OK Move_Projectiles lea pFirst_Proj,a1 ; ^ Old ptr move.l pFirst_Proj,d0 ; Get ptr MP_Lp tst.l d0 ; Valid ? beq.s MP_Exit ; No. move.l d0,a5 ; Ptr subq.b #1,pDelay[a5] ; Dec count bne.s MP_Next ; Go away tst.b pStart_Cnt[a5] ; Active yet ? beq.s MP_Active ; Yes subq.b #1,pStart_Cnt[a5]; No MP_Active subq.b #1,pSpeedDel[a5]; Time to change speed ? bne.s MP_doit ; No, carry on move.l ppSpeedTab[a5],a0 ; Yes, get next speed move.b [a0]+,pSpeedDel[a5]; Next phase length move.b [a0]+,pSpeed[a5] ; cnt beq.s MP_Kill_Und ; Done move.l a0,ppSpeedTab[a5] ; Save ptr MP_doit move.b pSpeed[a5],pDelay[a5] ; Set up cnt move.l ppMaze[a5],a0 ; Get pMaze move.b pUnderChar[a5],d0 ; Get char under proj beq.s MP_Undraw ; None, don't replace move.b d0,[a0] ; Replace old MP_Undraw move.b [a0],d0 ; Replace on screen bsr Show_VDU ; and.b #$FE,d0 ; Door ? cmp.b #$DC,d0 ; beq.s MP_Kill ; Yes, kill proj MP_Move move.l ppMove[a5],a6 ; Jump to move proj jmp [a6] ; MP_Done move.b [a0],d0 ; Get char under proj cmp.b #" ",d0 ; Blank ? beq.s MP_Done1 ; Yes, plant proj clr.b pUnderChar[a5] ; Don't redraw MP_Next move.l ppNext[a5],d0 ; Get next proj lea ppNext[a5],a1 ; ^Old Ptr bra MP_Lp ; Loop MP_Done1 move.b d0,pUnderChar[a5] ; Save it move.b pChar[a5],d0 ; Get new char move.b d0,[a0] ; Store proj bsr Show_VDU ; Display it bra.s MP_Next ; Get next proj MP_Kill_Und move.b pUnderChar[a5],d0 ; Get char under proj beq.s MP_Kill ; None, don't replace move.l ppMaze[a5],a0 ; Get pMaze move.b d0,[a0] ; Replace old char bsr Show_VDU ; Remove on screen MP_Kill move.l ppTarget[a5],a0 ; Dec ProjCnt clr.w d0 ; Get cnt move.b pFire_pCnt[a5],d0 ; Which cnt ? add.b d0,d0 ; 0 , 2 or 4 subq #1,mProjCnt_0[a0,d0.w] ; No. fired at it move.l ppNext[a5],d0 ; Get ptr move.l d0,[a1] ; Update old ptr bsr Kill_Proj ; Kill this one bra MP_Lp ; Loop Move_Light_E move.b 4,d4 ; Max bounce count Move_Light subq.b #1,d4 ; Bounce-out ? beq MP_Kill ; Yes move p_e[a5],d0 ; Get e cmp #0,d0 ; e > 0 bgt.s ML_Line_1 ; add p_c2[a5],d0 ; e := e + 2dY move pdHoriz[a5],d1 ; ext.l d1 ; Sign extend add.l d1,a0 ; dHoriz bra.s ML_Line_Done ; OK ML_Line_1 add p_c1[a5],d0 ; e := e + 2dY - 2dX move pdDiag[a5],d1 ; ext.l d1 ; Sign extend add.l d1,a0 ; dDiag ML_Line_Done move d0,p_e[a5] ; Save e move.b [a0],d5 ; Get char cmp.b #" ",d5 ; Space ? beq.s ML_A ; Yes, Ok and.b #$FE,d5 ; Door ? cmp.b #$DC,d5 ; beq.s ML_Bounce ; Bounce and.b #$F8,d5 ; Monster ? cmp.b #$D0,d5 ; beq.s ML_Hit ; cmp.b #$A8,d5 ; Man ? beq.s ML_Hit ; and.b #$F0,d5 ; Type cmp.b #$90,d5 ; Wall ? beq.s ML_Bounce ; Bounce ML_A move.l a0,ppMaze[a5] ; Save ptr move.b pChar[a5],d0 ; add.b #1,d0 ; and.b #$01,d0 ; or.b #$A2,d0 ; move.b d0,pChar[a5] ; bra MP_Done ; Display it ML_Hit move.l ppOwner[a5],a1 ; Hit firer ? move.l mpMaze[a1],d0 ; cmp.l a0,d0 ; bne.s ML_H_1 ; Yes tst.b pStart_Cnt[a5] ; Active yet ? bne.s ML_A ; No, ignore hit ML_H_1 moveq #Light_Dam,d1 ; Damage move.b #Dead_Magic,d0 ; Char for death bsr DoDamage ; a1 := pThing bra ML_A ; Done ML_Bounce bsr.s Bounce ; Reflect off a wall bra Move_Light ; Try again Bounce move.l ppMaze[a5],a0 ; Restore ptr move pdHoriz[a5],d0 ; Horiz offset move.b 0[a0,d0.w],d5 ; Read char bsr.s TestWall ; Wall ? bne.s B_1 ; No neg pdHoriz[a5] ; Reflect off of it B_1 tst p_c2[a5] ; Horizontal steps only ? beq.s B_X ; Yes, don't reflect diags move pdDiag[a5],d1 ; Get Diag offset clr.b d5 ; Clear flag move #512,d2 ; Vert step btst #15,d1 ; Step up ? beq.s B_1a ; Yes neg d2 ; No, step down B_1a move.b 0[a0,d2.w],d5 ; Try stepping vert bsr.s TestWall ; Hit wall ? bne.s B_1b ; No,try horiz st.b d0 ; Yes, assert altered sub d2,d1 ; Negate this part of diag sub d2,d1 ; B_1b move d1,d2 ; Horiz step ext d2 ; Make +-1 move.b 0[a0,d2.w],d5 ; Try stepping horiz bsr.s TestWall ; Hit wall ? bne.s B_1c ; No,set if vert st.b d0 ; Yes, assert altered sub d2,d1 ; Negate this part of diag sub d2,d1 ; B_1c tst.b d0 ; Did either work ? beq.s B_2 ; No, reflect both move d1,pdDiag[a5] ; Save reflected step B_X rts ; Done B_2 neg pdDiag[a5] ; Reflect both neg pdHoriz[a5] ; rts ; Done TestWall and.b #$FE,d5 ; Door ? cmp.b #$DC,d5 ; beq.s TW_Exit ; Yes, Ok and #$F0,d5 ; Type cmp.b #$90,d5 ; Wall ? TW_Exit rts ; Return Z Move_Fire_E move.b 4,d4 ; Max bounce count Move_Fire subq.b #1,d4 ; Bounce-out ? beq MP_Kill ; Yes move p_e[a5],d0 ; Get e cmp #0,d0 ; e > 0 bgt.s MF_Line_1 ; add p_c2[a5],d0 ; e := e + 2dY move pdHoriz[a5],d1 ; ext.l d1 ; Sign extend add.l d1,a0 ; dHoriz bra.s MF_Line_Done ; OK MF_Line_1 add p_c1[a5],d0 ; e := e + 2dY - 2dX move pdDiag[a5],d1 ; ext.l d1 ; Sign extend add.l d1,a0 ; dDiag MF_Line_Done move d0,p_e[a5] ; Save e move.b [a0],d5 ; Get char cmp.b #" ",d5 ; Space ? beq.s MF_A ; Yes, Ok and.b #$FE,d5 ; Door ? cmp.b #$DC,d5 ; beq MF_Bounce ; Bounce and.b #$F8,d5 ; Monster ? cmp.b #$D0,d5 ; beq.s MF_Hit ; cmp.b #$A8,d5 ; Man ? beq.s MF_Hit ; and #$F0,d5 ; Type cmp.b #$90,d5 ; Wall ? beq.s MF_Bounce ; Bounce MF_A move.l a0,ppMaze[a5] ; Save ptr move.b pChar[a5],d0 ; add.b #1,d0 ; and.b #$03,d0 ; or.b #$A4,d0 ; move.b d0,pChar[a5] ; bra MP_Done ; Display it MF_Hit move.l ppOwner[a5],a1 ; Hit firer ? move.l mpMaze[a1],d0 ; cmp.l a0,d0 ; bne.s MF_H_1 ; Yes tst.b pStart_Cnt[a5] ; Active yet ? bne.s MF_A ; No, ignore hit MF_H_1 movem.l a2,-[sp] ; moveq #Fire_Dam,d1 ; Damage move.b #Dead_Magic,d0 ; Char for death bsr DoDamage ; move.l ppTarget[a5],a2 ; Get current target clr.w d0 ; Get cnt move.b pFire_pCnt[a5],d0 ; Which cnt ? add.b d0,d0 ; 0 , 2 or 4 subq #1,mProjCnt_0[a2,d0.w] ; No. fired at it move.l a1,ppTarget[a5] ; Now aimed at addq #1,mProjCnt_0[a1,d0.w] ; No. fired at it movem.l [sp]+,a2 ; bra MF_A ; Done MF_Bounce move.l ppMaze[a5],a0 ; Get ptr movem.l a2/a3,-[sp] movem.l a0/a1/a5,-[sp] ; Save regs move.l ppTarget[a5],a1 ; Ptr to target thing btst #7,mFlags[a1] ; Alive ? bne.s MF_Reflect ; No move.l mpMaze[a1],a1 ; Ptr to where it is cmp.l a1,a0 ; On target beq.s MF_Reflect ; Just bounce bsr Look_Line ; Can we see it ? movem.l [sp]+,a0/a1/a5 ; Restore regs tst.b d5 ; bne MF_Bounce_Fail ; No, end move.l #Fire_Tab,ppSpeedTab[a5] ; Reset speed move d6,p_e[a5] ; Store new vectors move d1,p_c1[a5] ; move d3,p_c2[a5] ; move a2,pdHoriz[a5] ; move a3,pdDiag[a5] ; movem.l [sp]+,a2/a3 bra Move_Fire ; Try again MF_Reflect movem.l [sp]+,a0/a1/a5 ; Restore regs MF_Bounce_Fail bsr Bounce ; Merely bounce off wall movem.l [sp]+,a2/a3 ; Restore regs bra Move_Fire ; Done DoDamage movem.l a0/a2/d2/d7,-[sp] ; Save regs a5 = pProj move.b d0,d7 ; Dead char move.b [a0],d0 ; Get char and.b #$F0,d0 ; Man or monster ? cmp.b #$A0,d0 ; bne.s DD_Mon ; Monster btst #0,[a0] ; Bottom of man ? beq.s DD_Mon ; No, right address lea -512[a0],a0 ; Get addr of top half DD_Mon move.l #Monsters,a1 ; Ptr to man data move.l a0,d0 ; Address of thing move #nMons,d2 ; Compare cnt move #lMon,a2 ; Length of entry DD_Find cmp.l mpMaze[a1],d0 ; Same place ? beq.s DD_a ; Found add.l a2,a1 ; Step ptr dbf d2,DD_Find ; Loop bra.s DD_X ; Fail DD_a btst #7,mFlags[a1] ; Killed ? bne.s DD_X ; Yes, ignore move.l a1,d0 ; Firer ? cmp.l ppOwner[a5],d0 ; bne.s DD_b ; No tst.b pStart_Cnt[a5] ; Active yet ? bne.s DD_X ; No, ignore impact DD_b move mWounds[a1],d0 ; Get wounds add d1,d0 ; Do damage move d0,mWounds[a1] ; cmp #323,d0 ; Killed ? blt.s DD_X ; No move #323,mWounds[a1] ; Max wounds bset #7,mFlags[a1] ; Flag dead move.l ppOwner[a5],a2 ; Add its score to firer btst #7,mFlags[a2] ; Firer alive ? bne.s DontScore ; No, ignore move mScore[a1],d0 ; Get its score add d0,mScore[a2] ; DontScore move.l mpMaze[a1],a0 ; Get pMaze btst #1,mNumber[a1] ; Man ? beq.s DD_Kill_Man ; Yes move.b d7,[a0] ; Replace char move.b d7,d0 ; Display on screen bsr Show_VDU ; cmp.b #Dead_Magic,d0 ; Steam ? bne.s DD_X ; No, done move.b d0,mChar[a1] ; First char bset #6,mFlags[a1] ; Flag steaming move.b #SteamTime,mSteamCnt[a1] ; Time to steam DD_X movem.l [sp]+,a0/a2/d2/d7 ; Pop regs rts ; DD_Kill_Man move.b #Dead_Man,d0 ; Display cross move.b d0,[a0] ; bsr Show_VDU ; add.l #BM_Max_X,a0 ; move.b #Dead_Man+1,d0 ; move.b d0,[a0] ; bsr Show_VDU ; bra.s DD_X ; Add_Lightning movem.l a0/a1/a5,-[sp] bsr New_Proj ; a5 := new proj beq.s AL_Fail ; None, fail move.l a6,ppOwner[a5] ; Ptr to firer move.b mNumber[a6],pFire_pCnt[a5] ; 0,1 or 2 move.b #1,pDelay[a5] ; Speeds move.b #1,pSpeedDel[a5] ; Time out immed. move.l #Light_Tab,ppSpeedTab[a5] ; Table clr.b pUnderChar[a5] ; Char being replaced move.b #3,pStart_Cnt[a5] ; Delay till armed move.l mpMaze[a6],ppMaze[a5] ; Ptr to maze move sdHoriz[a0],pdHoriz[a5] move sdDiag[a0],pdDiag[a5] move s_e[a0],p_e[a5] move s_c1[a0],p_c1[a5] move s_c2[a0],p_c2[a5] move.l spTarget[a0],a0 move.l a0,ppTarget[a5] clr.w d0 ; Get cnt move.b pFire_pCnt[a5],d0 ; Which cnt ? add.b d0,d0 ; 0 , 2 or 4 addq #1,mProjCnt_0[a0,d0.w] ; No. fired at it move.l #Move_Light_E,ppMove[a5] ; Move routine AL_Fail movem.l [sp]+,a0/a1/a5 rts Add_Fire movem.l a0/a1/a5,-[sp] bsr New_Proj ; a5 := new proj beq.s AL_Fail ; None, fail move.l a6,ppOwner[a5] ; Ptr to firer move.b mNumber[a6],pFire_pCnt[a5] ; 0,1 or 2 move.b #1,pDelay[a5] ; Speeds move.b #1,pSpeedDel[a5] ; Time out immed. move.l #Fire_Tab,ppSpeedTab[a5] ; Table clr.b pUnderChar[a5] ; Char being replaced move.b #3,pStart_Cnt[a5] ; Delay till armed move.l mpMaze[a6],ppMaze[a5] ; Ptr to maze move sdHoriz[a0],pdHoriz[a5] move sdDiag[a0],pdDiag[a5] move s_e[a0],p_e[a5] move s_c1[a0],p_c1[a5] move s_c2[a0],p_c2[a5] move.l spTarget[a0],a0 move.l a0,ppTarget[a5] clr.w d0 ; Get cnt move.b pFire_pCnt[a5],d0 ; Which cnt ? add.b d0,d0 ; 0 , 2 or 4 addq #1,mProjCnt_0[a0,d0.w] ; No. fired at it move.l #Move_Fire_E,ppMove[a5] ; Move routine movem.l [sp]+,a0/a1/a5 rts Light_Tab defb 2,5 defb 4,6 defb 6,7 defb 8,8 defb 10,9 defb 9,10 defb 8,12 defb 7,14 defb 6,16 defb 5,18 defb 4,20 defb 3,22 defb 2,24 defb 1,26 defb 0,0 Fire_Tab defb 2,8 defb 4,9 defb 5,10 defb 4,11 defb 3,12 defb 2,13 defb 2,14 defb 3,15 defb 4,17 defb 5,19 defb 6,21 defb 5,22 defb 4,23 defb 0,0 Move_Things move #nMons,d5 ; Cnt + 1 man move.l #Monsters,a6 ; Ptr MT_Lp subq #1,mDelay[a6] ; Dec count bne.s MT_Next ; Don't move yet btst #7,mFlags[a6] ; Dead ? bne.s MT_Next_D ; Yes, ignore move.w mSpeed[a6],mDelay[a6] move.l mpMove[a6],a0 ; Move it jsr [a0] ; MT_Next add.l #lMon,a6 ; Step ptr dbf d5,MT_Lp ; Lp rts ; Done MT_Next_D btst #6,mFlags[a6] ; Steaming ? beq.s MT_Next ; No. move.b mChar[a6],d0 ; Next char addq.b #1,d0 ; and.b #%11,d0 ; or.b #Dead_Magic,d0 ; move.b d0,mChar[a6] ; move.l mpMaze[a6],a0 ; Replace move.b d0,[a0] ; bsr Show_VDU ; and.b #%11,d0 ; Full cycle ? bne.s Steam_Exit ; No add.l #BM_Max_X,a0 ; Look down move.b [a0],d0 ; cmp.b #$CF,d0 ; Full bottle ? beq.s Steam_Exit ; Yes, ignore and.b #$F0,d0 ; What is it ? cmp.b #$C0,d0 ; Bottle ? bne.s Steam_Exit ; No move.b [a0],d0 ; addq.b #1,d0 ; Step it move.b d0,[a0] ; bsr Show_VDU ; Display change Steam_Exit clr.w d0 ; move.b mSteamCnt[a6],d0 ; Step cnt addq.b #1,d0 ; btst #7,d0 ; bne.s Stop_Steaming ; Done move.b d0,mSteamCnt[a6] ; Save move mSpeed[a6],mDelay[a6] asr #1,d0 add d0,mDelay[a6] bra.s MT_Next ; Stop_Steaming move.l mpMaze[a6],a0 ; New char move.b #Dead_Dead_Magic,d0 ; move.b d0,[a0] ; bsr Show_VDU ; bclr #6,mFlags[a6] ; Don't steam bra MT_Next ; Done MMan_X rts ; Done Move_Man btst #7,mFlags[a6] ; Alive ? bne.s MMan_X ; move.l mpMaze[a6],a0 ; pChar move.l a0,a5 ; Duplicate move.b #" ",[a0] ; Remove from maze move.b #" ",512[a0] ; move.l mpKbd[a6],a4 ; Ptr to keys move.b mDirection[a6],-[sp] ; Save dirn bsr Man_Move ; Move_Him move.b [sp]+,d0 ; Get Old dirn bclr #0,mFlags[a6] ; Moved last time ? bne.s MM_CheckMoved ; Yes, don't check dirn cmp.b mDirection[a6],d0 ; cmp with last dirn bne.s MM_SamePlace ; Different, don't move MM_CheckMoved cmp.l a0,a5 ; Moved ? beq.s MM_SamePlace ; Not moved bset #0,mFlags[a6] ; Assert moved move.l a0,a2 ; Save new ptr move.l a5,a0 ; Old ptr move.b #" ",d0 ; Clear bsr Show_VDU ; lea 512[a0],a0 ; Bottom half bsr Show_VDU ; move.l a2,a5 ; Restore new ptr MM_SamePlace move.l a5,a0 ; Get ptr move.l a0,mpMaze[a6] ; Save ptr bsr MM_Drive_Disp ; Keep man on window clr.l d0 ; Get man shape move.b mDirection[a6],d0; add.l #Man_Shape_Tab,d0 ; move.l d0,a1 ; Ptr to shapes move.b [a1]+,d0 ; Get char move.b d0,[a0] ; Save it bsr Show_Pos_VDU ; Save as mX,mY also lea 512[a0],a0 ; Bottom half move.b [a1],d0 ; move.b d0,[a0] ; bsr Show_VDU ; lea -512[a0],a0 ; Step back move.b mDirection[a6],d0 ; Get facing dirn and #%110,d0 ; Mask bits move.l #Man_Dir_Off,a1 ; Table move.w 0[a1,d0.w],a1 ; Get offset add.l a0,a1 ; Calc addr tst.b kO[a4] ; "O" ? beq.s MM_NotOpen ; No bsr Open_Door ; Try to open MM_NotOpen tst.b kC[a4] ; "C" ? beq.s MM_NotDoor ; No bsr Close_Door ; Close door MM_NotDoor movem.l d0-a6,-[sp] ; Save regs bsr Look ; Can see any ? movem.l [sp]+,d0-a6 ; Restore regs move.l #Sight_WS_0,a0 ; pVariables tst.b mNumber[a6] ; beq.s MM_F1 ; move.l #Sight_WS_1,a0 ; pVariables MM_F1 move sRange[a0],d2 ; Test valid cmp #$7F,d2 ; beq.s MM_NotFire ; Fail movem.l d1/d2/d3/a1/a2,-[sp] clr.l d3 ; Get man number move.b mNumber[a6],d3 ; d3 := 0 or 1 add.b d3,d3 ; := 0 or 2 move.l a0,a2 ; Save ptr move.l spTarget[a0],a1 ; Get mProjCnt move mProjCnt_0[a1,d3.w],d1 ; MM_Seek_Lp add.l #lSight,a0 ; Get next sighting move sRange[a0],d0 ; Test valid cmp #$7F,d0 ; beq.s MM_FoundTarget ; Done move.l spTarget[a0],a1 ; Comp mProjCnt cmp mProjCnt_0[a1,d3.w],d1 ; blt.s MM_Seek_Lp ; More proj bne.s MM_S_New ; Less proj cmp d0,d2 ; Nearer ? bls.s MM_Seek_Lp ; No MM_S_New move d0,d2 ; Replace min Range move mProjCnt_0[a1,d3.w],d1 ; Replace min mProj move.l a0,a2 ; Replace pNearest bra.s MM_Seek_Lp ; Loop MM_FoundTarget move.l a2,a0 ; Nearest movem.l [sp]+,d1/d2/d3/a1/a2 tst.b kL[a4] ; "L" beq.s MM_NotLight ; bsr Add_Lightning ; Create a lightning bolt MM_NotLight tst.b kF[a4] ; "F" beq.s MM_NotFire ; bsr Add_Fire ; Create a lightning bolt MM_NotFire tst.b kK[a4] ; "K" ? beq.s MM_NotKeep ; No bsr MM_DropCells ; Get drop addresses movem.l a0,-[sp] ; Save pMaze move.l a1,a0 ; First bsr.s MM_PickUp ; Anything ? bne.s MM_KX ; Yes, done cmp.l a1,a2 ; Same address? beq.s MM_KX ; Yes, done move.l a2,a0 ; First bsr.s MM_PickUp ; Anything ? MM_KX movem.l [sp]+,a0 ; Restore pMaze MM_NotKeep tst.b kD[a4] ; "D" ? beq.s MM_NotDrop ; No tst mnSwag[a6] ; Any swag ? beq.s MM_NotDrop ; None bsr MM_DropCells ; Get drop addresses movem.l a0,-[sp] ; Save pMaze move.l a1,a0 ; First bsr.s MM_Drop ; Anything ? beq.s MM_DX ; Yes, done cmp.l a1,a2 ; Same address? beq.s MM_DX ; Yes, done move.l a2,a0 ; First bsr.s MM_Drop ; Anything ? MM_DX movem.l [sp]+,a0 ; Restore pMaze MM_NotDrop tst.b kH[a4] ; "H" beq.s MM_NotHeal ; No move mMagic[a6],d0 ; Get magic subq #2,d0 ; Enought ? bmi.s MM_NotHeal ; No. move d0,mMagic[a6] ; new magic tst mWounds[a6] ; Any wounds ? beq.s MM_NotHeal ; No subq #1,mWounds[a6] ; Dec wounds MM_NotHeal tst.b kSpace[a4] ; "Space" bne Justify_Screen ; Justify rts ; Done MM_Drop move.b [a0],d0 ; Blank square ? cmp.b #" ",d0 ; bne.s MM_PU_X ; No . . can't drop move mnSwag[a6],d0 ; Get offset subq #1,d0 ; Dec move d0,mnSwag[a6] ; Replace move.b mSwag[a6,d0.w],d0 ; Get swag move.b d0,[a0] ; Put into t'maze bsr Show_VDU ; And onto t'screen cmp.b d0,d0 ; Assert Zero rts ; Done MM_PickUp move.b [a0],d0 ; Get char cmp.b #" ",d0 ; Blank ? beq.s MM_PU_X ; Yes, done cmp.b #$C0,d0 ; Empty potion ? beq.s MM_PU_1 ; Yes, skip drink test and.b #$F0,d0 ; Get type field cmp.b #$C0,d0 ; Potion bne.s MM_PU_1 ; No, try rest subq.b #1,[a0] ; Drink it move.b [a0],d0 ; bsr Show_VDU ; Show drinking move #2,d0 ; Add to magic bsr.s Inc_Magic ; move #$1F,ccr ; NZ MM_PU_X rts MM_PU_1 move mnSwag[a6],d0 ; No. held cmp #16,d0 ; 16 items ? beq.s MM_PU_X ; Yes, don't pick up move.b [a0],d1 ; Get item and.b #$F0,d1 ; Type field cmp.b #$C0,d1 ; Magic ? beq.s MM_PU_Ok ; Ok cmp.b #$B0,d1 ; Treasure ? beq.s MM_PU_Ok ; Ok cmp.b d0,d0 ; Fail rts ; Done MM_PU_Ok move.b [a0],mSwag[a6,d0.w] ; Pick up item addq #1,d0 ; Inc no. held move d0,mnSwag[a6] ; move.b #" ",d0 ; Clear maze move.b d0,[a0] ; bsr Show_VDU ; . . and screen move #$1F,ccr ; NZ rts ; Inc_Magic add mMagic[a6],d0 ; Add to magic move d0,mMagic[a6] ; cmp #323,d0 ; In range ? bls.s IM_1 ; Yes move #323,mMagic[a6] ; Limit IM_1 rts MM_DropCells move.b mDirection[a6],d0 ; Get dirn add d0,d0 ; *2 lea Man_Cell_Off,a0 ; Ptr to table move 0[a0,d0.w],a1 ; Offset 1 move 2[a0,d0.w],a2 ; Offset 2 move.l mpMaze[a6],a0 ; Base addr add.l a0,a1 ; Calc addr add.l a0,a2 ; Calc addr rts ; Man_Cell_Off defw -512,-512,1,513,512*2,512*2,-1,511 Illegal illegal MM_Drive_Disp move.l a0,d6 ; Get addr move.l mpScreen[a6],a1 ; Get vars sub.l #BM_Start,d6 ; Y*512+X move.l d6,d7 ; and.w #$1FF,d6 ; d6 := X sub [a1],d6 ; Leftmost X bmi.s MM_D_D_Left ; Off screen-left cmp #40,d6 ; On screen ? bcc.s MM_D_D_Right ; Off screen-right asr.l #8,d7 ; d7 := Y asr.l #1,d7 ; sub 2[a1],d7 ; Topmost Y bmi.s MM_D_D_Up ; Off top cmp #23,d7 ; On screen ? bcc.s MM_D_D_Down ; Off bottom rts ; Done MM_D_D_Left sub #40,[a1] ; Step ptr back bra.s MM_DD_X ; MM_D_D_Right add #40,[a1] ; Step ptr back bra.s MM_DD_X ; MM_D_D_Up sub #23,2[a1] ; Step ptr back bra.s MM_DD_X ; MM_D_D_Down add #23,2[a1] ; Step ptr back MM_DD_X move [a1],d6 ; move 2[a1],d7 ; bra JS_Display ; Show on current display Man_Move move.l a0,a1 ; Present posn. move Man_Keys.l,d0 ; ZXMN and.b #%0000 11 00,d0 ; cmp.b #%0000 01 00,d0 ; Up ? beq.s MM_Up ; Yes cmp.b #%0000 10 00,d0 ; Down ? bne.s MM_LR ; No add.l #512,a0 ; Move down move.b #4,mDirection[a6] ; bra.s MM_LR ; Try it MM_Up sub.l #512,a0 ; Move up MM_U_First move.b #0,mDirection[a6] ; MM_LR move.b [a0],d0 ; Test clear cmp.b #" ",d0 ; bne.s MM_LR_1 ; No move.b 512[a0],d0 ; Test clear cmp.b #" ",d0 ; bne.s MM_LR_1 ; No move.l a0,a1 ; Ok to move to here MM_LR_1 move.l a1,a0 ; Can't move move Man_Keys.l,d0 ; ZX and.b #%11,d0 ; cmp.b #%01,d0 ; Left ? beq.s MM_Left ; Yes cmp.b #%10,d0 ; Right bne.s MM_Test ; No addq.l #1,a0 ; Move right move.b #2,mDirection[a6] ; bra.s MM_Test ; MM_Left subq.l #1,a0 ; Move left MM_L_First move.b #6,mDirection[a6] ; MM_Test move.b [a0],d0 ; Test clear cmp.b #" ",d0 ; bne.s MM_T_Fail ; No move.b 512[a0],d0 ; Test clear cmp.b #" ",d0 ; bne.s MM_T_Fail ; No clr Man_Keys.l ; Clear flags rts ; Done MM_T_Fail move.l a1,a0 ; Don't move clr Man_Keys.l ; Clear flags rts ; Man_Shape_Tab defb $A8,$A9,$AA,$AB ; Man chars defb $AC,$AD,$AE,$AF ; MM_RTS rts ; Exit Move_Monster btst #7,mFlags[a6] ; Dead ? bne.s MM_RTS ; Yes, done move.l mpMaze[a6],a0 ; Get pChar move.l a0,a5 ; Preserve old move.b mDirection[a6],d0 ; bsr Get_Dir_Offset ; a2 := Offset add.l a2,a0 ; Move ptr MM_Moved move.b [a0],d0 ; Get cell cmp.b #" ",d0 ; Blank ? beq MM_Change ; Yes, move there (Random change) and #$FE,d0 ; Door ? cmp.b #$DC,d0 ; Vert and horiz beq MM_Open ; Open it and.b #$F0,d0 ; Get type field cmp.b #$C0,d0 ; Magic? beq MM_Drink ; Yes, drink it cmp.b #$B0,d0 ; Treasure ? beq MM_Collect ; Yes, grab it MM_NewDir move.l a5,a0 ; Restore ptr bsr Get_Directions ; Find valid moves bsr Rand_Less_D0 ; Get a random one move.w d0,a0 ; Index it move.b Dir_List[a0],d0 ; Get direction move.b d0,mDirection[a6] ; move.l a5,a0 ; Restore ptr bsr Get_Dir_Offset ; a2 := Offset add.l a2,a0 ; Move ptr move.b [a0],d0 ; Get cell cmp.b #" ",d0 ; Blank ? beq.s MM_Exit ; Yes, move there MM_Exit_DontMove move.l a5,a0 ; Don't move MM_Exit cmp.l a5,a0 ; Same address ? beq.s MM_X_1 ; Yes, don't undraw move.l a0,a2 ; Save ptr move.l a5,a0 ; Old ptr move.b #" ",d0 ; move.b d0,[a0] ; Remove from maze bsr Show_VDU ; Remove from screen {s} move.l a2,a0 ; Get new ptr MM_X_1 move.b [a0],d0 ; Get cell cmp.b mChar[a6],d0 ; Same char ? beq.s MM_X_2 ; Yes, done move.b mChar[a6],d0 ; Get char move.l a0,mpMaze[a6] ; Replace ptr move.b d0,[a0] ; bsr Show_Pos_VDU ; Place and save mX,mY MM_X_2 move.b mDoorCnt[a6],d0 ; Get door timer beq.s MM_X_3 ; No door subq.b #1,mDoorCnt[a6] ; Dec cnt bne.s MM_X_3 ; Still no door move.l mpDoor[a6],a1 ; Get ptr bsr Close_Door ; Close it MM_X_3 bsr.s Monster_Combat rts ; Done Monster_Combat bsr Quick_Rand ; To fire, or not to fire and.b #%1,d0 ; 1:2 chance bne.s MC_DontFire ; lea mdHoriz[a6],a0 ; Look at player 0 btst #8,d0 ; 50 : 50 beq.s MC_Chosen ; lea mdHoriz_2[a6],a0 ; Look at player 1 MC_Chosen move sRange[a0],d0 ; Test valid cmp #$7F,d0 ; beq.s MC_DontFire ; Fail movem.l d5/a6,-[sp] ; Save regs bsr Quick_Rand ; Which to fire ? and.b #%11,d0 ; bne.s MC_Fire ; Do fire bsr Add_Lightning ; Fire lightning bra.s MC_X ; MC_Fire bsr Add_Fire ; Fire fireball MC_X movem.l [sp]+,d5/a6 ; MC_DontFire move #$7F,mRange[a6] ; Don't fire again move #$7F,mRange_2[a6] ; Don't fire again rts ; MM_Change move.b mDoorCnt[a6],d0 ; Don't change if in door bne MM_Exit ; bsr Quick_Rand ; Get a fast random no. cmp.b mRandomness[a6],d0 ; Change dirn ? bls MM_Exit ; No, Bog off bra MM_NewDir ; Change dirn MM_Drink move.b [a0],d0 ; Get potion char cmp.b #$C0,d0 ; Empty ? beq MM_NewDir ; Yes, get new direction subq.b #1,[a0] ; Consume potion move.b [a0],d0 ; bsr Show_VDU ; Display on screen bra MM_Exit_DontMove ; Done MM_Collect move.b [a0],d0 ; Get potion char cmp.b #$B0,d0 ; Empty ? beq MM_NewDir ; Yes, get new direction subq.b #1,[a0] ; Consume potion move.b [a0],d0 ; bsr Show_VDU ; Display on screen bra MM_Exit_DontMove ; Done MM_Open bsr Quick_Rand ; Open door ? cmp.b #200,d0 ; bls MM_NewDir ; No move.l a0,a1 ; Open the door bsr Open_Door ; bsr Quick_Rand ; Don't close again cmp.b #180,d0 ; bls MM_Moved ; move.l a0,mpDoor[a6] ; Save ptr to door move.b #2,mDoorCnt[a6] ; Assert door bra MM_Moved ; Continue Get_Dir_Offset and #%111,d0 ; Mask bits add d0,d0 ; * 2 move.l #GDO_Tab,a2 ; Table move.w 0[a2,d0.w],a2 ; Get offset rts GDO_Tab defw -512,-511,+1,+513,+512,+511,-1,-513 Man_Dir_Off defw -512,1,512*2,-1 Show_VDU_A1 move.l a1,d6 ; Get diff. address bra.s S_VDU ; Show it Show_VDU move.l a0,d6 ; Get addr S_VDU sub.l #BM_Start,d6 ; Y*512+X move.l d6,-[sp] ; Save it move.l d6,d7 ; Save it and.w #$1FF,d6 ; d5 := X sub ScreenX_1,d6 ; Leftmost X cmp #40,d6 ; On screen ? bhi.s S_VDU_Fail ; No asr.l #8,d7 ; d6 := Y asr.l #1,d7 ; SPV sub ScreenY_1,d7 ; Topmost Y cmp #23,d7 ; On screen ? bhi.s S_VDU_Fail ; No bsr Set_Display_0 ; bsr Out_It ; Place on screen S_VDU_Fail move.l [sp]+,d6 ; Restore it move.l d6,d7 ; Save it and.w #$1FF,d6 ; d5 := X sub ScreenX_2,d6 ; Leftmost X cmp #45,d6 ; On screen ? bhi.s S_VDU_Fail_2 ; No asr.l #8,d7 ; d6 := Y asr.l #1,d7 ; sub ScreenY_2,d7 ; Topmost Y cmp #28,d7 ; On screen ? bhi.s S_VDU_Fail_2 ; No bsr Set_Display_1 ; bra Out_It ; Place on screen S_VDU_Fail_2 rts ; Exit Show_Pos_VDU move.l a0,d6 ; Get addr sub.l #BM_Start,d6 ; Y*512+X move.l d6,-[sp] ; Save move.l d6,d7 ; and #$1FF,d6 ; d5 := X asr.l #8,d7 ; d6 := Y asr.l #1,d7 ; move d6,mX[a6] ; X move d7,mY[a6] ; Y sub ScreenX_1,d6 ; Leftmost X cmp #45,d6 ; On screen ? bhi.s S_VDU_Fail ; No bra.s SPV ; Show char Draw_Monster rts Undraw_Monster rts Get_Directions move.b #$F0,d1 ; Wall char mask move.b #$90,d2 ; Wall chars moveq #0,d0 ; No. of directions move.l #Dir_List,a1 ; List move.b -512[a0],d3 ; U and.b d1,d3 ; Wall ? cmp.b d2,d3 ; beq.s GD_1 ; No move.b #0,[a1]+ ; Place dir addq.b #1,d0 ; Inc. no. GD_1 move.b -511[a0],d3 ; and.b d1,d3 ; Wall ? cmp.b d2,d3 ; beq.s GD_2 ; No move.b #1,[a1]+ ; Place dir addq.b #1,d0 ; Inc. no. GD_2 move.b 1[a0],d3 ; R and.b d1,d3 ; Wall ? cmp.b d2,d3 ; beq.s GD_3 ; No move.b #2,[a1]+ ; Place dir addq.b #1,d0 ; Inc. no. GD_3 move.b 513[a0],d3 ; and.b d1,d3 ; Wall ? cmp.b d2,d3 ; beq.s GD_4 ; No move.b #3,[a1]+ ; Place dir addq.b #1,d0 ; Inc. no. GD_4 move.b 512[a0],d3 ; D and.b d1,d3 ; Wall ? cmp.b d2,d3 ; beq.s GD_5 ; No move.b #4,[a1]+ ; Place dir addq.b #1,d0 ; Inc. no. GD_5 move.b 511[a0],d3 ; and.b d1,d3 ; Wall ? cmp.b d2,d3 ; beq.s GD_6 ; No move.b #5,[a1]+ ; Place dir addq.b #1,d0 ; Inc. no. GD_6 move.b -1[a0],d3 ; L and.b d1,d3 ; Wall ? cmp.b d2,d3 ; beq.s GD_7 ; No move.b #6,[a1]+ ; Place dir addq.b #1,d0 ; Inc. no. GD_7 move.b -513[a0],d3 ; and.b d1,d3 ; Wall ? cmp.b d2,d3 ; beq.s GD_8 ; No move.b #7,[a1]+ ; Place dir addq.b #1,d0 ; Inc. no. GD_8 rts ; Done Init_Things move.l #Monsters,a6 ; Ptr bsr Scan_Kbd ; Get ptr to Kbd move.l #ScreenX_1,a1 ; Get ptr to screen data moveq #0,d0 ; Add man 0 bsr Init_Man ; add.l #lMon,a6 ; Step ptr ; Now initiallise second man move.l #Man_Keys+2,a0 ; Get ptr to Kbd move.l #ScreenX_2,a1 ; Get ptr to screen data moveq #1,d0 ; Add man 1 bsr Init_Man ; move #nMons-2,d7 ; Cnt IT_Lp add.l #lMon,a6 ; Step ptr movem.l d7/a6,-[sp] bsr.s Init_Thing ; Create one movem.l [sp]+,d7/a6 dbf d7,IT_Lp ; Lp rts ; Done Init_Thing move.w #100,mDelay[a6] ; Delay move #100,d0 ; bsr Rand_Less_D0 ; add #20,d0 move.w d0,mSpeed[a6] ; Speed clr.b mFlags[a6] ; Clear flags clr.b mDoorCnt[a6] ; clr mnSwag[a6] ; Nothing carried move.b #2,mNumber[a6] ; Monster 'type' bsr Find_Blank ; Get Free cell move.l a0,mpMaze[a6] ; pMonster bsr Random ; in d1 and.b #%111,d1 ; Random monster shape or.b #$D0,d1 ; d0..D7 move.b d1,mChar[a6] ; Save move.b d1,[a0] ; Put in maze swap d1 ; Random and.b #%111,d1 ; 00..07 move.b d1,mDirection[a6] ; move.l #Draw_Monster,mpDraw[a6] ; Standard routine move.l #Undraw_Monster,mpUndraw[a6] ; Standard routine move.l #Move_Monster,mpMove[a6] ; Standard routine clr mWounds[a6] ; None to start with clr mProjCnt_0[a6] ; No. aimed at it clr mProjCnt_1[a6] ; clr mProjCnt_M[a6] ; move.b #128,mMagic[a6] ; Lots ! move #$7F,mRange[a6] ; Can't see man to start with move #$7F,mRange_2[a6] ; move #1,mScore[a6] ; Score of 1 bsr Random ; Randomness and.b #$7F,d1 ; Range add.b #20,d1 ; move.b d1,mRandomness[a6] ; rts ; done Init_Man move.l a0,mpKbd[a6] ; Save ptr to keys move.b #$FF,8[a0] ; Clear kbd mask move.b d0,mNumber[a6] ; Save which man clr.b mFlags[a6] ; Clear flags clr mnSwag[a6] ; Nothing carried move.l a1,mpScreen[a6] ; Save ptr to screen data move.w #1,mDelay[a6] ; Delay move.w #12,mSpeed[a6] ; Speed move.b #2,mDirection[a6] ; Face right IM_Place bsr Find_Blank ; Get a blank cell move.b 512[a0],d0 ; Blank below too ? cmp.b #" ",d0 ; bne.s IM_Place ; No, try again move.l a0,mpMaze[a6] ; pMan move.b #$AA,[a0] ; Put in maze move.b #$AB,512[a0] ; move.l #Move_Man,mpMove[a6] ; Standard routine clr mWounds[a6] ; None to start with move #1,mScore[a6] ; st mWounds_A[a6] ; Actual wounds st mMagic_A[a6] ; st mScore_A[a6] ; clr mProjCnt_0[a6] ; No. aimed at it clr mProjCnt_1[a6] ; move #323,mMagic[a6] ; Lots ! bra Justify_Screen ; Page in display Justify_Screen move.l mpMaze[a6],d6 ; Get ptr to maze sub.l #BM_Start,d6 ; Offset into BM move.l d6,d7 ; Into d1 ror.l #5,d7 ; ror.l #4,d7 ; and.l #$1FF,d7 ; Y and.l #$1FF,d6 ; X divu #7,d6 ; X/7 mulu #7,d6 ; Clip to 7 divu #7,d7 ; Y/7 mulu #7,d7 ; Clip to 7 sub #2*7,d6 ; Offset X sub #1*7,d7 ; Offset Y move.l mpScreen[a6],a0 ; Ptr to data cmp [a0]+,d6 ; Same X ? bne.s JS_New ; No, move it cmp [a0],d7 ; Same Y ? beq.s JS_Old ; Yes, don't move JS_New move d7,[a0] ; Save Y move d6,-[a0] ; Save X JS_Display move.b mNumber[a6],d0 ; Which display bsr Set_Display ; bra Show_Window ; Display it JS_Old rts ; Exit Close_Door move.l #1,a2 ; Right move.b #$92,d3 ; LHS move.b #$91,d1 ; RHS move.b #" ",d2 ; Value move.b #$DC,d0 ; Becomes move.l a1,a3 ; Save ptr bsr.s OD_1 ; Close door move.l a3,a1 ; Restore ptr move.l #512,a2 ; Down move.b #$98,d3 ; Top move.b #$94,d1 ; Bottom move.b #$DD,d0 ; Becomes bra.s OD_1 ; Close door Open_Door move.l #1,a2 ; Right move.b #$92,d3 ; LHS move.b #$91,d1 ; RHS move.b #$DC,d2 ; Value move.b #" ",d0 ; Becomes move.l a1,-[sp] ; Save ptr bsr.s OD_1 ; Open door move.l [sp]+,a1 ; Restore ptr move.l #512,a2 ; Down move.b #$98,d3 ; Top move.b #$94,d1 ; Bottom move.b #$DD,d2 ; Value OD_1 move #5,d4 ; Search value OD_Lp cmp.b [a1],d3 ; Near end ? beq.s OD_Near ; Yes, check rest cmp.b [a1],d1 ; Far end ? beq.s OD_a ; Yes, ok cmp.b [a1],d2 ; Door char ? bne.s OD_Fail ; No, exit not door OD_a sub.l a2,a1 ; Step ptr back dbf d4,OD_Lp ; Scan left/up OD_Fail rts ; Not found OD_Near move #3,d4 ; 4 door spaces OD_N_Lp add.l a2,a1 ; Skip 1 cmp.b [a1],d2 ; Door char ? bne.s OD_Fail ; Failure dbf d4,OD_N_Lp ; Scan all add.l a2,a1 ; Get end char cmp.b [a1],d1 ; End ? bne.s OD_Fail ; No, fail move #3,d4 ; Door count OD_Fill sub.l a2,a1 ; Step back move.b d0,[a1] ; Fill space bsr Show_VDU_A1 ; Display it dbf d4,OD_Fill ; Do 4 of them rts ; Done Init_Treasure move #nTreasure,d3 ; No. of lumps move.b #$BF,d2 ; Treasure chars bra.s IM_Lp ; Init_Magic move #nMagic,d3 ; No. of bottles move.b #$CF,d2 ; Chars IM_Lp bsr.s Find_Blank ; Get a blank square bsr Random ; d1 and #%1111,d1 ; 0 .. F or.b d2,d1 ; Treasure move.b d1,[a0] ; Place dbf d3,IM_Lp ; Lp rts ; Init_Projectiles move.l #Projectiles,a6 ; Ptr move #nProj-2,d7 ; Cnt-1 clr.l pFirst_Proj ; None to start with move.l a6,pFree_Proj ; This one first IP_Lp lea lProj[a6],a0 ; Address of next move.l a0,ppNext[a6] ; Link ptr add.l #lProj,a6 ; Step ptr dbf d7,IP_Lp ; Lp clr.l ppNext[a6] ; No more rts ; Done New_Proj tst.l pFree_Proj ; Any beq.s NP_Fail ; No. move.l pFree_Proj,a5 ; Get one into a5 move.l ppNext[a5],pFree_Proj ; Replace ptr move.l pFirst_Proj,ppNext[a5]; Link to active list move.l a5,pFirst_Proj ; move #%00000,ccr ; NZ NP_Fail rts ; Done (Z or NZ) Kill_Proj move.l pFree_Proj,ppNext[a5] ; Link to free list move.l a5,pFree_Proj ; rts ; Done Find_Blank bsr Random ; d1 and.l #$3FFFF,d1 ; Mask cmp.l #BM_Max_X*BM_Max_Y,d1 ; In range bhi.s Find_Blank ; Not in maze, try again add.l #BM_Start,d1 ; Add base addr move.l d1,a0 ; move.b [a0],d0 ; Get cell cmp.b #$20,d0 ; Empty ? bne.s Find_Blank ; No, try again rts ; Find_Blank_Man bsr Random_64 ; d1 mulu #BM_Max_X,d1 ; Y move.l d1,-[sp] ; Save it bsr Random_64 ; d1 add.l [sp]+,d1 ; Address add.l #BM_Start,d1 ; Add base addr move.l d1,a0 ; move.b [a0],d0 ; Get cell cmp.b #$20,d0 ; Empty ? bne.s Find_Blank_Man ; No, try again rts ; Random_64 bsr Random ; d1 and.l #$3F,d1 ; 0 .. 63 rts ; Done Quick_Rand move.l a0,-[sp] ; Save Ptr clr.l d0 ; Zero d0 move QRand_Ptr,d0 ; Get rand and.b #$FE,d0 ; Word bound move.l d0,a0 ; Get ptr move [a0]+,d0 ; move a0,QRand_Ptr ; Save ptr xor d0,QRand_Seed ; Randomise add QRand_Seed,d0 ; move.l [sp]+,a0 ; Restore ptr rts Drive_About move.b kShiftL[a0],d0 ; Restart ? and.b kShiftR[a0],d0 ; bne Start ; Yes, restart game clr d0 ; Reset flags ; Now get move keys (ZXNM) tst.b kZ[a0] ; Left beq.s DA_Z ; No bset #0,d0 ; Assert DA_Z tst.b kX[a0] ; Right beq.s DA_X ; No bset #1,d0 ; Assert DA_X tst.b kN[a0] ; Up beq.s DA_N ; No bset #2,d0 ; Assert DA_N tst.b kM[a0] ; Down beq.s DA_M ; No bset #3,d0 ; Assert DA_M tst.b kSpace[a0] ; Just beq.s DA_Sp ; No bset #4,d0 ; Assert DA_Sp or d0,Man_Keys.l ; Store results rts ; Done Stat_Data defb "Souls 1 Wounds" defb $F1,$E8,$E8,$E8,$E8,$E8,$E8,$E8,$F2 defb "Magic" defb $F1,$E8,$E8,$E8,$E8,$E8,$E8,$E8,$F2 defb 0 org (*+1) and $FFFFFFFE; Even boundary Man_Keys defs 2 ; All the man key flags cSpeed defw Speed ; Slow speed ScreenX_1 defs 2 ; ScreenY_1 defs 2 ; ScreenX_2 defs 2 ; ScreenY_2 defs 2 ; QRand_Seed defs 2 ; Fast random data QRand_Ptr defs 2 ; pFirst_Proj defs 4 ; pList of proj pFree_Proj defs 4 ; pFree list Dir_List defs 8 ; 8 possible dirs org $50000 ; Away from BM Monsters defs (nMons+2)*lMon ; Data for things Projectiles defs nProj*lProj ; Data for projectiles Sight_WS_0 defs $800 ; Data for visible monsters Sight_WS_1 defs $800 ;