; YAMFG 1.0 - ©1993 F.Delacroix- FreeWare
; écrit sur le Devpac 3 d'Hisoft

; tous les includes system ont été ajoutés au moment de l'as-
; semblage grâce à un fichier .gs de Devpac 3. Si vous utili-
; sez un autre assembleur,ajoutez-les manuellement.

	include	exec/execbase.i		; d'autres includes: struct ExecBase
	include	hardware/custom.i	; custom hardware: nombres aléatoires
	include	libraries/reqtools.i	; includes pour reqtools.library
	include	libraries/reqtools_lib.i

DEFAULT_WIDTH	EQU	20	; constantes utiles: évidentes
DEFAULT_HEIGHT	EQU	20
DEFAULT_MINES	EQU	40
MAX_WIDTH	EQU	24
MAX_HEIGHT	EQU	21
UP	EQU	$4c		; touches utilisées pour bouger le tank
DOWN	EQU	$4d
RIGHT	EQU	$4e
LEFT	EQU	$4f
STATUSX	EQU	4	; coordonnées pour la ligne status
STATUSY	EQU	18

	move.l	4.w,a6
	move.l	ThisTask(a6),a4	;trouve la tâche (même chose que FindTask(0))
	moveq	#0,d0
	tst.l	pr_CLI(a4)	; venons-nous du CLI ?
	bne.s	FromCLI	; oui...
	lea	pr_MsgPort(a4),a0	; non: allons chercher le message
	jsr	_LVOWaitPort(a6)	; WBStartup envoyé par le Workbench
	lea	pr_MsgPort(a4),a0
	jsr	_LVOGetMsg(a6)
FromCLI	move.l	d0,WBStarter	; et rangeons-le (0 pour le CLI)

	lea	ReqTools.Name(pc),a1	; ouvrons la reqtools.library
	moveq	#0,d0
	jsr	_LVOOpenLibrary(a6)
	move.l	d0,ReqTools.Base
	beq	OutOfHere	; pas de reqtools.library: fin du programme

	move.l	ReqTools.Base(pc),a0	; et prenons-y les bases des autres
	move.l	rt_IntuitionBase(a0),Intuition.Base	; bibliothèques
	move.l	rt_GfxBase(a0),Graphics.Base

	lea	YAMFG.NewWindow(pc),a0	; ouvrons la fenêtre
	move.l	Intuition.Base(pc),a6
	jsr	_LVOOpenWindow(a6)
	move.l	d0,YAMFG.Window
	beq	CloseReqTools	; pas de fenêtre !

	move.l	YAMFG.Window(pc),a0	; attachons les menus à la fenêtre
	lea	Project.Menu(pc),a1
	jsr	_LVOSetMenuStrip(a6)
	tst.l	d0
	beq	CloseWindow	; raté ! (ne devrait pas arriver)

	move.l	YAMFG.Window(pc),a0	; données importantes pour la fenêtre
	move.l	wd_RPort(a0),YAMFG.RastPort	; RastPort pour les graphismes
	move.l	wd_UserPort(a0),YAMFG.UserPort	; UserPort pour les messages
	bra	NewGame	; commençons une nouvelle partie

WaitMessage
	move.l	YAMFG.UserPort(pc),a0	; attends un message envoyé par
	move.l	4.w,a6			; Intuition à notre fenêtre...
	jsr	_LVOWaitPort(a6)
NextMessage
	move.l	YAMFG.UserPort(pc),a0	; et vas le chercher!
	move.l	4.w,a6
	jsr	_LVOGetMsg(a6)
	tst.l	d0
	beq.s	WaitMessage	; Y en a-t-il vraiment un ?
	move.l	d0,a1		; Oui !
	move.l	im_Class(a1),d7		; Sauve les champs importants:Classe
	move.w	im_Code(a1),d6		; et Code
	jsr	_LVOReplyMsg(a6)	; et réponds à Intuition
	cmp.l	#IDCMP_CLOSEWINDOW,d7	; Devons-nous quitter ?
	beq	ClearMenus		; Oui? Alors partons...
	cmp.w	#IDCMP_RAWKEY,d7	; A-t-on appuyé sur une touche?
	bne	NoRawKey
	btst	#IECODEB_UP_PREFIX,d6	; ignore si une touche a été lachée
	bne	NextMessage
	tst.b	FinishFlag	; Le jeu est-il terminé ?
	bne	NewGame		; oui? alors commence une nouvelle partie
	move.w	MinerX(pc),d0	; non: prend la position du tank
	move.w	MinerY(pc),d1

	cmp.w	#UP,d6		; Haut ?
	beq.s	GoUp
	cmp.w	#DOWN,d6	; Bas ?
	beq.s	GoDown
	cmp.w	#RIGHT,d6	; Droite ?
	beq.s	GoRight
	cmp.w	#LEFT,d6	; Ou gauche ?
	bne	NextMessage	; Rien de cela ?? alors prochain message

	subq.w	#1,d0		; 1 case à gauche
	bra.s	DirectionGot
