; YAMFG 1.0 - ©1993 F.Delacroix- FreeWare ; written on HiSoft Devpac 3 ; all system includes were included at assembly time using the ; system.gs file of Devpac 3. If you use another assembly,just ; include them individually include exec/execbase.i ; some more includes: ExecBase struct include hardware/custom.i ; custom hardware: for random numbers include libraries/reqtools.i ; includes for reqtools.library include libraries/reqtools_lib.i DEFAULT_WIDTH EQU 20 ; useful constants: self-explanatory... DEFAULT_HEIGHT EQU 20 DEFAULT_MINES EQU 40 MAX_WIDTH EQU 24 MAX_HEIGHT EQU 21 UP EQU $4c ; keys used to move the tank DOWN EQU $4d RIGHT EQU $4e LEFT EQU $4f STATUSX EQU 4 ; coordinates for the status-line STATUSY EQU 18 move.l 4.w,a6 move.l ThisTask(a6),a4 ;find my task (same as FindTask(0)) moveq #0,d0 tst.l pr_CLI(a4) ; were we called from CLI ? bne.s FromCLI ; yes,we were... lea pr_MsgPort(a4),a0 ; no: get the WBStartup message jsr _LVOWaitPort(a6) ; sent by the Workbench lea pr_MsgPort(a4),a0 jsr _LVOGetMsg(a6) FromCLI move.l d0,WBStarter ; and store it (0 if from CLI) lea ReqTools.Name(pc),a1 ; let's open the reqtools.library moveq #0,d0 jsr _LVOOpenLibrary(a6) move.l d0,ReqTools.Base beq OutOfHere ; no reqtools.library: exit program move.l ReqTools.Base(pc),a0 ; and get other library bases from it move.l rt_IntuitionBase(a0),Intuition.Base move.l rt_GfxBase(a0),Graphics.Base lea YAMFG.NewWindow(pc),a0 ; let's open the window move.l Intuition.Base(pc),a6 jsr _LVOOpenWindow(a6) move.l d0,YAMFG.Window beq CloseReqTools ; cannot open window ! move.l YAMFG.Window(pc),a0 ; let's attach the menues to the window lea Project.Menu(pc),a1 jsr _LVOSetMenuStrip(a6) tst.l d0 beq CloseWindow ; failed ! (shouldn't occur) move.l YAMFG.Window(pc),a0 ; store important data from our window move.l wd_RPort(a0),YAMFG.RastPort ; RastPort for graphics move.l wd_UserPort(a0),YAMFG.UserPort ; UserPort for messages bra NewGame ; let's begin a new game... WaitMessage move.l YAMFG.UserPort(pc),a0 ; let's wait for a message from move.l 4.w,a6 ; Intuition to our window... jsr _LVOWaitPort(a6) NextMessage move.l YAMFG.UserPort(pc),a0 ; And get it! move.l 4.w,a6 jsr _LVOGetMsg(a6) tst.l d0 beq.s WaitMessage ; Was there actually one ? move.l d0,a1 ; Yeah ! move.l im_Class(a1),d7 ; Store important fields:Class move.w im_Code(a1),d6 ; and Code jsr _LVOReplyMsg(a6) ; then reply to Intuition cmp.l #IDCMP_CLOSEWINDOW,d7 ; Should we quit ? beq ClearMenus ; Yes? Then go... cmp.w #IDCMP_RAWKEY,d7 ; Was a key pressed bne NoRawKey btst #IECODEB_UP_PREFIX,d6 ; ignore if a key was released bne NextMessage tst.b FinishFlag ; was the game finished ? bne NewGame ; yes? then begin a new one move.w MinerX(pc),d0 ; no: get the position of the tank move.w MinerY(pc),d1 cmp.w #UP,d6 ; Up ? beq.s GoUp cmp.w #DOWN,d6 ; Down ? beq.s GoDown cmp.w #RIGHT,d6 ; Right ? beq.s GoRight cmp.w #LEFT,d6 ; Or left ? bne NextMessage ; None of that ?? then get next Message subq.w #1,d0 ; 1 step left bra.s DirectionGot GoRight addq.w #1,d0 ; 1 step right bra.s DirectionGot GoDown addq.w #1,d1 ; 1 step down bra.s DirectionGot GoUp subq.w #1,d1 ; 1 step up DirectionGot bsr CheckBounds ; check if tank does not go out of bounds bsr MoveMiner ; then move it move.l Width(pc),d0 ; Is tank on the right edge ? subq.l #1,d0 cmp.w MinerX(pc),d0 bne.s NoGoal move.l Height(pc),d0 ; Is it on the bottom ? subq.l #1,d0 cmp.w MinerY(pc),d0 bne.s NoGoal ; yes ! The goal is reached ! (Congrats!) lea Won.MSG(pc),a0 ; Get winning message.. bra.s EndOfGame ; and end the game NoGoal moveq #0,d0 ; Target not reached yet... move.w MinerY(pc),d0 ; Turn tank position into an offset for mulu Width+2(pc),d0 ; the mine array: offset=Width*Y+X add.w MinerX(pc),d0 lea Mines.Array(pc),a2 tst.b (a2,d0) ; test if tank is on a mine beq.s ShowNumber ; No!! lea Lost.MSG(pc),a0 ; Uh-Oh: a mine ! EndOfGame st FinishFlag ; The game is finished bsr DisplayStatus ; Display the end message (won or lost) bsr RevealMines ; and display mine positions bra NextMessage ; go back to loop NewGame clr.b FinishFlag ; When a game begins,it is not finished yet move.l YAMFG.RastPort(pc),a1 moveq #RP_JAM2,d0 move.l Graphics.Base(pc),a6 jsr _LVOSetDrMd(a6) ; set drawmode to RP_JAM2 (uses both pens) move.l YAMFG.RastPort(pc),a1 moveq #0,d0 jsr _LVOSetAPen(a6) ; select color 0 move.l YAMFG.RastPort(pc),a1 move.l #4,d0 ; draw a big rectangle to clear all the display move.l #12,d1 move.l #396,d2 move.l #196,d3 jsr _LVORectFill(a6) bsr DrawMinesBorder ; draw a border around play area bsr PlaceMines ; Generate random mine positions clr.w MinerX ; Place the tank in the upper left corner clr.w MinerY bsr ShowMiner ; draw the tank ShowNumber lea Mines.Array(pc),a2 moveq #0,d0 move.w MinerY(pc),d0 ; turn tank position into offset for table mulu Width+2(pc),d0 add.w MinerX(pc),d0 add.l d0,a2 ; tank emplacement within mine array moveq #0,d1 move.l Width(pc),d3 ; d3=Width of play area move.l Height(pc),d4 move.l d3,d5 ; d5=Width-1 subq.l #1,d5 subq.l #1,d4 ; d4=Height-1 move.l d3,d6 neg.l d6 ; d6=-Width tst.w MinerY ; is tank on upper edge ? beq.s No9 ; yes? then don't test above tank! tst.b (a2,d6.l) ; mine in position 8 ? beq.s No8 ; note: I follow these conventions within addq.l #1,d1 ; the source: 789 No8 tst.w MinerX ; 4 6 beq.s No7 ; 123 tst.b -1(a2,d6.l) ; if the array in tested position beq.s No7 ; (in order of appearance:8,7,9,4,6,1,2,3) addq.l #1,d1 ; is not zero, then there is a mine,and No7 cmp.w MinerX(pc),d5 ; the mine counter (d1) is incremented beq.s No9 ; Of course,if the position does not make tst.b 1(a2,d6.l) ; a sense (if the tank is on an edge of beq.s No9 ; the play area),the position is not tested. addq.l #1,d1 No9 tst.w MinerX beq.s No4 tst.b -1(a2) beq.s No4 addq.l #1,d1 No4 cmp.w MinerX(pc),d5 beq.s No6 tst.b 1(a2) beq.s No6 addq.l #1,d1 No6 cmp.w MinerY(pc),d4 beq.s No3 tst.w MinerX beq.s No1 tst.b -1(a2,d3) beq.s No1 addq.l #1,d1 No1 tst.b (a2,d3) beq.s No2 addq.l #1,d1 No2 cmp.w MinerX(pc),d5 beq.s No3 tst.b 1(a2,d3) beq.s No3 addq.l #1,d1 No3 add.b #'0',d1 ; turn mine counter into a displayable digit move.b d1,Mines.Number ; and store it for printing lea MinesNumber.MSG(pc),a0 ; This is the 'Mines around' message bsr DisplayStatus ; display it! bra NextMessage ; next user action... NoRawKey cmp.l #IDCMP_MENUPICK,d7 ; was a menu selected ? bne NextMessage ; no: ignore that a strange message! DoNextSelect move.w d6,d0 ; this is the menu number given by Intuition lea Project.Menu(pc),a0 ; our menu strip move.l Intuition.Base(pc),a6 jsr _LVOItemAddress(a6) ; get address of selected MenuItem move.l d0,a5 tst.l d0 ; was there one actually ? beq NextMessage ; No: end of menu treatment move.w mi_NextSelect(a5),d6 ; store menunumber of next selected move.l mi_SIZEOF(a5),a1 ; This is a custom field in the item cmp.l #0,a1 ; structure: it points to the routine to execute.. beq DoNextSelect ; if there is one of course jsr (a1) ; execute it ! bra.s DoNextSelect ; then process next menu selection ClearMenus ; Time to quit the game !! move.l YAMFG.Window(pc),a0 ; remove menues from our window move.l Intuition.Base(pc),a6 jsr _LVOClearMenuStrip(a6) CloseWindow move.l YAMFG.Window(pc),a0 ; close the window move.l Intuition.Base(pc),a6 jsr _LVOCloseWindow(a6) CloseReqTools move.l ReqTools.Base(pc),a1 ; close the reqtools.library move.l 4.w,a6 jsr _LVOCloseLibrary(a6) OutOfHere move.l WBStarter(pc),d1 ; were we called from Workbench ? beq.s BackToCLI ; no: there is no more to be done jsr _LVOForbid(a6) ; yes: we must reply to the WBStartup move.l d1,a1 ; message we received on start of the prog move.l 4.w,a6 ; note that the Forbid() call is absolutely jsr _LVOReplyMsg(a6) ; necessary. BackToCLI moveq #0,d0 ; so that CLI does not display strangest codes... rts ; This is the sad end ... ; subroutine that initializes some display variables and draws the ; rectangular border and displays the target picture DrawMinesBorder movem.l d0-d1/a0-a1/a6,-(sp) move.l Width(pc),d0 ; Width in pixels=Width*16 lsl.l #4,d0 move.l Height(pc),d1 ; Height in pixels=Height*8 lsl.l #3,d1 addq.l #1,d0 addq.l #1,d1 move.w d0,Border.Right1 ; store these values for drawing the move.w d0,Border.Right2 ; border move.w d0,Border.Right3 move.w d1,Border.Bot1 move.w d1,Border.Bot2 move.w d1,Border.Bot3 move.l YAMFG.RastPort(pc),a0 ; the window RastPort lea YAMFG.Border(pc),a1 ; the Border structure move.l Width(pc),d0 ; Compute the PlayX variable to center lsl.l #3,d0 ; the playing field: PlayX=(400-Width*16)/2 neg.l d0 ; PlayX=200-Width*8 add.l #200,d0 move.l d0,PlayX move.l Height(pc),d1 ; Compute the PlayY variable in a similar lsl.l #2,d1 ; way: PlayY=(200-Height*8)/2=100-Height*4 neg.l d1 add.l #100,d1 addq.l #3,d1 ; and add 3 pixels cmp.l #STATUSY+4,d1 ; but do not overlap the Status Line bge.s NotTooLow ; area !! move.l #STATUSY+4,d1 ; If it's the case,then lower it a bit NotTooLow move.l d1,PlayY move.l Intuition.Base(pc),a6 jsr _LVODrawBorder(a6) ; Draw the damn border move.l YAMFG.RastPort(pc),a0 ; Necessary for all graphic operations lea Target.Image,a1 ; The image structure for the target move.l Width(pc),d0 ; X Y positions of the target: subq.l #1,d0 ; in the lower right corner lsl.l #4,d0 add.l PlayX(pc),d0 move.l Height(pc),d1 subq.l #1,d1 lsl.l #3,d1 add.l PlayY(pc),d1 jsr _LVODrawImage(a6) ; let Intuition draw it. movem.l (sp)+,d0-d1/a0-a1/a6 rts ; this is the subroutine that randomly places the mines in the array ; It is NOT guaranteed that there is a way out if the mines are too ; numerous. The routine uses a classic FastRand() algorythm which takes ; the position of the raster as seed PlaceMines movem.l d0/d3-d5/a2,-(sp) lea Mines.Array(pc),a2 ; array to fill move.l Width(pc),d0 mulu Height+2(pc),d0 ; Size of the array move.l d0,d3 subq.l #1,d0 ; a dbra loop counts down to -1 ClearMines clr.b (a2)+ ; wipe all mines from the array dbra d0,ClearMines moveq #0,d5 move.w $DFF000+vhposr,d5 ; get the seed from the vhposr registr lea Mines.Array(pc),a2 ; restore a2 move.l Mines(pc),d4 ; number of mines to place cmp.l d4,d3 ; is it possible ?? bgt.s AnotherRandom ; yes it is move.l d3,d4 ; there are far too many mines !! Reduce the number subq.l #4,d4 ; this is only for safety: who would want a game where AnotherRandom ; every move is loss ? add.l d5,d5 ; This is the FastRand() routine that generates bhi.s .NoEOR ; a seemingly random series of numbers eor.l #$1D872B41,d5 ; Why this number ? This is a good question. .NoEOR moveq #0,d0 ; divide the random number by the array size so that move.w d5,d0 ; the modulo reflects a valid position in the grid divu d3,d0 swap d0 tst.w d0 ; I don't want a mine in the upper left corner! beq AnotherRandom tst.b (a2,d0.w) ; Is there already a mine there ? bne.s AnotherRandom ; Yes?? Well use another offset move.b #1,(a2,d0.w) ; No: well now there is one subq #1,d4 ; Was it the last mine to be placed ? bne AnotherRandom ; No. movem.l (sp)+,d0/d3-d5/a2 ; Yes: restore registers and rts ; return ; This displays the tank.. ShowMiner movem.l d0-d1/a0-a1/a6,-(sp) move.l YAMFG.RastPort(pc),a0 lea Tank.Image,a1 ; Image structure for the tank moveq #0,d0 move.l d0,d1 move.w MinerX(pc),d0 move.w MinerY(pc),d1 lsl.l #4,d0 lsl.l #3,d1 add.l PlayX(pc),d0 ; X=PlayX+MinerX*16 add.l PlayY(pc),d1 ; Y=PlayY+MinerY*8 move.l Intuition.Base(pc),a6 jsr _LVODrawImage(a6) ; Draw it. Easy no? movem.l (sp)+,d0-d1/a0-a1/a6 rts ; This checks whether the tank has gone out of bounds,in which case it is ; placed back on the edge of the grid. This routine is called with the ; newly demanded position in D0 and D1 (X and Y respectively). CheckBounds ext.l d0 ; Turn X position into a longword cmp.l Width(pc),d0 ; Too far on the right ? blt.s NotRightEdge move.l Width(pc),d0 subq.l #1,d0 NotRightEdge tst.l d0 ; Too far on the left ? bge.s NotLeftEdge moveq #0,d0 NotLeftEdge ext.l d1 ; Turn Y position into a longword tst.l d1 ; Too far up ? bge.s NotUpEdge moveq #0,d1 NotUpEdge cmp.l Height(pc),d1 ; Too far down ? blt.s NoDownEdge move.l Height(pc),d1 subq.l #1,d1 NoDownEdge rts ; This routine erases the tank image and then draw it at the position ; given by D0 and D1 (X and Y).It also updates the MinerX and MinerY vars. MoveMiner bsr.s EraseMiner move.w d0,MinerX move.w d1,MinerY bra ShowMiner ; This erases the tank image by printing two spaces in color 3 EraseMiner movem.l d0-d1/a0-a1/a6,-(sp) move.l YAMFG.RastPort(pc),a1 moveq #0,d0 ; X=PlayX+MinerX*16 move.l d0,d1 ; Y=PlayY+MinerY*8 move.w MinerX(pc),d0 move.w MinerY(pc),d1 lsl.l #4,d0 lsl.l #3,d1 add.l PlayX(pc),d0 add.l PlayY(pc),d1 addq.l #6,d1 ; Add 6 to the Y position to get the baseline of the move.l Graphics.Base(pc),a6 ; standard topaz font. jsr _LVOMove(a6) ; Move the graphic cursor there move.l YAMFG.RastPort(pc),a1 moveq #3,d0 ; set the B pen to color 3 (orange or blue on jsr _LVOSetBPen(a6) ; normal-coloured workbenchs) move.l YAMFG.RastPort(pc),a1 moveq #RP_JAM2,d0 ; set the drawmode to RP_JAM2 so that jsr _LVOSetDrMd(a6) ; spaces are truly made blue lea Space.Text(pc),a0 ; The spaces move.l YAMFG.RastPort(pc),a1 moveq #2,d0 ; there are two of them jsr _LVOText(a6) movem.l (sp)+,d0-d1/a0-a1/a6 rts ; That's it ; This routine is used to erase the status line. It is called by DisplayStatus EraseStatus movem.l d0-d3/a0-a1/a6,-(sp) move.l YAMFG.RastPort(pc),a1 moveq #RP_JAM2,d0 move.l Graphics.Base(pc),a6 jsr _LVOSetDrMd(a6) ; Drawmode to RP_JAM2 move.l YAMFG.RastPort(pc),a1 moveq #0,d0 ; A pen to color 0 jsr _LVOSetAPen(a6) move.l YAMFG.RastPort(pc),a1 move.l #STATUSX,d0 ; coordinates for the rectangle that will move.l #STATUSY-6,d1 ; be drawn over the status line move.l #STATUSX+40*8,d2 move.l #STATUSY+2,d3 jsr _LVORectFill(a6) ; draw the rectangle movem.l (sp)+,d0-d3/a0-a1/a6 rts ; This routine displays a message in the status line,which is first cleared. ; On calling,A0 must be loaded with a pointer to the message to be displayed. DisplayStatus: ;DisplayStatus(Message)(A0) movem.l d0-d1/a0-a2/a6,-(sp) bsr EraseStatus ; First erase the status line move.l a0,a2 ; Save the message pointer (A2 is guaranteed to move.l YAMFG.RastPort(pc),a1 ; be preserved by library routines) moveq #RP_JAM1,d0 move.l Graphics.Base(pc),a6 jsr _LVOSetDrMd(a6) ; drawmode to RP_JAM1: only the A pen is used move.l YAMFG.RastPort(pc),a1 moveq #1,d0 jsr _LVOSetAPen(a6) ; A Pen to color 1 (normally black or white) move.l YAMFG.RastPort(pc),a1 move.l #STATUSX,d0 ; Coordinates of the status line move.l #STATUSY,d1 jsr _LVOMove(a6) ; move the graphic cursor there move.l a2,a0 .LenLoop ; count the length of the message tst.b (a2)+ ; this is required for the Text() function bne .LenLoop sub.l a0,a2 subq.l #1,a2 move.l a2,d0 move.l YAMFG.RastPort(pc),a1 jsr _LVOText(a6) ; print the text movem.l (sp)+,d0-d1/a0-a2/a6 rts ; This routine reveals where the mines were placed,it is called when the ; game has ended (the player has won or lost) RevealMines movem.l d0-d3/a0-a2/a6,-(sp) lea Mines.Array(pc),a2 ; The mines grid moveq #-1,d2 ; The current position in the array move.l Intuition.Base(pc),a6 move.l Width(pc),d3 mulu Height+2(pc),d3 ; d3 is the size of the array RevealLoop addq.l #1,d2 ; increment position cmp.l d3,d2 ; have we reached the end of the array ? beq.s EndOfReveal ; yes...then go. tst.b (a2)+ ; is there a mine here ? beq.s RevealLoop ; No, check next position move.l d2,d0 ; yes! Its position is in D0 divu Width+2(pc),d0 ; this is to split X and Y positions moveq #0,d1 ; X position (the modulo of the division) is in D0 move.w d0,d1 ; and the Y is in D1 (the quotient of the division) clr.w d0 swap d0 move.l YAMFG.RastPort(pc),a0 lea Mine.Image,a1 ; Image structure for a mine lsl.l #4,d0 ; Turn X and Y positions in the grid into true lsl.l #3,d1 ; graphic places add.l PlayX(pc),d0 add.l PlayY(pc),d1 jsr _LVODrawImage(a6) ; Draw a mine bra RevealLoop ; check some more positions EndOfReveal movem.l (sp)+,d0-d3/a0-a2/a6 ; all mines were displayed,our job rts ; is finished ; This routine is called when the corresponding menu is selected QuitYAMFG addq.l #4,sp ; There is no return for this routine bra ClearMenus ; We quit! ; This is called when the player has chosen 'About' in the menues ShowAbout movem.l d0-d1/a0-a4/a6,-(sp) lea About.Body(pc),a1 ; Main message lea About.Gad(pc),a2 ; Text for the gadget suba.l a3,a3 ; No ReqInfo structure move.l a3,a4 ; And no formatting things lea About.TagList(pc),a0 ; specific TagList move.l ReqTools.Base(pc),a6 ; Let the great reqtools.library jsr _LVOrtEZRequestA(a6) ; do it.. movem.l (sp)+,d0-d1/a0-a4/a6 rts ; This is when the user wants to change the number of mines (with the menu) ModifyMines lea Mines(pc),a1 ; Variable containing the number of mines lea HowManyMines.Title(pc),a2 ; Title for the requester suba.l a3,a3 ; No ReqInfo structure lea Mines.TagList(pc),a0 ; but some tags... move.l ReqTools.Base(pc),a6 ; Request the number of mines jsr _LVOrtGetLongA(a6) tst.l d0 ; has the user entered a valid number ? bne.s NewMines ; yes, go for a new game rts ; no,the requester was canceled ; This user wants to change the width of the playfield ChangeWidth lea Width(pc),a1 ; Variable for the width lea Width.Title(pc),a2 ; Title of the requester sub.l a3,a3 ; No ReqInfo structure lea Width.TagList(pc),a0 ; some tags... move.l ReqTools.Base(pc),a6 jsr _LVOrtGetLongA(a6) ; Get new width tst.l d0 bne.s NewWidth ; New game if it is valid rts ; return if the requester was canceled NewMines ; this is a branch for the routines that require a new NewWidth ; game to be started NewHeight addq.l #4,sp ; cancel the return address on the stack bra NewGame ; and branch to the main program ; This is exactly the same routine as ChangeWidth(),I don't think comments ; are needed. ChangeHeight lea Height(pc),a1 lea Height.Title(pc),a2 sub.l a3,a3 lea Height.TagList(pc),a0 move.l ReqTools.Base(pc),a6 jsr _LVOrtGetLongA(a6) tst.l d0 bne.s NewHeight rts ; This part contains some data for windows,menus,messages,and miscellane- ; ous little things. YAMFG.NewWindow ; this is the NewWindow structure dc.w 120,0 ; XY origin dc.w 400,200 ; Width and Height in pixels dc.b 0,1 ; FrontPen and BackPen colors dc.l IDCMP_CLOSEWINDOW!IDCMP_RAWKEY!IDCMP_MENUPICK ; The above line contains IDCMP flags, a message will be sent by intuition ; to our program when such events occur. dc.l WINDOWDRAG!WINDOWDEPTH!WINDOWCLOSE!ACTIVATE!NOCAREREFRESH ; This are standard window flags. There is no special strange flag,they ; are self-explanatory,thus there is no need for further explanations,you ; should understand these by yourself, so there is no need for any further ; comments, so why should I bore you to death with this ? dc.l 0 ; No gadgets on that window dc.l 0 ; No custom CheckMark (we don't even use a checkmark) dc.l YAMFG.WindowName ; Name for our window dc.l 0 ; Screen: we will just use the Workbench screen dc.l 0 ; Bitmap: No bitmap. dc.w 400,200 ; Minimum dimensions (useless in our case) dc.w 400,200 ; Maximum dimensions (idem) dc.w WBENCHSCREEN ; yes,the Workbench screen YAMFG.Border ; Border structures for the rectangle around the play area dc.w -1,-1 ; XY origin dc.b 1,0,RP_JAM1,3 ; FontPen,BackPen,DrawMode,Number of vectors dc.l YAMFG.Vectorsa,YAMFG.Borderb ; Vectors,Next border struct YAMFG.Borderb dc.w -1,-1 ; we use two linked border structures in dc.b 2,0,RP_JAM1,3 ; order to create a simi-3D effect (one side dc.l YAMFG.Vectorsb,0 ; is drawn in white,the other black) YAMFG.Vectorsa ; This are the XY coordinates for the vectors of the firs dc.w 0 ; border. Some fields will be altered by the program Border.Bot1 dc.w DEFAULT_HEIGHT*8+1 dc.w 0,0 Border.Right1 dc.w DEFAULT_WIDTH*16+1,0 YAMFG.Vectorsb ; The same for the second border Border.Right2 dc.w DEFAULT_WIDTH*16+1,1 Border.Right3 dc.w DEFAULT_WIDTH*16+1 Border.Bot2 dc.w DEFAULT_HEIGHT*8+1 dc.w 1 Border.Bot3 dc.w DEFAULT_HEIGHT*8+1 Project.Menu ; This is the menu structure for the project menu dc.l Options.Menu ; Next menu: the 'Options' menu dc.w 0,0 ; LeftEdge and TopEdge dc.w 63,0 ; Width and Height (Height is unused) dc.w MENUENABLED ; Flags: the menu is enabled dc.l Project.Name ; guess what this is dc.l About.MenuItem ; First item for that menu dc.w 0,0,0,0 ; mysterious Intuition variables About.MenuItem ; MenuItem structure for the 'About' Item dc.l Quit.MenuItem ; Next Item dc.w 0,0 ; LeftEdge,TopEdge dc.w 104,8 ; Width,Height dc.w ITEMTEXT!COMMSEQ!ITEMENABLED!HIGHCOMP ; menu flags: ; ITEMTEXT means that an IntuiText structure will be used (it could have been ; an Image),COMMSEQ means there will be a keyboard shortcut,ITEMENABLED means ; that the item can actually be selected,HIGHCOMP tells Intuition to inverse ; the colors of the menu when the mouse pointer is on it dc.l 0 ; No Mutual-Exclude dc.l About.IText ; Render: an IntuiText structure dc.l 0 ; No render for selected state dc.b 'A' ; Keyboard shortcut dc.b 0 ; This is just a fill byte to make the address even dc.l 0 ; No SubItem list dc.w MENUNULL ; will be filled by Intuition for extended ; selection dc.l ShowAbout ; This is a custom field,used by the prog to ; determine which routine is to be executed when the menu is selected About.IText ; This is an IntuiText structure for rendering the MenuItem dc.b 3,1,RP_COMPLEMENT,0 ; DetailPen,BlockPen,DrawMode,FillByte dc.w 0,0 ; LeftEdge,TopEdge dc.l 0 ; No custom font dc.l About.MSG ; Message dc.l 0 ; No more IntuiText structure ; The other Menu and MenuItem structures are made the same way,it would be a ; waste of time to describe them all. Quit.MenuItem dc.l 0 dc.w 0,8 dc.w 104,8 dc.w ITEMTEXT!COMMSEQ!ITEMENABLED!HIGHCOMP dc.l 0 dc.l Quit.IText dc.l 0 dc.b 'Q' dc.b 0 dc.l 0 dc.w MENUNULL dc.l QuitYAMFG Quit.IText dc.b 3,1,RP_COMPLEMENT,0 dc.w 0,0 dc.l 0 dc.l Quit.MSG dc.l 0 Options.Menu dc.l 0 dc.w 70,0 dc.w 63,0 dc.w MENUENABLED dc.l Options.Name dc.l Mines.MenuItem dc.w 0,0,0,0 Mines.MenuItem dc.l Width.MenuItem dc.w 0,0 dc.w 184,8 dc.w ITEMTEXT!COMMSEQ!ITEMENABLED!HIGHCOMP dc.l 0 dc.l Mines.IText dc.l 0 dc.b 'M' dc.b 0 dc.l 0 dc.w MENUNULL dc.l ModifyMines Mines.IText dc.b 3,1,RP_COMPLEMENT,0 dc.w 0,0 dc.l 0 dc.l Mines.MSG dc.l 0 Width.MenuItem dc.l Height.MenuItem dc.w 0,8 dc.w 184,8 dc.w ITEMTEXT!COMMSEQ!ITEMENABLED!HIGHCOMP dc.l 0 dc.l Width.IText dc.l 0 dc.b 'W' dc.b 0 dc.l 0 dc.w MENUNULL dc.l ChangeWidth Width.IText dc.b 3,1,RP_COMPLEMENT,0 dc.w 0,0 dc.l 0 dc.l Width.MSG dc.l 0 Height.MenuItem dc.l 0 dc.w 0,16 dc.w 184,8 dc.w ITEMTEXT!COMMSEQ!ITEMENABLED!HIGHCOMP dc.l 0 dc.l Height.IText dc.l 0 dc.b 'H' dc.b 0 dc.l 0 dc.w MENUNULL dc.l ChangeHeight Height.IText dc.b 3,1,RP_COMPLEMENT,0 dc.w 0,0 dc.l 0 dc.l Height.MSG dc.l 0 About.TagList ; The tags for the about requester dc.l RT_IDCMPFlags,IDCMP_MOUSEBUTTONS!INACTIVEWINDOW ; Some more IDCMP flags to react on dc.l RTEZ_Flags,EZREQF_CENTERTEXT ; Center Text in window dc.l TAG_END Mines.TagList ;Tags for the number of mines requester dc.l RTGL_Min,1 ; Minimum 1 dc.l RTGL_Max,100 ; Maximum 100 dc.l TAG_END Width.TagList ; For the width requester dc.l RTGL_Min,4 ; Minimum 4 dc.l RTGL_Max,MAX_WIDTH ; Maximum dc.l TAG_END Height.TagList ; For the height requester dc.l RTGL_Min,4 ; Minimum dc.l RTGL_Max,MAX_HEIGHT ; Maximum dc.l TAG_END Project.Name ; No need for comments dc.b 'Project',0 About.MSG dc.b 'About...',0 Quit.MSG dc.b 'Quit',0 Options.Name dc.b 'Options',0 Mines.MSG dc.b 'Number of mines...',0 Width.MSG dc.b 'Width...',0 Height.MSG dc.b 'Height...',0 YAMFG.WindowName dc.b 'YAMFG 1.0 © 1993 F.Delacroix -FreeWare',0 ReqTools.Name dc.b 'reqtools.library',0 ; Name of the reqtools.library Space.Text dc.b ' ' ; Used to erase the tank image Lost.MSG dc.b 'You blew up ! Press a key...',0 MinesNumber.MSG dc.b 'Number of mines around you:' Mines.Number dc.b '0',0 Won.MSG dc.b 'Congratulations! You''ve reached the goal!',0 About.Body ; The about message,please dont change this. dc.b 'YAMFG 1.0 by F.Delacroix - FreeWare',10,10 dc.b 'This program may not be used for any profit',10 dc.b 'To contact me,write to:',10 dc.b 'Frédéric DELACROIX',10 dc.b '5 rue d''Artres',10 dc.b '59269 QUERENAING, FRANCE',0 About.Gad dc.b 'Ah-ha.',0 HowManyMines.Title dc.b 'How many mines ?',0 Width.Title dc.b 'New width ?',0 Height.Title dc.b 'New height ?',0 WBStarter dc.l 0 ; WBStartup received (0 if from CLI) Graphics.Base dc.l 0 ; Base of the graphics.library Intuition.Base dc.l 0 ; Base of intuition.library ReqTools.Base dc.l 0 ; Base of the great reqtools.library YAMFG.Window dc.l 0 ; Window structure (not NewWindow) YAMFG.RastPort dc.l 0 ; RastPort for our window YAMFG.UserPort dc.l 0 ; UserPort for it Mines dc.l DEFAULT_MINES ; Number of mines MinerX dc.w 0 ; X position of the tank (from 0 to width-1) MinerY dc.w 0 ; Y position of the tank (from 0 to height-1) Width dc.l DEFAULT_WIDTH ; Width (in columns) Height dc.l DEFAULT_HEIGHT ; Height (in lines) PlayX dc.l 0 ; Graphic offset for the playfield PlayY dc.l 0 Mines.Array dcb.b MAX_WIDTH*MAX_HEIGHT,0 ; Array containing the posi- ; tions of the mines. Not that it may be that only a part of it is used as ; Width and Height may not be equal to MAX_WIDTH and MAX_HEIGHT FinishFlag dc.b 0 ; Flag set when the game is over section Images,DATA_C ; These are some structures that need to be in CHIP-ram: Tank.Image ; Image structure for the tank dc.w 0,0 ; LeftEdge,TopEdge dc.w 16,8 ; Width,Height dc.w 2 ; Depth: 4 colours dc.l Tank.ImageData ; Data for the picture dc.b $0003,$0000 ; Patterns used for rendering in bitplanes dc.l 0 ; Next Image structure:none Tank.ImageData dc.w $0000,$001F,$0000,$7FFE,$FFFF,$FFFF,$FFFF,$7FFE ; Data for the first bitplane dc.w $07C0,$0FE0,$0FE0,$7FFE,$FFFF,$8001,$7FFE,$0000 ; Data for the second bitplane Mine.Image ; Image structure for a mine dc.w 0,0 dc.w 16,8 dc.w 2 dc.l Mine.ImageData dc.b $0001,$0000 dc.l 0 Mine.ImageData dc.w $0000,$0000,$0000,$0000,$0FF0,$7FFE,$7FFE,$0000 ; Only one bitplane here Target.Image ; Image structure for the target dc.w 0,0 dc.w 16,8 dc.w 2 dc.l Target.ImageData dc.b $0003,$0000 dc.l 0 Target.ImageData dc.w $07E0,$0FF0,$1FF8,$3E7C,$3E7C,$1FF8,$0FF0,$07E0 dc.w $07E0,$0C30,$1818,$318C,$318C,$1818,$0C30,$07E0