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

MarkDecisionPoints

ShowMaze

ShowMode

UpdateTextScreen

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.

Starting Files


MP3 Code Assignment

<HR> ; 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. <H2><A name=MAZEASM>MAZE.ASM</A></H2><FONT size=-1><XMP>
Copyright 1996-2002 John Lockwood