GoRight	addq.w	#1,d0		; 1 case à droite
	bra.s	DirectionGot
GoDown	addq.w	#1,d1		; 1 case en bas
	bra.s	DirectionGot
GoUp	subq.w	#1,d1		; 1 case en haut

DirectionGot
	bsr	CheckBounds	; voyons si le tank ne sort pas des limites
	bsr	MoveMiner	; puis déplaçons-le
	move.l	Width(pc),d0	; le tank est-il sur le bord droit ?
	subq.l	#1,d0
	cmp.w	MinerX(pc),d0
	bne.s	NoGoal
	move.l	Height(pc),d0	; le tank est-il en bas ?
	subq.l	#1,d0
	cmp.w	MinerY(pc),d0
	bne.s	NoGoal		; oui ! le but est atteint ! (Félicitations!)
	lea	Won.MSG(pc),a0	; Affiche le message de fin
	bra.s	EndOfGame	; et termine le jeu

NoGoal	moveq	#0,d0		; But pas encore atteint
	move.w	MinerY(pc),d0	; Transforme la position du tank en un offset
	mulu	Width+2(pc),d0	; pour la matrice: offset=Width*Y+X
	add.w	MinerX(pc),d0
	lea	Mines.Array(pc),a2
	tst.b	(a2,d0)		; Regarde si le tank est sur une mine
	beq.s	ShowNumber	; Non!!

	lea	Lost.MSG(pc),a0	; Uh-Oh: une mine !
EndOfGame
	st	FinishFlag	; Le jeu est terminé
	bsr	DisplayStatus	; Affiche le message de fin (gagné ou perdu)
	bsr	RevealMines	; et révèle la position des mines
	bra	NextMessage	; Reboucle
NewGame
	clr.b	FinishFlag	; Quand un jeu commence,il n'est pas fini
	move.l	YAMFG.RastPort(pc),a1
	moveq	#RP_JAM2,d0
	move.l	Graphics.Base(pc),a6
	jsr	_LVOSetDrMd(a6)	; mode de dessin:RP_JAM2 (deux couleurs)
	move.l	YAMFG.RastPort(pc),a1
	moveq	#0,d0
	jsr	_LVOSetAPen(a6)	; choisit couleur 0
	move.l	YAMFG.RastPort(pc),a1
	move.l	#4,d0	; dessine un gros rectange pour effacer l'affichage
	move.l	#12,d1
	move.l	#396,d2
	move.l	#196,d3
	jsr	_LVORectFill(a6)
	bsr	DrawMinesBorder	; dessine un border autour de l'aire de jeu
	bsr	PlaceMines	; Génère les positions aléatoires des mines
	clr.w	MinerX	; Place le tank dans le coin supérieur gauche
	clr.w	MinerY
	bsr	ShowMiner	; dessine le tank

ShowNumber
	lea	Mines.Array(pc),a2
	moveq	#0,d0
	move.w	MinerY(pc),d0	; change la position du tank en offset
	mulu	Width+2(pc),d0
	add.w	MinerX(pc),d0
	add.l	d0,a2		; position du tank dans la matrice
	moveq	#0,d1
	move.l	Width(pc),d3	; d3=Largeur de l'aire de jeu
	move.l	Height(pc),d4
	move.l	d3,d5		; d5=Largeur-1
	subq.l	#1,d5
	subq.l	#1,d4		; d4=Hauteur-1
	move.l	d3,d6
	neg.l	d6		; d6=-Largeur
	tst.w	MinerY		; tank sur le bord haut ?
	beq.s	No9		; oui? alors ne teste pas au-dessus!
	tst.b	(a2,d6.l)	; mine en position 8 ?
	beq.s	No8		; note: Je suis ces conventions dans le
	addq.l	#1,d1		; source: 789
