.model small .stack data segment ; TABELLA ; ____ ; 111_ ; 2M1_ ; M21_ ; ; UTILIZZO BIT TABELLA ; n0 ; n1 ; n2 ; n3 ; 0 ; mina (1:mina ; 0:non-mina) ; bandiera (1:bandiera ; 0:non-bandiera ; visibile (1:visibile ; 0:non-visibile ; latabella DB 0,0,0,0, 1,1,1,0, 2,32,1,0, 32,2,1,0 ;tabella di prova latabella DB 0,0,0,0,0,0, 1,1,1,0,0,0, 2,32,1,0,0,0, 32,3,1,0,1,1, 32,2,0,0,1,32, 1,1,0,0,1,1 vnumero EQU 00001111b ;maschera controllo numero vmina EQU 00100000b ;maschera controllo mina vbandiera EQU 01000000b ;maschera controllo bandiera vvisibile EQU 10000000b ;maschera controllo visibilità nvbandiera EQU 10111111b ;maschera not_bandiera mousebut DB 00h tabx DB ? taby DB ? tabifrommouse DB ? nmine DB 04h ncelle DB 24h ncellelib DB 20h nbandiere DB 04h nrighe DB 06h ncolonne DB 06h FORE EQU 0Bh BACK EQU 01h perso DB "Hai PERSO!!!$" vinto DB "Hai vinto! Complimenti!$" nomouse DB "Impossibile inizializzare il mouse! Il programma termina qui!$" quit DB "Grazie per aver giocato! Alla prossima!$" data ends .code ;**************************************************************; ;PROCEDURE E MACRO ; ;**************************************************************; ;CANCELLA LO SCHERMO clrscr MACRO push ax mov ax,0003h int 10h pop ax ENDM ;VA A CAPO acapo MACRO n LOCAL ciclo push ax push dx push cx xor cx,cx mov ah,02h mov cl,n ciclo: mov dl,0dh int 21h mov dl,0ah int 21h loop ciclo pop cx pop dx pop ax ENDM getmouseevt MACRO LOCAL ciclo pusha mov ax,0003h ciclo: int 33h cmp bx,00h je ciclo ; finchè non premo un tasto, ripeto il test mov mousebut,bl ; pulsanti premuti (0=nessuno, 1=left,2=right,3=both) mov ax,cx mov bl,08h div bl mov tabx,al ; mousex/8= x della tabella mov ax,dx div bl mov taby,al ; mousey/8= y della tabella mov ah,00h mov bl,ncolonne mul bl add al,tabx mov tabifrommouse,al ; ((mousey/8)*ncelle)+tabx = indice totale nella tabella popa ENDM scrivic MACRO char,fore,back pusha mov ah,09h ; funzione 9h: scrive un carattere con attributi ; NB: se scrivo solo un carattere, il cursore NON SI SPOSTA! Quindi lo si sposta a mano.. mov al,char ; al=carattere ; bl: ; bit 7 : blink (ma non credo funzioni) ; bit 4-6 : back (solo bassa intensità) ; bit 0-3 : fore (tutti i colori possibili) mov bl,back shl bl,4 or bl,fore mov bh,00h mov cx,0001h ; cx = numero di ripetizioni del carattere int 10h ; scrive mov ah,03h ; funzione 03h : rileva la posizione del cursore int 10h ; dh=riga; dl=colonna inc dx ; mi muovo nella colonna successiva (dl+1) mov ah,02h ; funzione 02h: setta la posizione del cursore int 10h popa ENDM ;DISEGNA IL CAMPO DI GIOCO (non stampa le mine!) campo MACRO LOCAL ciclo,bandiera,numero,vuoto,invisibile,continua,fineciclo,visibile,mina pusha mov si,0 xor cx,cx mov cl,ncelle mov bl,ncolonne ; se lo metti qui, lo fai una volta sola per ciclo! ciclo: mov al,latabella[si] test al,vbandiera ;controlla se è una bandiera jz visibile ;salta se non è una bandiera scrivic "B",FORE,BACK jmp continua visibile: test al,vvisibile ;controlla se è visibile jz invisibile ;salta se è invisibile mina: test al,vmina jz numero scrivic 2,FORE,BACK jmp continua numero: and al,vnumero ;controlla se c'è un numero jz vuoto ;salta se non c'è un numero add al,30h scrivic al,FORE,BACK ;scrive il numero jmp continua vuoto: scrivic " ",FORE,BACK ;scrive lo spazio bianco jmp continua invisibile: scrivic 0dbh,FORE,BACK ;scrive la cella coperta continua: inc si ;guarda l'elemento successivo mov ax,si div bl ;divide l'indice per ncolonne cmp ah,00h ;controlla se il resto è zero jne fineciclo ;salta se c'è resto acapo 1h ;inizia una nuova linea fineciclo: loop ciclo ;ricomincia il ciclo popa ENDM ;RENDE VISIBILE IL CAMPO DA GIOCO rivela MACRO LOCAL ciclo,fine push ax push cx push si xor cx,cx xor si,si mov cl,ncelle ciclo: mov al,latabella[si] or al,vvisibile ; rendo visibile la cella (senza controllo..credo si perda di più facendo una cmp e un salto, piuttosto che un or bit a bit) and al,nvbandiera ; tolgo le bandiere.. (facendo l'and con "not_vbandiera" caricato in bl (anche qui stessa considerazione di cui sopra) mov latabella[si],al ;rendo la cella visibile fine: inc si ;passo all'elemento successivo loop ciclo pop si pop cx pop ax ENDM setflag MACRO LOCAL fine,setbandiera,set push si push ax mov si,tabifrommouse and si,00FFh ; tabifrommouse è un byte, si è una word..faccio l'and con 0000000011111111 per cancellare la parte alta mov al,latabella[si] test al,vbandiera jz setbandiera and al,nvbandiera ;tolgo la bandiera inc nbandiere jmp set setbandiera: cmp nbandiere,00h je fine or al,vbandiera ;aggiungo la bandiera dec nbandiere set: mov latabella[si],al fine: pop ax pop si ENDM ;**************************************************************; ;DESCRIZIONE FUNZIONI ; ;clrscr libera lo schermo ; ;acapo n va a capo di nlinee ; ;scrivi char scrive il carattere char ; ;campo disegna il campo di gioco ; ;rivela rende il campo di gioco interamente visibile ; ;cella gestisce la singola cella ;**************************************************************; ;**************************************************************; ;CODICE PROGRAMMA ; ;**************************************************************; lea ax,data mov ds,ax ;inizializzazione segmento dati mov ax,0000h int 33h cmp ax,0FFFFh jne errore_mouse mov ax,0001h int 33h ciclo: clrscr ;pulisce lo schermo campo ;disegna il campo di gioco getmouseevt mov al,mousebut cmp al,01h jne checkright ; inizio salvataggio parametri xor ax,ax mov al,tabifrommouse mov ah,ncellelib push ax push OFFSET latabella mov ah,nrighe mov al,ncolonne push ax mov ah,tabx mov al,taby push ax call check pop dx jc you_lose mov ncellelib,dh cmp dh,00h je you_win jmp ciclo checkright: cmp al,02h jne testexit setflag jmp ciclo testexit: cmp al,03h jge uscita jmp ciclo fine_gioco: clrscr rivela campo acapo 02h mov ah,09h int 21h mov ah,07h int 21h jmp fineprogramma errore_mouse: mov ah,09h lea dx,nomouse int 21h jmp fineprogramma uscita: acapo 2 mov ah,09h lea dx,quit int 21h fineprogramma: mov ah,4ch int 21h you_lose: lea dx,perso jmp fine_gioco you_win: lea dx,vinto jmp fine_gioco ; procedura che gestisce il tasto sinistro ; situazione stack dopo il push bp ; bp+4 : tabx-taby ; bp+6 : nrighe-ncolonne ; bp+8 : [latabella] ; bp+10 : ncellelib-tabifrommouse check PROC push bp mov bp,sp pusha mov si,[bp+8] ; in si metto l'indirizzo della tabella xor bx,bx mov bl,byte ptr [bp+10] ; in di metto l'indice della cella interessata (tabifrommouse) test si+bx,vbandiera ;testo se è una bandiera..se lo è, non faccio niente jnz fineproc test si+bx,vmina jz nomina stc ; se è una mina, setto il carryflag e salto subito fuori (viene testato solo dal main!) jmp fineproc nomina: mov al,si+bx ; in ax carico la cella corrispondente (che so non essere né mina, né bandiera) test al,vvisibile jnz fineproc ; se è visibile, mi fermo! or al,vvisibile ; la setto come visibile mov si+bx,al dec byte ptr [bp+11] ; ncellelib-=1 cmp byte ptr [bp+11],00h ; se le celle da liberare sono 0 e non ho ancora preso una mina..ho vinto! e salto fuori..è inutile fare i test sui vicini jne cont ; altrimenti, inzio la fase di test jmp fineproc cont: test ax,vnumero ; se è il numero zero, passo a controllare i vicini jz as jmp fineproc ; altrimenti ho finito as: mov bx,[bp+4] ; bh=tabx; bl=taby cmp bl,00h ; se y=0, alto non c'è je s cmp bh,00h ; se x=0, sinistra non c'è je aa dec bx ; y-1 (è equivalente a scrivere dec bl, ma usando bx, impiego meno cicli) dec bh ; x-1 mov al,[bp+10] sub al,cl dec al ; nuovo indice = ((y-1)*ncolonne) + (x-1) = vecchio_indice - ncolonne - 1 mov ah,byte ptr [bp+11] push ax ; salvo i parametri push [bp+8] push [bp+6] push bx ; al posto di tabx;taby salvo tabx-1;taby-1 call check ; controllo x-1,y-1 pop dx mov byte ptr [bp+11],dh aa: ; non controllo la y, perchè gia fatto prima. non controllo la x, perchè inutile mov bx,[bp+4] ; bh=tabx; bl=taby dec bl ; y-1 mov al,[bp+10] sub al,cl ; nuovo indice = ((y-1)*ncolonne) + (x) = vecchio_indice - ncolonne mov ah,byte ptr [bp+11] push ax ; salvo i parametri push [bp+8] push [bp+6] push bx ; al posto di tabx;taby salvo tabx;taby-1 call check ; controllo x,y-1 pop dx mov byte ptr [bp+11],dh ad: mov bx,[bp+4] ; bh=tabx; bl=taby mov cx,[bp+6] ; ch=nrighe; cl=ncolonne inc bh ; x+1 cmp bh,cl ; se x+1>=ncolonne, destra non c'è jge s dec bl ; y-1 mov al,[bp+10] sub al,cl inc al ; nuovo indice = ((y-1)*ncolonne) + (x+1) = vecchio_indice - ncolonne + 1 mov ah,byte ptr [bp+11] push ax ; salvo i parametri push [bp+8] push [bp+6] push bx ; al posto di tabx;taby salvo tabx+1;taby-1 call check ; controllo x+1,y-1 pop dx mov byte ptr [bp+11],dh s: mov bx,[bp+4] ; bh=tabx; bl=taby cmp bh,00h ; se x=0, sinistra non c'è je d dec bh ; x-1 mov al,byte ptr [bp+10] dec ax ; nuovo indice = tabifrommouse-1 mov ah,byte ptr [bp+11] push ax ; salvo i parametri push [bp+8] push [bp+6] push bx ; al posto di tabx;taby salvo tabx-1;taby call check ; controllo x-1,y pop dx mov byte ptr [bp+11],dh d: mov bx,[bp+4] ; bh=tabx; bl=taby mov cx,[bp+6] ; ch=nrighe; cl=ncolonne inc bh ; x+1 cmp bh,cl ; se x+1>=ncolonne, destra non c'è jge bs mov al,byte ptr [bp+10] inc ax ; nuovo indice = tabifrommouse+1 mov ah,byte ptr [bp+11] push ax ; salvo i parametri push [bp+8] push [bp+6] push bx ; al posto di tabx;taby salvo tabx+1;taby call check ; controllo x+1,y pop dx mov byte ptr [bp+11],dh bs: mov bx,[bp+4] ; bh=tabx; bl=taby mov cx,[bp+6] ; ch=nrighe; cl=ncolonne inc bl ; y+1 cmp bl,ch ; se y+1>=nrighe, giù non c'è jge fineproc ; se non c'è giù, ho finito.. cmp bh,00h ; se x=0, sinistra non c'è jmp bb dec bh ; x-1 mov al,[bp+10] add al,cl dec al ; nuovo indice = ((y+1)*ncolonne) + (x-1) = vecchio_indice + ncolonne - 1 mov ah,byte ptr [bp+11] push ax ; salvo i parametri push [bp+8] push [bp+6] push bx ; al posto di tabx;taby salvo tabx-1;taby+1 call check ; controllo x-1,y+1 pop dx mov byte ptr [bp+11],dh bb: mov bx,[bp+4] ; bh=tabx; bl=taby ; non controllo la y perchè già fatto, non controllo la x perchè inutile inc bl ; y+1 mov al,[bp+10] add al,cl ; nuovo indice = ((y+1)*ncolonne) + (x) = vecchio_indice + ncolonne mov ah,byte ptr [bp+11] push ax ; salvo i parametri push [bp+8] push [bp+6] push bx ; al posto di tabx;taby salvo tabx;taby+1 call check ; controllo x,y+1 pop dx mov byte ptr [bp+11],dh bd: mov bx,[bp+4] ; bh=tabx; bl=taby mov cx,[bp+6] ; ch=nrighe; cl=ncolonne inc bh cmp bh,cl ; se x+1>=ncolonne, destra non c'è jge fineproc ; non controllo la y perchè già fatto inc bl ; y+1 mov al,[bp+10] add al,cl inc al ; nuovo indice = ((y+1)*ncolonne) + (x+1) = vecchio_indice + ncolonne + 1 mov ah,byte ptr [bp+11] push ax ; salvo i parametri push [bp+8] push [bp+6] push bx ; al posto di tabx;taby salvo tabx+1;taby+1 call check ; controllo x+1,y+1 pop dx mov byte ptr [bp+11],dh fineproc: popa pop bp ret 6 check ENDP END