| CS306 |
Processing Systems and Structures |
Lockwood, Spring 2002 |
Machine Problem 3: The Maze (Part I)
| Assigned |
Monday, March 11 |
| Due Date |
Friday, March 22 |
| Purpose: |
File I/O, Data Processing, Video Graphics |
| Points |
50 |
Introduction
Consider a mouse that has found itself in a maze.
There are a series of winding hallways that separate
the mouse from the starting position and the end of the maze.
The mouse can move through the halls, but cannot walk through walls.
At each location in the maze where two or more hallways meet, the mouse
must decide which path to explore.
Machine Problem (MP3) is the first part of three machine problems.
For MP3, you will implement a program which uses the system I/O
to read a file describing the maze layout.
You will then process that file to record the location of walls,
hallways, starting position, and the ending position to system memory.
Once the map is in memory, you will then process the map to
mark the location of each decision point in the maze. Lastly, you
will render a top-down view of the
maze onto a color video graphics screen.
A screen-dump of the program is shown below:
In MP4, you will implement a function to advance the mouse around the maze.
You will then add 'Turbo' and 'Auto-Advance'
features that automatically forward
the mouse through hallways and around turns.
You will finally implement a Depth First Search (DFS)
algorithm to automatically guide the mouse out of the maze.
Lastly, in MP5, you will implement a "mouse eye-view" of the maze--
i.e., render a three dimensional view of the maze that
the mouse would see while standing inside the maze looking
directly down a hallway.
Problem Description
This machine problem represents the maze using three
methods. The input to the maze program
is defined by a standard text file called MAZE.DTA. The maze
has 80 columns and 23 rows. Walls are indicated with the '#' character.
Hallways
are indicated by the ' ' (space) character.
The starting location in the maze is
indicated with the 'S' character. The end of the maze is indicated with the 'E'
character. The MAZE.DTA file can be edited with any text editor. The only
restriction on the file is that the walls must surround the maze (i.e., all of
row 0, row 22, column 0, and column 79 hold the '#' character).
Internally, our program will represent the maze as a byte array of 80
(columns) * 23 (rows) = 1840 (bytes) called _MAZE.
The size of the maze
is defined as a constant called MAZESIZE. The array is stored in left-to-right,
top-to-bottom order -- i.e., offset zero of _MAZE holds the top-left
byte of the maze and offset MAZESIZE-1 holds the bottom-right element of
_MAZE. Each byte defines a hallway, a wall, an endpoint, or a
decision point. A decision point is a location in the maze where the
mouse must decide which way to travel (i.e., the hallway branches).
You will compute
the location of decisions points just after the maze is read from the
file.
To view the maze, the VGA adapter is used in with text-mode graphics.
In this mode, each
character on the screen is represented by two bytes --
an attribute byte and the
ASCII character. The attribute byte determines the background color, the
foreground color, intensity, and a flag to determine if the character should be
blinking. Details of programming the VGA adapter were described in lecture
and appear in the textbook.
The location of the mouse is determined by a variable called _POS.
_POS is a word-sized (16-bit) integer defined as an offset into
_MAZE. For example, if the mouse is at row 5, column 7 of the maze,
_POS would equal 80*5+7. The mouse can move NORTH, EAST, SOUTH, or
WEST. North is defined pointing towards
the top of the screen. The mouse is represented on the
screen as an arrow that points in the current direction.
Operation of MAZE
The best way to understand the MAZE is to play the
MAZE.
There are four modes of operation to this program: Manual, Turbo,
AutoAdvance, and AutoSolve. Modes can be selected by pressing the 'M' key,
followed by a number (0 to 3). In manual mode (M0), pressing the arrows keys
will advance you by one position. In turbo mode (M1), the mouse will run down a
hallway until hitting a wall. In AutoAdvance mode (M2), the mouse will traverse
down a hallway until hitting a decision point. In AutoSolve mode (M3), the mouse
will find the solution to the maze automatically. The mode of the program is
displayed at the top-center of the screen.
In modes 1-3, the speed of the mouse can be adjusted. The (+) and (-) keys
determine the delay rate. A larger rate slows the mouse, while a smaller makes
the mouse move faster. The delay rate is displayed at the top-right of the
screen.
You can exit the program by pressing 'Q' to quit.
Implementation
The program begins running at the ..start label of MP3.ASM.
After setting up the segments, the program first calls
ReadMazeData to read the file MAZE.DTA.
The C
program (mazec.c) is used to start the program, read the maze data file
(maze.dta), and calculate the location of the decision points. The ASM
routines are used to provide high-speed graphic update and maze movement
routines. Because this is a class on assembly; you are only responsible for
writing the ASM routines.
The ASM procedures that you will need to implement are described below.
There are working library versions of each of these procedures in
libmp3.lib. Unless otherwise noted, it is expected that that
all subroutines will
preserve the value of any register that they modify.
The only exception is for registers that are used as outputs of
procedures.
ReadMazeFile
- Purpose:
- This subroutine reads a disk file
to record the layout of the maze into the
_MAZE array.
- Input
- Output Variables:
- All 80*23 bytes of the _MAZE array.
- The word-size _POS variable
should be set to store the start
location of the mouse.
- Called by:
- Description:
- For each
ASCII character in the input file,
store the corresponding CONSTANT
(as defined at the top of mp3.asm)
into the _MAZE array.
- '#' [pound symbol] maps to WALL
- ' ' [space] maps to HALL
- 'E' indicates ENDPOS (The End Position)
- Update _POS based on the location of the 'S'
- C code for a simlar function is given below
|
FILE* fp;
int x, y, ch;
int position=0;
fp = fopen("Maze.Dta","r"); // Open Maze File
for (y=0; y |
- Notes
- Use MSDOS Interrupt service routines to
to open, read, and close the file.
- If an error occurs while opening or reading the file,
print a meaningful error message.
- Details of MS-DOS calls appear in
Chapter
13 of the Art of Assembly book.
- Note that the _MAZE array holds constants, not
ASCII codes, to represent the maze.
- Note that
Carriage return and line feeds
appear the end of each line of the text input file.
It is safe to ignore all ASCII 13 and ASCII 10 values.
- Avoid overflowing the _MAZE buffer.
This will occur if you read more than
80*23 characters into the _MAZE array.
MarkDecisionPoints
- Purpose:
- Mark all locations in the _MAZE where hallways
join.
- Input/Output Variable:
- Called By:
- Description:
- For each location in the _MAZE array
(except the outer walls), determine if
the mouse will need to make a decision.
- Look at the type of character above, below, to the left,
and to the right of each position in _MAZE.
If less than two of these
positions contain a WALL, then this location
must be a decision point. Write the DECPOS
constant into the _MAZE array to indicate
that the location is a decision point.
- C-code for the function is show below
|
MarkDecisionPoints() {
int x, y, wallctr, position;
for (y=1; y<(MAZEROWS-1); y++)
for (x=1; x<(MAZECOLS-1); x++) {
position=x+MAZECOLS*y;
if (*(&_MAZE+position) == HALL) {
wallctr=0;
if (*(&_MAZE+position+1)==WALL)
wallctr++;
if (*(&_MAZE+position-1)==WALL)
wallctr++;
if (*(&_MAZE+position+MAZECOLS)==WALL)
wallctr++;
if (*(&_MAZE+position-MAZECOLS)==WALL)
wallctr++;
if (wallctr<2) *(&MAZE+position) = DECPOS;
}
}
}
|
ShowMaze
- Purpose: Draw the maze on the screen. and indicate the initial
location of the mouse using the mouse.
- Variables: Both _MAZE, _POS
and _DIR are read but not
modified
- Inputs: ES points to the segment address of the video display
memory.
- Useful Constants: MAZESIZE, HALL, WALL, DECPOS, ENDPOS, HALLCH,
WALLCH, DECCH, and ENDCH.
- Called by: _ShowMaze
- Registers: All preserved
- Description:
The maze can be drawn on the screen as follows: For each byte of the maze,
this routine should write a word to the video buffer.
For your convenience, a number of constants have been defined in
maze.def. MAZESIZE defines the size of the maze (in bytes).
This constant is equal to 80 (columns) * 23 (rows) = 1840 (bytes). For each
element in the maze, this routine will draw an element on the screen.
Constants are also used to define the values of _MAZE elements and
their Attribute:Character values used on the screen. A table lookup is an
efficient method to map the byte-value of _MAZE[index] to a
Attribute:Character value used by the video buffer. The mapping function is
summarized below.
_MAZE Value (byte) |
Attribute:Character (word) |
Description |
| HALL
| HALLCH
| Black background |
| WALL
| WALLCH
| Green, Solid Box |
| DECPOS
| DECCH
| Decision Position - Blue crosshair (+) |
| VISPOS
| VISCH
| Visited Position - Green crosshair (+) |
| FINPOS
| FINSH
| Finished Position - Red crosshair (+) |
| ENDPOS
| ENDCH
| Yellow End-of-maze Marker (E) |
After drawing the maze, the routine also needs to draw the location of the
mouse (Red smile character). The variable _POS holds the initial
position (byte offset into the maze).
The constants M{N,E,S,W}CH
are the
attribute:character value for the mouse pointing in
different directions.
At the bottom of the screen, there is static text with directions that
should be displayed.
ShowMode
- Purpose: Display the current mode and rate at the top of the
screen and the instructions at the bottom of the screen.
- Variables: Both mazemode and mazedelay are read
but not modified
- Inputs: ES points to the segment address of the video display
memory.
- Called by: _ShowMaze when the program begins and by
_MazeManual when the user changes mazemode or
mazedelay.
- Registers: All preserved
- Description:
At the top of the screen, there are two boxes that display the mode of the
game and the delay value.
Mazemode indicates the mode of the game. Its value ranges from 0
to 3. For each of these values, a text message should be printed to indicate
the mode. This message should be printed at the top, center of the screen
using yellow text on a blue background. The mappings between mazemode
and output values are as follows:
| MazeMode |
Text String |
Description |
| 0
| 'MANUAL'
| Manual Mode |
| 1
| 'TURBO'
| Turbo Mode |
| 2
| 'AUTOADV'
| Auto-Advance |
| 3
| 'AUTOSLV'
| Auto-Solve |
Mazedelay indicates the delay between movements. Its value ranges
from 0 to 255. At the top, right of the screen, the value should be printed
using the same text attributes as used for the mode message.
UpdateTextScreen
- Purpose: Draw mouse at new position on the screen after an advance.
- Inputs:
- SI: Original Position of Mouse
- DI: New position of Mouse
- AL: Direction of the mouse (0..3)
- Outputs: Writes only to screen
- Description:
After advancing by a position, it is necessary to update the screen. This
routine provides an efficient alternative to redrawing the entire screen. The
mouse should be drawn at the new position given by DI. The mouse should be
removed from the old position given by SI. To remove the mouse, you will need
to access _MAZE to determine what element should be drawn on the
screen. Possible values of maze include: WALL, ENDPOS, HALL, DECPOS,
VISPOS, and FINPOS. The mappings from characters in
_MAZE to attribute:character elements for the screen is the same as
were used for ShowMaze.
Points
You earn points by replacing each subroutine with your own code.
Your score will be proportional to the percentage of the code that your write
yourself. The breakdown in points is given below. Your routine MUST perform all
functions of the subroutine to receive credit.
- ReadMazeFile: 10 pts
- MarkDecisionPoints: 10 pts
- ShowMaze: 10 pts
- ShowMode: 10 pts
- UpdateTextScreen: 10 pts
Starting Files
- You will begin MP3 with the following files:
- mp3.exe: A fully functional executable program
using library routines
- maze.dta: The maze definition file.
- mp3.asm: A starting point for the program.
You are given the routines for reading and
processing keyboard input, calling the other functions,
and delaying movement.
- libmp3.lib: Binary
versions of the routines that you need to implement.
- lib306.lib: The standard ECE306 library routines.
(you can always use these routines freely)
- build.bat: A short batch program which assembles
and links your program
- clean.bat: A short batch program which removes temporary files
- These files can be download as mp3.zip
MP3 Code Assignment
; You Name Here : ____________________________________
; CS306: Machine Problem 3, Spring 2002
; Prof. John W. Lockwood
; Washington University, Department of Computer Science
; Ver. 2.1
; ================ Constants / Definitions / MACROs =====================
MAZESIZE EQU 1840
; MAP Elements
WALL EQU 0
ENDPOS EQU 1
HALL EQU 2
DECPOS EQU 3
VISPOS EQU 4
FINPOS EQU 5
; Direction Definitions
NORTH EQU 0
EAST EQU 1
SOUTH EQU 2
WEST EQU 3
; Keyboard Input Codes
FORWARDKEY EQU 72
BACKWARDKEY EQU 80
LEFTKEY EQU 75
RIGHTKEY EQU 77
; Attribute Byte for Mode Display
LB EQU 00011110b ; Red background; Bright yellow text
; Modes
MODEMAN EQU 0
MODEADV EQU 1
MODEAUTOADV EQU 2
MODEAUTOSOLVE EQU 3
TEXTMODE EQU 0
GRMODE EQU 1
; Video Memory Segments (Store in ES)
VIDTEXTSEG EQU 0B800h ; Text-mode video (for the maze of mp3/mp4)
VIDGRSEG EQU 0A000h ; Grahphis video (for the 3d maze of mp5)
; Screen Display values
HALLCH EQU 0000000000100000b
WALLCH EQU 0000001011011011b
ENDCH EQU 0000111001000101b
DECCH EQU 0000000100101011b
VISCH EQU 0000001000101011b
FINCH EQU 0000010000101011b
; New Mouse Cursers (Mouse North,East,South,West)
MNCH EQU 0000110000011110b
MECH EQU 0000110000010000b
MSCH EQU 0000110000011111b
MWCH EQU 0000110000010001b
; Text Mode (TMODE) Macro
%macro TMODE 0
push ax
mov ax,VIDTEXTSEG
mov es,ax
mov ah,00h
mov al,02h
int 10h
pop ax
%endmacro
; ================== GLOBAL Variables & Procedures ======================
; External Routines (called from C)
GLOBAL _MazeManual
; Public variables (used by C Program and libmp4)
GLOBAL _POS, _MAZE
GLOBAL VidMode
; Public variables (used by libmp3)
GLOBAL Movement, mazemode, mazedelay, updatescreen
; =================== External Library Procedures =======================
; Your code can call these library routines (but not for free)
EXTERN LibReadMazeFile
EXTERN LibMarkDecisionPoints
EXTERN LibShowMaze
EXTERN LibShowMode
EXTERN LibUpdateTextScreen
EXTERN LibAdv
EXTERN LibAutoAdv
EXTERN LibAutoSolve
EXTERN LibDrawBox
EXTERN LibDrawTrap
EXTERN LibDrawBackWall
EXTERN LibDrawFloorCeiling
EXTERN LibDrawSides
EXTERN LibDrawGrScreen
; The library routines may need call these
; procedures in your code
GLOBAL AutoAdv
GLOBAL AutoSolve
GLOBAL Adv
GLOBAL UpdateScreen
GLOBAL DrawBox
GLOBAL DrawTrap
GLOBAL DrawBackWall
GLOBAL DrawFloorCeiling
GLOBAL DrawSides
GLOBAL DrawGrScreen
; FREE LIB306 Routines
EXTERN kbdin, kbdine, dspmsg, binasc, dspmsg, dspout
EXTERN mpxit
;====== Stack ============================================================
SEGMENT stkseg stack
resb 64*8
stacktop:
;====== Begin Code/Data ===================================================
SEGMENT code
; _MAZE and _POS are read in by the C program
_MAZE resb MAZESIZE ; An array of bytes that defines the maze
_POS dw 0 ; Position of the mouse in the maze
MazeFile resb MAZESIZE+100 ; A file which holds the maze data
mazemode db 0 ; By default, Start in Manual Mode
mazedelay db 16 ; Default Delay Period
movement dw -80,+1,+80,-1 ; Movement Offsets for fast table-lookup operation
; --- New Variables for MP4 ---
VidMode db TEXTMODE ; Can be TEXTMODE (default) or GRMODE
; Pointed Mouse Attribute:Character Lookup Table (North, East, South, West)
mousech dw MNCH, MECH, MSCH, MWCH
; ================= Procedures (Your code goes here) ====================
MazeFileName db "MAZE.DTA",0 ; File name of maze, Null terminated
MazeFileHandle dw 0 ; File handle
MazeFileBuffer db 0 ; signle byte buffer
FileOpenMsg db "Error: Could not open MAZE.DTA for reading", 13,10,'$'
FileReadMsg db "Error: Could not read MAZE.DTA file ", 13,10,'$'
ReadMazeFile:
; Purpose (1) Read Maze.dta file from disk
; (2) Write data form file to _MAZE
; (3) Convert ASCII codes to HALLs and WALLs, and END positions
; (4) Set _POS based on starting postion
Call LibReadMazeFile
ret
; ------------------------------------------------------------------------
ShowMaze:
; Purpose: (1) Draw initial Maze on screen,
; (2) Show initial Position of mouse (Smiley Character)
; Variables: _MAZE, _POS, mazemode, mazedelay (no variables modified)
Call LibShowMaze; Comment this out and replace with your own code!
ret
; ------------------------------------------------------------------------
MarkDecisionPoints:
; Purpose: (1) Identify all points in maze where a decision must be made
; (2) Place a DECPOS letter in _MAZE at such locations
; Variables: _MAZE,
Call LibMarkDecisionPoints; Comment this out and replace with your own code!
ret
; ------------------------------------------------------------------------
ShowMode:
Call LibShowMode; Comment this out and replace with your own code!
ret
; ------------------------------------------------------------------------
UpdateTextScreen:
Call LibUpdateTextScreen; Comment this out and replace with your own code!
ret
; ------------------------------------------------------------------------
Adv:
Call LibAdv; [ Subject of Machine Problem 4 ]
ret
; ------------------------------------------------------------------------
AutoAdv:
Call LibAutoAdv ; [ Subject of Machine Problem 4 ]
ret
; ------------------------------------------------------------------------
AutoSolve:
Call LibAutoSolve; [ Subject of Machine Problem 4 ]
ret
; ------------------------------------------------------------------------
DrawBox:
Call LibDrawBox ; [Subject of machine problem 5]
ret
; ------------------------------------------------------------------------
DrawTrap:
Call LibDrawTrap ; [Subject of machine problem 5]
ret
; ------------------------------------------------------------------------
DrawBackWall:
Call LibDrawBackWall ; [Subject of machine problem 5]
ret
; ------------------------------------------------------------------------
DrawFloorCeiling:
Call LibDrawFloorCeiling ; [Subject of machine problem 5]
ret
; ------------------------------------------------------------------------
DrawSides:
Call LibDrawSides; [Subject of machine problem 5]
ret
; ------------------------------------------------------------------------
DrawGrScreen:
Call LibDrawGrScreen ; [Subject of machine problem 5]
ret
; ------------------------------------------------------------------------
UpdateScreen: ; This code is given to you for free
call UpdateTextScreen
ret
; ------------------------------------------------------------------------
_MazeManual: ; This code is given to you for free.
; Purpose: Interactively allows user to traverse maze and run AutoSolve
; Variables: _MAZE, mazemode, mazedelay
; Input: From keyboard
; Output: None.
PUSH BP
PUSH DS
PUSH ES
PUSH SI
PUSH DI
MOV AX,VIDTEXTSEG ; Use ES=Video Segment
MOV ES,AX
MOV BL,NORTH ; By default, go north
MMLoop: Call kbdin
CMP AL,'Q'
JNE MMNotDone1
JMP MMDone
MMNotDone1:
CMP AL,'q'
JNE MMNotDone2
JMP MMDone
MMNotDone2:
CMP AL,FORWARDKEY
JE MMForward
CMP AL,BACKWARDKEY
JE MMBackward
CMP AL,LEFTKEY
JE MMLeft
CMP AL,RIGHTKEY
JE MMRight
CMP AL,'m'
JE MMode
CMP AL,'+'
JE MMSlower
CMP AL,'-'
JE MMFaster
CMP AL,'g'
JE MMGrMode
CMP AL,'t'
JE MMTMode
CMP AL,'v'
JE MMMark
JMP MMLoop
; Check for Keyboard Arrow Keys (up, down, left, right)
; Redefine keyboard - forward , back , left turn , right turn
MMForward: MOV AL,BL ; Go Forward
JMP MMArrow
MMBackward: MOV AL,BL
ADD AL,2 ; Reverse direction
AND AL,3
CALL Adv ; Advance 1
MOV AL,BL ; Set Direction to forward
CALL UpdateScreen ; Show screen
JMP MMLoop
MMLeft: ADD BL,3 ; Go Left
AND BL,3
MOV AL,BL
; MOV SI,[_POS] ; should not be needed
; MOV DI,[_POS]
Call UpdateScreen
JMP MMLoop
MMRight: ADD BL,1 ; Go Right
AND BL,3
MOV AL,BL
; MOV SI,[_POS]
; MOV DI,[_POS]
Call UpdateScreen
JMP MMLoop
; Set Game Mode ('m0','m1','m2','m3')
MMode: Call kbdin
CMP AL,'0'
JB MMLoop
CMP AL,'3'
JA MMLoop
SUB AL,'0'
MOV [mazemode],AL
Call ShowMode
JMP MMLoop
; Control Interactive Speed (Smaller Mazedelay==Faster)
MMFaster: DEC byte [mazedelay]
Call ShowMode
JMP MMLoop
MMSlower: INC byte [mazedelay]
Call ShowMode
JMP MMLoop
MMGrMode: ; MP5 will support Graphics mode
; For now, do nothing.
JMP MMLoop
MMTMode: TMODE ; (Macro in MAZE.DEF) - Switch back to 80x25 Text Mode
mov byte [VidMode],TEXTMODE
Call ShowMaze
Call ShowMode ; Need to redraw (entire) text screen
JMP MMLoop ; after switching modes
MMMark: mov DI,[_POS] ; New Feature - Hit 'v' to visit/unvisit node
cmp byte [_MAZE+DI],DECPOS
jne MMMark2
mov byte [_MAZE+DI],VISPOS
jmp MMMarkD
MMMark2: cmp byte [_MAZE+DI],VISPOS
jne MMMark3
mov byte [_MAZE+DI],FINPOS
jmp MMMarkD
MMMark3: cmp byte [_MAZE+DI],FINPOS
jne MMLoop
mov byte [_MAZE+DI],DECPOS
MMMarkD: MOV AL,BL
MOV SI,DI
Call UpdateScreen
JMP MMLoop
MMArrow: CMP byte [mazemode],3 ; AutoSolve Mode
JE MMASolve
CMP byte [mazemode],2 ; AutoAdvance Mode
JE MMAutoAdv
MMAdv: Call Adv ; Movement Loop
Call UpdateScreen
CMP byte [mazemode],0
JE MMLoop
CMP byte [_MAZE+DI],HALL
JNE MMLoop
CMP AH,1
JE MMLoop
Call delay
JMP MMAdv
MMAutoAdv: mov al,bl
Call AutoAdv
mov bl,al
JMP MMLoop
MMASolve: mov al,bl
Call AutoSolve
mov bl,al
JMP MMLoop
MMDone: MOV AX,0 ; Return value
POP DI
POP SI
POP ES
POP DS
POP BP
RET ; Use FAR returns when going back to a C routine!
; ------------------------------------------------------------------------
delay:
; Purpose: Burn CPU cycles between movements
; Inputs: variable mazedelay (0..255) - Delay constant
; Outputs: None - All Registers Preserved
; Notes: There is no need to modify this code (it is given for free)
CMP byte [mazedelay],0
JE DLoopNone
PUSH CX
MOV CX,0FFFFh
DLoop: PUSH CX
MOV CH,0
MOV CL,[mazedelay]
DLoop2: NOP
LOOP DLoop2
POP CX
LOOP DLoop
POP CX
DLoopNone: ret
; ------------------------------------------------------------------------
..start
MOV AX,CS ; Set Code Segment = Data (Default) Segment
MOV DS,AX
MOV AX,VIDTEXTSEG ; Use extra segment for Text mode video
MOV ES,AX
MOV AX, stkseg ; Stack segment
MOV SS, AX
MOV SP, stacktop
; BODY OF MAIN PROGRAM BEGINS HERE!
Call ReadMazeFile ; Read in the contents of the maze
TMODE ; MACRO to switch to text mode video
Call ShowMaze ; Display original maze and mouse on screen
call kbdin
call MarkDecisionPoints
Call ShowMaze ; Display original maze and mouse on screen
call kbdin
Call ShowMode ; Display mazemode and mazedelay values on screen
call kbdin
MOV SI, [_POS] ; Store position in register SI
MOV DI, [_POS] ; Store position in register SI
Call _MazeManual
Call mpxit ; no RET opcode needed for this procedure.
; mpxit will terminates the program.