No8	tst.w	MinerX		;         4 6
	beq.s	No7		;         123
	tst.b	-1(a2,d6.l)	; si la grille dans la position testée (par
	beq.s	No7		; ordre d'apparition:8,7,9,4,6,1,2,3) ne
	addq.l	#1,d1		; contient pas zero,alors il y a une mine,et
No7	cmp.w	MinerX(pc),d5	; Le compteur de mines (d1) est incrémenté
	beq.s	No9		; Bien sûr,si la position n'existe pas
	tst.b	1(a2,d6.l)	; (si le tank est sur un bord de l'aire de
	beq.s	No9		; jeu),la position n'est pas testée.
	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	; change le compteur de mines en un chiffre affichable
	move.b	d1,Mines.Number	; et range-le pour l'afficher
	lea	MinesNumber.MSG(pc),a0	; Le message 'Mines around you'
	bsr	DisplayStatus	; affiche-le!
	bra	NextMessage	; prochaine action du joueur...

NoRawKey
	cmp.l	#IDCMP_MENUPICK,d7	; un menu sélectionné ?
	bne	NextMessage	; non: ignore ce message étrange!
DoNextSelect
	move.w	d6,d0		; le menu number donné par Intuition
	lea	Project.Menu(pc),a0	; notre barre de menu
	move.l	Intuition.Base(pc),a6
	jsr	_LVOItemAddress(a6)	; adresse du MenuItem choisi
	move.l	d0,a5
	tst.l	d0	; y en a-t-il vraiment un ?
	beq	NextMessage	; Non: fin du traitement des menus
	move.w	mi_NextSelect(a5),d6	; stocke le menunumber suivant
	move.l	mi_SIZEOF(a5),a1	; Ceci est un champ non standard de
	cmp.l	#0,a1	; la structure MenuItem:  la routine à executer...
	beq	DoNextSelect	; si il y en a une bien sûr
	jsr	(a1)	; execute-la !
	bra.s	DoNextSelect	; puis examine la sélection suivante

ClearMenus	; Temps de quitter le jeu !!
	move.l	YAMFG.Window(pc),a0	; retire les menus de la fenêtre
	move.l	Intuition.Base(pc),a6
	jsr	_LVOClearMenuStrip(a6)
CloseWindow
	move.l	YAMFG.Window(pc),a0	; ferme la fenêtre
	move.l	Intuition.Base(pc),a6
	jsr	_LVOCloseWindow(a6)
CloseReqTools
	move.l	ReqTools.Base(pc),a1	; ferme la reqtools.library
	move.l	4.w,a6
	jsr	_LVOCloseLibrary(a6)
OutOfHere
	move.l	WBStarter(pc),d1	; venons-nous du Workbench ?
	beq.s	BackToCLI	; non: plus rien à faire
	jsr	_LVOForbid(a6)	; oui: nous devons répondre au message
	move.l	d1,a1	; WBStartup que nous avons reçu au début
	move.l	4.w,a6		; notez que Forbid() est absolument nécessaire
	jsr	_LVOReplyMsg(a6)
BackToCLI
	moveq	#0,d0	; pour que le CLI n'affiche pas d'étranges codes
	rts	; C'est la triste fin ...

; sous-routine qui initialise quelques variables d'affichage et dessine
; un bord rectangulaire et affiche l'image de la cible
DrawMinesBorder
	movem.l	d0-d1/a0-a1/a6,-(sp)
	move.l	Width(pc),d0	; Largeur en pixels=Largeur*16
	lsl.l	#4,d0
	move.l	Height(pc),d1	; Hauteur en pixels=Hauteur*8
	lsl.l	#3,d1
	addq.l	#1,d0
	addq.l	#1,d1
	move.w	d0,Border.Right1	; stocke ces valeurs pour dessiner
	move.w	d0,Border.Right2	; le cadre
	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	; le RastPort de la fenêtre
	lea	YAMFG.Border(pc),a1	; la structure Border
	move.l	Width(pc),d0	; Calcule la variable PlayX pour centrer
	lsl.l	#3,d0	; l'aire de jeu: 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	; Calcule PlayY de façon similaire
	lsl.l	#2,d1	; PlayY=(200-Height*8)/2=100-Height*4
	neg.l	d1
	add.l	#100,d1
	addq.l	#3,d1	; et ajoute 3 pixels
	cmp.l	#STATUSY+4,d1	; mais ne déborde pas sur la ligne de status
	bge.s	NotTooLow
	move.l	#STATUSY+4,d1	; Si c'est le cas,descends un peu
NotTooLow
	move.l	d1,PlayY
	move.l	Intuition.Base(pc),a6
	jsr	_LVODrawBorder(a6)	; Dessine-le,ce cadre
	move.l	YAMFG.RastPort(pc),a0	; Nécessaire pour tous les graphismes
	lea	Target.Image,a1	; La structure image pour la cible
	move.l	Width(pc),d0	; position X Y de la cible
	subq.l	#1,d0	; dans le coin inférieur droit
	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)	; Intuition la dessine.
	movem.l	(sp)+,d0-d1/a0-a1/a6
	rts

