253 byte PC minesweeper game (complete source code)

I had some spare time so I wrote this up just for fun. I don't know of any 256 byte compos going on right now so I'll just post it here...

Since this forums policy forbids me from posting the compiled version you must make do with only the full source code

; Mine - 253 byte minesweeper - written by Chris Mumma - 2011 (public domain)
; inspired by James David Chapman and his 256 byte games (TET/INV/BD3)
; Mr Chapman's games can be found at his website:
; http://www.users.globalnet.co.uk/~jchap/tvpro256.htm
; compile with FASM - http://flatassembler.net/
; Control with mouse
; Press any key after win/loose to exit game
; Asterisks (*) are mines. If you see one you've lost
; Features:
; 40x25 character C0LOR text mode
; playable with a one button mouse
; 8x8 square board with 8 mines (randomized each game)
; mouse clicks uncover empty spots with floodfill
; numbers to indicate nearby mines
; holding mouse button down while moving the mouse acts like rapid clicks
; exit game code (press any key after win or loose)
; features cut out:
; all text and user messages
; flagging mines with right click
; proper 8-way floodfill
; game timer
; adjustable board size
; mouse driver check`
; won't run under DosBox as it lacks 100% compatable text mode mouse cursor
; (I understand that. I figure almost no dos games use text mode with a mouse)
; tested and works under windows 7 console (CMD.EXE / NTVDM)
; should run on any 386 based DOS PC but I don't have the resources to do
; extensive testing...

mapSize equ 8 ; easy mode right? (square maps only)
mineCount equ 8 ; (16x16 w/40 mines = medium | 24x24 w/90 mines = hard)
mapData equ heapPtr + 80 ; generated mine map memory offset

org 100h ; dos .com file program start
inc ax
int 10h ; set 40x25
int 33h ; show mouse cursor
;init game map in heap
mov ah,7 ; set text color
mov di,mapData - 80
mov cl,40 ; assume CH = null on entry
rep stosw ; line of null (for map clipping)
mov cl,mapSize
@: push cx
mov cl,mapSize ; square maps only
mov al,20h ; empty space marked with space (bar)
rep stosw
mov al,0
mov cl,40-mapSize ; rest of screen is null
rep stosw
pop cx
loop @B
mov cl,40
rep stosw ; line of null at end of data
;generate mines
mov di,mapData
mov cl,mineCount
@: in ax,40h
mov bx,mapSize*40 ; size of map buffer in bytes (including nulls)
xor dx,dx ; clear DX for DIV
div bx
mov bx,dx ; spot == rand()%total_spots
shl bx,1 ; force even (word align) address
mov dx,[di+bx] ; load map spot
cmp dl,20h
jne @B ; only write in empty space (20h)
mov byte [di+bx],'*'
;place numbers on map around mines giving hints
sub bx,82
call packMineCount ; NW, N, NE
add bx,154
call packMineCount ; SW, S, SE
sub bx,82
call mineCounter ; E
sub bx,4
call mineCounter ; W
loop @B
;setup video segment
push 0B800h
pop es
;draw board to screen
xor di,di
mov ax,7FEh ; color + ascii char
mov cl,mapSize
@: push cx
mov cl,mapSize
rep stosw
pop cx
add di,80-(mapSize*2) ; next line down
loop @B
mov ax,3 ; read mouse info
int 33h
shr cx,2 ; horz. 0-80 -> 320/4 = 40 chars (80 bytes)
shr dx,3 ; vert. 0-24 -> 200/8 = 25 chars high
and bx,bx ; test buttons
jz inputLoop
;calc mouse click address
mov ax,80
mul dx ; mul doubles as xor dx,dx later on
add ax,cx ; 80*y + x
mov si,ax ; si = video and map data offset
;click action
call stackFill
lods word [es:si] ; (lodsw [es:si]) bytecode: db 26h, 0ADh
cmp al,'*'
jne @F
winLoose: ; win or loose brings us here
xor ax,ax
int 16h
; win game test.... if unclicked spaces == mineCount then you win
@: xor si,si
mov cx,mapSize*40
lods word [es:si] ; lodsw [es:si] (bytecode: db 26h,0ADh)
cmp al,0FEh ; still covered?
jne @F
inc dx ; count unclicked spots
@: loop wincheck
cmp dl,mineCount ; all mines accounted for?
je winLoose
jmp inputLoop

;do horizontal row of three (above or below a mine)
packMineCount: ; save some bytes
push cx
mov cl,3
@: call mineCounter
inc bx
inc bx
loop @B
pop cx

;incriment 1 of the 8 spaces around mine (assuming no other mine in it)
mov dx,[di+bx]
and dl,dl ; game board clipping
jz @F
cmp dl,'*' ; dont change value of mines
je mineCountDone
cmp dl,20h
jne @F
mov dx,830h
@: sub dx,0FEFFh
mov [di+bx],dx ; and store

;4-way flood fill (not full 8 way)
mov ax,[es:si] ; load scr char
cmp al,0FEh ; don't fill if already revealed/flagged
jne @F
mov ax,[si+mapData] ; load map char
mov [es:si],ax ; copy to screen
cmp al,20h ; stop fill if close to a mine
jne @F ; if map char != empty space then ret
lodsw ; si+=2
call stackFill ; x+1
add si,78
call stackFill ; y+1
sub si,160
call stackFill ; y-1
add si,78
call stackFill ; x-1
lodsw ; si+=2
@: ret

heapPtr: ; start of game map memory heap


Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!