; 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