; ceci est la routine qui place aléatoirement les mines dans la grille
; il n'est PAS garanti qu'il y ait moyen de passer si les mines sont trop
; nombreuses. La routine utilise un algorythme FastRand() classique,avec
; la position du raster pour graine
PlaceMines
	movem.l	d0/d3-d5/a2,-(sp)
	lea	Mines.Array(pc),a2	; grille à remplir
	move.l	Width(pc),d0
	mulu	Height+2(pc),d0	; Taille de la grille
	move.l	d0,d3
	subq.l	#1,d0	; une boucle dbra décompte jusqu'à -1
ClearMines
	clr.b	(a2)+	; enlève toutes les mines de la grille
	dbra	d0,ClearMines
	moveq	#0,d5
	move.w	$DFF000+vhposr,d5	; obtient la graine de la position raster
	lea	Mines.Array(pc),a2	; récupère a2
	move.l	Mines(pc),d4	; nombre de mines à placer
	cmp.l	d4,d3	; est-ce possible ??
	bgt.s	AnotherRandom	; oui
	move.l	d3,d4	; il y a beaucoup trop de mines !! Réduis leur nombre
	subq.l	#4,d4	; c'est seulement une sécurité:qui jouerait une partie
AnotherRandom		; où chaque mouvement est perdu ?
	add.l	d5,d5	; Voici la routine FastRand() qui génère une série
	bhi.s	.NoEOR	; de nombres apparamment aléatoire
	eor.l	#$1D872B41,d5	; Pourquoi ce nombre ? Bonne question.
.NoEOR
	moveq	#0,d0	; divise le nombre aléatoire par la taille de la
	move.w	d5,d0	; grille pour que le reste soit une position valide
	divu	d3,d0
	swap	d0
	tst.w	d0	; Pas de mine dans le coin supérieur gauche
	beq	AnotherRandom
	tst.b	(a2,d0.w)	; Y a-t-il déjà une mine ici ?
	bne.s	AnotherRandom	; Oui?? Alors utilise un autre offset
	move.b	#1,(a2,d0.w)	; Non: maintenant y en a une
	subq	#1,d4	; Etait-ce la dernière mine à placer ?
	bne	AnotherRandom	; Non.
	movem.l	(sp)+,d0/d3-d5/a2	; Oui: récupère les registres et
	rts	; retourne

; Ceci affiche le tank..
ShowMiner
	movem.l	d0-d1/a0-a1/a6,-(sp)
	move.l	YAMFG.RastPort(pc),a0
	lea	Tank.Image,a1	; Structure image pour le 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)	; Dessine-le. Facile non?
	movem.l	(sp)+,d0-d1/a0-a1/a6
	rts

; Ceci regarde si le tank est sorti des limites,auquel cas il est remis sur
; le bord de la grille. Cette routine est appelée avec la nouvelle position
; souhaitée en D0 et D1 (X et Y respectivement).
CheckBounds
	ext.l	d0	; Change l'abscisse en un mot long
	cmp.l	Width(pc),d0	; Trop loin sur la droite ?
	blt.s	NotRightEdge
	move.l	Width(pc),d0
	subq.l	#1,d0
