Console Games

We wondered how easy it would be to program simple console games using MASM. This would require changing the colours of the text and background and would need equivalents of Pascal crt routines such as GoToXY. We decided to convert the first version of Joe's SnakeWithoutATail to MASM assembler. The code of snake.asm is below. It runs with this script in a batch file in the same directory as snake.asm on the same drive as MASM:

\masm32\bin\ml /c /Zd /coff snake.asm
\masm32\bin\Link /SUBSYSTEM:CONSOLE snake.obj
snake

The locate procedure is the equivalent of GoToXY, except that the parameters X and Y are zero-based. Similar to Pascal's random function, nrandom when passed a parameter Num returns (in the EAX register) a random integer in the range 0 to Num - 1. The random seed has the identifier nrandom_seed. You could ask the user to input a value for the random seed or use one based on time, perhaps by using the GetLocalDateTime procedure.

We changed the colours using SetConsoleTextAttribute, but were surprised that ClearScreen did not use our supplied argument for the text and background colours. Instead, we printed a string comprising 2000 spaces!

;SnakeWithoutATail Version 1.0
;Pascal version copyright (c) 2012 Joe
;Licensed under the Apache License, Version 2.0 (the "License"); you may
;not use this file except in compliance with the License, as described at
;http://www.apache.org/licenses/ and http://www.pp4s.co.uk/licenses/
include \masm32\include\masm32rt.inc
.686
.data
  nrandom_seed DD 12345678 ;Change this for variety
  spaces db 2000 dup(32),0
  X DD 10
  Y DD 10
  FoodX DD ?
  FoodY DD ?
  hOutPut DWORD ?
  CCI CONSOLE_CURSOR_INFO {}
  OldK DD ?
  K DD ?
  Speed DD 120
  SlowSpeed DD 120
  FastSpeed DD 60
.code
START:
invoke GetStdHandle, STD_OUTPUT_HANDLE
MOV hOutPut, EAX
;Turn off the cursor
invoke GetConsoleCursorInfo, hOutPut, ADDR CCI
MOV CCI.bVisible, 0
invoke SetConsoleCursorInfo, hOutPut, ADDR CCI
invoke SetConsoleTextAttribute, hOutPut, FOREGROUND_BLUE OR BACKGROUND_GREEN
;Clear screen to green.
invoke locate, 0, 0
print OFFSET spaces
SetConsoleCaption "Snake without a tail"
invoke locate, 0, 0
print "Welcome To The Game",13,10  ;This is the start screen.
print "Instructions",13,10
print "Eat fruit",13,10
print "W     - Up",13,10
print "S     - Down",13,10
print "D     - Right",13,10
print "A     - Left",13,10
print "Space - toggle run or walk",13,10
print "ESC - End",13,10
print "Press any key to begin",13,10
getkey
cls
CALL PrintFood
invoke locate, X, Y
print "#"
StartLoop:
call crt__kbhit ;EAX is zero if no key press
Test EAX, EAX
JZ Move         ;jump to Move if EAX is zero
MOV EAX, K
MOV OldK, EAX   ; store old key
call crt__getch ; get new key
MOV K, EAX
Move:
CMP K, 119 ; 'w'
JE Up
CMP K, 97  ; 'a'
JE Left
CMP K, 115 ; 's'
JE Down
CMP K, 100 ; 'd'
JE Right
CMP K, 32       ;space toggles speed
JNE CheckEscape
MOV EAX, Speed
CMP EAX, SlowSpeed
JE @F ;Jump forward to @@
MOV EAX, SlowSpeed
MOV Speed, EAX
JMP SameDirection
@@:
MOV EAX, FastSpeed
MOV Speed, EAX
JMP SameDirection
CheckEscape:
CMP K, 27
JNE SameDirection
exit
SameDirection:
MOV EAX, OldK   ;Use the previous key
MOV K, EAX
JMP StartLoop
Right:
invoke locate, X, Y
print " "
INC(X)
CMP X, 79
JLE PrintPlayer
MOV X, 0
JMP PrintPlayer
Left:
invoke locate, X, Y
print " "
DEC(X)
CMP X, 0
JGE PrintPlayer
MOV X, 79
JMP PrintPlayer
Up:
invoke locate, X, Y
print " "
DEC(Y)
CMP Y, 0
JGE PrintPlayer
MOV Y, 24
JMP PrintPlayer
Down:
invoke locate, X, Y
print " "
INC(Y)
CMP Y, 24
JLE PrintPlayer
MOV Y, 0
PrintPlayer:
MOV EAX, X
CMP EAX, FoodX
JNE PrintIt
MOV EAX, Y
CMP EAX, FoodY
JNE PrintIt
CALL PrintFood
PrintIt:
invoke locate, X, Y
print "#"
invoke Sleep, Speed
JMP StartLoop
RET
PrintFood:
invoke nrandom, 25
MOV FoodY, EAX
invoke nrandom, 80
MOV FoodX, EAX
invoke locate, FoodX, FoodY
print "&"
RET
CALL START
END START

We developed and tested this code as a preliminary to adapting Jack Crenshaw's TINY compiler to translate crt-type TINY statements; TINY14_CRT generates similar MASM assembler code. We then converted Joe's SnakeWithoutATail from Pascal to TINY and used it to test the new functionality in the compiler.

Programming - a skill for life!

Getting started with the MASM assembler, MASM demonstrations (including console games and floating point numbers) and ARM assembly language