NotRightEdge
	tst.l	d0		; Trop loin sur la gauche ?
	bge.s	NotLeftEdge
	moveq	#0,d0
NotLeftEdge
	ext.l	d1	; Change l'ordonnée en un mot long
	tst.l	d1		; Trop haut ?
	bge.s	NotUpEdge
	moveq	#0,d1
NotUpEdge
	cmp.l	Height(pc),d1	; Trop bas ?
	blt.s	NoDownEdge
	move.l	Height(pc),d1
	subq.l	#1,d1
NoDownEdge
	rts

; Cette routine efface l'image du tank et la redessine à la position donnée
; par D0 et D1 (X et Y). Elle actualise aussi les variables MinerX et MinerY
MoveMiner
	bsr.s	EraseMiner
	move.w	d0,MinerX
	move.w	d1,MinerY
	bra	ShowMiner

; Ceci efface l'image du tank en affichant deux espaces en couleur 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	; Ajoute 6 à la position Y pour la ligne de base
	move.l	Graphics.Base(pc),a6	; de la fonte topaz standard.
	jsr	_LVOMove(a6)	; Déplace le curseur graphique
	move.l	YAMFG.RastPort(pc),a1
	moveq	#3,d0	; couleur B égale 3 (orange ou bleu sur les Workbenchs
	jsr	_LVOSetBPen(a6)	; normalement colorés)
	move.l	YAMFG.RastPort(pc),a1
	moveq	#RP_JAM2,d0	; drawmode: RP_JAM2 pour que les espaces
	jsr	_LVOSetDrMd(a6)	; soient réellement en bleu
	lea	Space.Text(pc),a0
	move.l	YAMFG.RastPort(pc),a1
	moveq	#2,d0	; Il y en a deux
	jsr	_LVOText(a6)
	movem.l	(sp)+,d0-d1/a0-a1/a6
	rts	; That's it

; Cette routine sert à effacer la ligne status. Elle est appelée par 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: RP_JAM2
	move.l	YAMFG.RastPort(pc),a1
	moveq	#0,d0	; couleur A= 0
	jsr	_LVOSetAPen(a6)
	move.l	YAMFG.RastPort(pc),a1
	move.l	#STATUSX,d0	; coordonnées pour le rectangle qui sera des-
	move.l	#STATUSY-6,d1	; siné par dessus la ligne status
	move.l	#STATUSX+40*8,d2
	move.l	#STATUSY+2,d3
	jsr	_LVORectFill(a6)	; dessine le rectangle
	movem.l	(sp)+,d0-d3/a0-a1/a6
	rts

; Cette routine affiche un message dans la ligne status,auparavant effacée.
; A0 est un pointeur sur le message à afficher.
DisplayStatus:			;DisplayStatus(Message)(A0)
	movem.l	d0-d1/a0-a2/a6,-(sp)
	bsr	EraseStatus	; Efface d'abord la ligne status
	move.l	a0,a2	; Sauve le pointeur sur le message (A2 est obligatoi-
	move.l	YAMFG.RastPort(pc),a1	; rement préservé par les librairies)
	moveq	#RP_JAM1,d0
	move.l	Graphics.Base(pc),a6
	jsr	_LVOSetDrMd(a6)	; drawmode: RP_JAM1: seule la couleur A est
	move.l	YAMFG.RastPort(pc),a1	; utilisée.
	moveq	#1,d0
	jsr	_LVOSetAPen(a6)	; Couleur A=1 (normalement noir ou blanc)
	move.l	YAMFG.RastPort(pc),a1
	move.l	#STATUSX,d0	; Coordonnées de la ligne status
	move.l	#STATUSY,d1
	jsr	_LVOMove(a6)	; déplace le curseur graphique
	move.l	a2,a0
.LenLoop		; compte la longueur du message
	tst.b	(a2)+	; nécessaire pour la fonction Text()
	bne	.LenLoop
	sub.l	a0,a2
	subq.l	#1,a2
	move.l	a2,d0
	move.l	YAMFG.RastPort(pc),a1
	jsr	_LVOText(a6)	; affiche le texte
	movem.l	(sp)+,d0-d1/a0-a2/a6
	rts

; Cette routine révèle l'emplacement des mines,appelée quand le jeu est
; terminé (le joueur a gagné ou perdu)
RevealMines
	movem.l	d0-d3/a0-a2/a6,-(sp)
	lea	Mines.Array(pc),a2	; La grille des mines
	moveq	#-1,d2		; La position actuelle dans la grille
	move.l	Intuition.Base(pc),a6
	move.l	Width(pc),d3
	mulu	Height+2(pc),d3	; d3 est la taille de la grille
RevealLoop
	addq.l	#1,d2	; incrémente la position
	cmp.l	d3,d2	; havons nous atteint la fin de la grille ?
	beq.s	EndOfReveal	; oui...alors fini.
	tst.b	(a2)+	; y a-t-il une mine ici ?
	beq.s	RevealLoop	; Non, position suivante
	move.l	d2,d0	; oui! sa position est en D0
	divu	Width+2(pc),d0	; pour séparer les coordonnées X et Y
	moveq	#0,d1	; abscisse (le reste de la division) en D0
	move.w	d0,d1	; ordonnée en D1 (le quotient de la division)
	clr.w	d0
	swap	d0
	move.l	YAMFG.RastPort(pc),a0
	lea	Mine.Image,a1	; structure Image pour une mine
	lsl.l	#4,d0	; Change X et Y de la grille en véritable coordonnées
	lsl.l	#3,d1	; graphiques
	add.l	PlayX(pc),d0
	add.l	PlayY(pc),d1
	jsr	_LVODrawImage(a6)	; Dessine une mine
	bra	RevealLoop	; contine avec les autres positions
EndOfReveal
	movem.l	(sp)+,d0-d3/a0-a2/a6	; toutes les mines affichées,on a
	rts	; fini notre travail

; Cette routine est appelée quand le menu correspondant est sélectionné
QuitYAMFG
	addq.l	#4,sp	; Pas de retour pour cette routine
	bra	ClearMenus	; Nous partons!

; Appelé quand le joueur a chois 'About' dans les menus
ShowAbout
	movem.l	d0-d1/a0-a4/a6,-(sp)
	lea	About.Body(pc),a1	; message principal
	lea	About.Gad(pc),a2	; Texte pour le gadget
	suba.l	a3,a3	; pas de structure ReqInfo
	move.l	a3,a4	; et pas de formattage
	lea	About.TagList(pc),a0	; TagList spécifique
	move.l	ReqTools.Base(pc),a6	; Laissons la reqtools.library
	jsr	_LVOrtEZRequestA(a6)	; le faire...
	movem.l	(sp)+,d0-d1/a0-a4/a6
	rts

; Quand l'utilisateur veut changer le nombre de mines (avec le menu)
ModifyMines
	lea	Mines(pc),a1	; Variable qui contient le nombre de mines
	lea	HowManyMines.Title(pc),a2	; Titre pour le requester
	suba.l	a3,a3	; pas de ReqInfo
	lea	Mines.TagList(pc),a0	; mais quelques tags...
	move.l	ReqTools.Base(pc),a6	; Demande le nombre de mines
	jsr	_LVOrtGetLongA(a6)
	tst.l	d0	; l'utilisateur a entré un nombre valide ?
	bne.s	NewMines	; oui, nouvelle partie
	rts	; non, requester annulé

; Il veut changer la largeur de l'aire de jeu
ChangeWidth
	lea	Width(pc),a1	; Variable pour la largeur
	lea	Width.Title(pc),a2	; Titre du requester
	sub.l	a3,a3
	lea	Width.TagList(pc),a0	; quelques tags...
	move.l	ReqTools.Base(pc),a6
	jsr	_LVOrtGetLongA(a6)	; Nouvelle largeur demandée
	tst.l	d0
	bne.s	NewWidth	; Nouvelle partie si c'est valide
	rts	; retourne si le requester a été annulé
NewMines	; un branch pour les routines qui nécessitent une nouvelle
NewWidth	; partie
NewHeight
	addq.l	#4,sp	; corrige la pile pour l'adresse de retour
	bra	NewGame	; et branche sur le programme principal

; Exactement la même routine que ChangeWidth(). Je ne crois pas que des
; commentaires soient nécessaires.
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

; Cette partie contient des données pour les fenêtres,menus,messages,et
; quelques petites choses diverses.
YAMFG.NewWindow	; la structure NewWindow
	dc.w	120,0	; origine XY
	dc.w	400,200	; Largeur et hauteur en pixels
	dc.b	0,1	; couleurs FrontPen et BackPen
	dc.l	IDCMP_CLOSEWINDOW!IDCMP_RAWKEY!IDCMP_MENUPICK
; La ligne ci-dessus contient les flags IDCMP, un message sera envoyé par
; Intuition à notre programme quand ces évenements arriveront.
	dc.l	WINDOWDRAG!WINDOWDEPTH!WINDOWCLOSE!ACTIVATE!NOCAREREFRESH
; Ce sont des flags standards pour les fenêtres. Il n'y a pas de flag exo-
; tique,ils sont évidents par leur nom,vous devriez les comprendre vous-
; même,donc pas besoin de commentaires supplémentaires, alors pourquoi
; est-ce que je vous ennuie avec ça ?
	dc.l	0	; Pas de gadgets sur cette fenêtre
	dc.l	0	; Pas de CheckMark particulier (on n'en utilise même pas)
	dc.l	YAMFG.WindowName	; Nom de notre fenêtre
	dc.l	0	; Ecran: on se contentera de celui du Workbench
	dc.l	0	; Bitmap: pas de bitmap.
	dc.w	400,200	; dimensions minimales (inutiles ici)
	dc.w	400,200	; dimensions maximales (idem)
	dc.w	WBENCHSCREEN	; oui,l'écran du workbench

YAMFG.Border	; structures Border pour le rectangle autour de l'aire de jeu
	dc.w	-1,-1	; origine XY
	dc.b	1,0,RP_JAM1,3	; FontPen,BackPen,DrawMode,Nombre de vecteurs
	dc.l	YAMFG.Vectorsa,YAMFG.Borderb	; Vecteurs,border suivant
YAMFG.Borderb
	dc.w	-1,-1		; on utilise 2 borders pour créer un effet
	dc.b	2,0,RP_JAM1,3	; de pseudo-3D (un coté en blanc,l'autre en
	dc.l	YAMFG.Vectorsb,0	; noir)

YAMFG.Vectorsa	; Les coordonnées pour les vecteurs du premier border
	dc.w	0	; Certaines seront changées par le programme.
Border.Bot1
	dc.w	DEFAULT_HEIGHT*8+1
	dc.w	0,0
Border.Right1
	dc.w	DEFAULT_WIDTH*16+1,0

YAMFG.Vectorsb	; Même chose pour le 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	; Voici la structure menu pour le menu project
	dc.l	Options.Menu	; Menu suivant: 'Options'
	dc.w	0,0	; Bord gauche et haut
	dc.w	63,0	; Largeur et hauteur (Hauteur inutilisée)
	dc.w	MENUENABLED	; Flags: le menu est autorisé
	dc.l	Project.Name	; devinez ce que c'est
	dc.l	About.MenuItem	; Premier item de ce menu
	dc.w	0,0,0,0	; variables Intuition mystérieuses

About.MenuItem	; structure MenuItem pour l'item 'About'
	dc.l	Quit.MenuItem	; Item suivant
	dc.w	0,0	; Bord gauche,Bord haut
	dc.w	104,8	; Largeur,Hauteur
	dc.w	ITEMTEXT!COMMSEQ!ITEMENABLED!HIGHCOMP	; menu flags:
; ITEMTEXT signifie qu'une structure IntuiText sera utilisée (ç'aurait pu
; être une Image),COMMSEQ signifie qu'il y a un raccourci clavier,ITEMENABLED
; que l'item peut être sélectionné,HIGHCOMP dit à Intuition d'inverser les
; couleurs du menu si le pointeur de souris passe dessus
	dc.l	0	; Pas d'exclusion mutuelle
	dc.l	About.IText	; Render: une structure IntuiText
	dc.l	0	; Pas de rendering pour l'état sélectionné
	dc.b	'A'	; Raccourci clavier
	dc.b	0	; Un octet de remplissage pour avoir une adresse paire
	dc.l	0	; pas de liste de SubItems
	dc.w	MENUNULL	; sera rempli par Intuition pour la sélection
; étendue
	dc.l	ShowAbout	; Champ non standard,utilisé par le prog
; pour determiner la routine à executer quand le menu est sélectionné
About.IText	; Une structure IntuiText pour le MenuItem
	dc.b	3,1,RP_COMPLEMENT,0	; DetailPen,BlockPen,DrawMode,FillByte
	dc.w	0,0	; Bord gauche,Bord haut
	dc.l	0	; fonte par défaut
	dc.l	About.MSG	; Message
	dc.l	0	; Pas d'autre structure IntuiText

; Les autres Menus et MenuItems sont faits de la même façon,ce serait une
; perte de temps de tous les décrire.

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	; Les tags pour le requester "about"
	dc.l	RT_IDCMPFlags,IDCMP_MOUSEBUTTONS!INACTIVEWINDOW
; Des flags IDCMP supplémentaires pour réagir
	dc.l	RTEZ_Flags,EZREQF_CENTERTEXT	; Centre le texte
	dc.l	TAG_END

Mines.TagList	;Tags pour le requester "nombre de mines"
	dc.l	RTGL_Min,1	; Minimum 1
	dc.l	RTGL_Max,100	; Maximum 100
	dc.l	TAG_END

Width.TagList	; Pour le requester de la largeur
	dc.l	RTGL_Min,4	; Minimum 4
	dc.l	RTGL_Max,MAX_WIDTH	; Maximum
	dc.l	TAG_END

Height.TagList	; Pour le requester de la hauteur
	dc.l	RTGL_Min,4	; Minimum
	dc.l	RTGL_Max,MAX_HEIGHT	; Maximum
	dc.l	TAG_END

Project.Name	; Pas besoin de commentaires
	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	; Nom de la reqtools.library
Space.Text
	dc.b	'  '	; Utilisé pour effacer l'image du tank
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 reçu (0 si CLI)
Graphics.Base	dc.l	0	; Base de la graphics.library
Intuition.Base	dc.l	0	; Base de l'intuition.library
ReqTools.Base	dc.l	0	; Base de la reqtools.library
YAMFG.Window	dc.l	0	; structure Window (pas NewWindow)
YAMFG.RastPort	dc.l	0	; RastPort de notre fenêtre
YAMFG.UserPort	dc.l	0	; Son UserPort
Mines	dc.l	DEFAULT_MINES	; Nombre de mines
MinerX	dc.w	0	; Abscisse du tank (de 0 à width-1)
MinerY	dc.w	0	; Ordonnée du tank (de 0 à height-1)
Width	dc.l	DEFAULT_WIDTH	; Largeur (en colonnes)
Height	dc.l	DEFAULT_HEIGHT	; Hauteur (en lignes)
PlayX	dc.l	0	; Offset graphique pour l'aire de jeu
PlayY	dc.l	0
Mines.Array	dcb.b	MAX_WIDTH*MAX_HEIGHT,0	; Matrice qui contient les
; positions des mines. Notez que seule une partie sera utilisé car Width et
; Height peuvent ne pas être MAX_WIDTH et MAX_HEIGHT
FinishFlag	dc.b	0	; Flag mis quand le jeu est terminé

	section	Images,DATA_C
; Voici des structures qui doivent être en CHIP-ram:
Tank.Image	; structure Image pour le tank
	dc.w	0,0	; Bord gauche,Bord haut
	dc.w	16,8	; Largeur,Hauteur
	dc.w	2	; Profondeur: 4 couleurs
	dc.l	Tank.ImageData	; Données pour l'image
	dc.b	$0003,$0000	; Modèles pour les bitplanes
	dc.l	0	; Image suivante:aucune
Tank.ImageData
	dc.w	$0000,$001F,$0000,$7FFE,$FFFF,$FFFF,$FFFF,$7FFE
; Données pour le premier bitplane
	dc.w	$07C0,$0FE0,$0FE0,$7FFE,$FFFF,$8001,$7FFE,$0000
; Données pour le second bitplane

Mine.Image	; Structure Image pour une 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
; Un seul bitplane ici

Target.Image	; Structure Image pour la cible
	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

