| CSE306 |
Processing Systems and Structures |
Lockwood, Spring 2004 |
Machine Problems 2 and 3: The Bakery of Hanoi
| Assigned | Wednesday, March 17, 2004 |
| Due Date | MP2: Monday, March 29, 2004, 3pm (50 pts)
MP3: Monday, April 5, 2004, 3pm (50 pts) |
| Purpose: |
Understand recursion, text-mode video, and mouse control.
|
| Points | 50 + 50 = 100 |
Introduction
A wedding is planned in the town of Hanoi.
For the event, a baker has prepared an elaborate
wedding cake with multiple tiers. Each tier of the cake is a
different size. Initially, the cake is stacked at the bakery
with the largest tier at the bottom and progressively smaller
cakes stacked above one another. Using manual labor and the bakery's
single delivery truck, a plan is needed to transport the
entire cake to the recepton. A diagram is shown below:
The baker must transport the entire cake to the reception.
Because the cake is heavy, it must be moved one tier at a time.
To insure that the cakes are not damaged before the reception, the
cake tiers must always be kept at the bakery, in the delivery van,
or on the table at the reception. Tiers of cake can be
moved directly between all three locations.
Tiers of the cake may be stacked,
but a larger tier must never be placed atop a smaller one for fear
of collapsing the smaller tier.
The baker's delivery man, Igor, has already moved some of the
tiers of cake. Wrought with confusion and frustration from moving
the cake, Igor has called the baker and quit his job. With the
wedding reception only hours away, the baker is desparate to find
someone to get all of the cakes to the reception and stacked in the
proper order.
As a student of CSE306, the baker has hired you to help him
devise a plan to start where Igor left the tiers and assemble the cake
at the reception as efficiently as possible.
Implementation
For this machine problem, you will write a program which:
- Graphically displays cake tiers at the bakery,
on the van, and at the reception using text-mode video.
- Simulates Igor's activity by randomly distributing
tiers of cake to each location.
- Allows a user to manually move tiers of cake
between locations via the mouse.
- Automatically transfer
all tiers of the cake to the reception using the
least number of transfers
starting with any number of tiers
in any given arrangement.
A screen dump of the running program is shown above. Along the top
of the screen are a series of buttons. Each of these buttons responds to
a mouse-click. Just below the buttons, the program displays the current
number of moves as well as the number of tiers of cake. The lower portion
of the screen contains the bakery, the delivery truck, and reception.
To win the game, the entire cake should be moved to the reception
(the right-most location).
Usage Instructions
The library-based MP2.EXE demo can be run from the DOS prompt.
Use the mouse to press the on-screen buttons and
move tiers of cake between locations. Tiers are moved by moving the
mouse to the source, pressing the mouse button, moving the mouse
to the destination, then releasing the mouse button. The program
will not allow larger tiers of cake to be placed atop smaller tiers.
If the mouse does not appear on your screen, enter
mouse to load your mouse driver.
This program should operate both in full-screen text-mode and within a
window.
Data Structures
The following variables are used throughout the program and by
the library functions.
- Tiers:
This word-sized variable stores the number of tiers in the current game.
A Larger number of tiers makes the game more difficult.
By default, the game begins with 4 tiers. The value can
be changed from 1 to 10 by clicking on the More Tiers or
Less Tiers buttons.
- Moves:
A word-sized variable that tracks the number of valid moves. It
is reset to zero whenever the game is reset or the tiers are distibuted.
It is incremented on every valid move.
- Bakery, Truck, Recept:
Bit maps are used to determine which tiers appear at each location.
Three words, Bakery, Truck, Recept are used to determine which
tiers are located at the bakery, on the delivery van, or at the the reception.
The least-significant bit (bit 0) of each word corresponds to the largest
tier. For a game with four tiers, for example, a value of 1 in the
0th bit position of recept would indicate that the largest
tier of the 4-tier cake is already at the reception. You may
find the following observations useful:
- A word-sized variable can represent all possible permuations
of tiers at any given location.
- The order of tiers at each location is implicit.
Larger tiers are always at the bottom.
- The number of '1's in the bit-vector corresponds to the number
of tiers at a given location.
- The three variables starting with Bakery
are located in six consecutive bytes of memory.
Procedures
The ASM procedures that you need to implement are described below.
There are working library versions of each of these procedures in
libmp2.lib. Unless otherwise noted, it is expected that
ALL routines will preserve the value of ALL registers modified,
other than the output (i.e., PUSH and POP all registers except
for those that need to return a value).
You are encouraged to write your own procedures to handle repetive
tasks. You will find, for example, that a function which
writes messages on the screen at given location can be used throughout
your program.
Be sure that you have experimented with the library-based program before
you begin. It is important that you fully understand the problem before
you try to write the code. Because library functions call other
library functions, you are encouraged to begin coding with the MAIN routine.
- PrintString
- Purpose:
Print a string on a text-mode video screen.
- Variables Used:
- Assumes that ES=B800 (the segment of the text-mode video buffer)
- DI=location to display screen (offset on the text-mode screen)
- BX=address of first character in string (pointer to memory)
- AH=attribute of the characters on the screen
- Description:
This routine prints a string onto the default 80x25 text-mode
video screen. Each of the characters should be colored using
the properties of the given attribute.
- Hints:
- Plot each of the characters until reaching the
end-of-string marker ('$').
- Note that the input string is represented with a single byte
per character, but the data on the screen uses a work (2 bytes) per
character
- As with all procedures, be sure to preserve the values of
all registers that you modify in the procedure.
- ClearScreen
- Purpose:
Clears all the characters from the default 80x25 text mode
video screen.
- Variables Used:
Assumes that ES=B800 (the segment of the text-mode video buffer)
- Description:
To clear the screen, write a screen full of blank characters
that have a white background with black text.
- Hints:
If you use any repeating string commands, be sure the
direction flag is set to be in the proper direction.
- DrawScreen
- Purpose:
Displays all text, menu buttons, and graphics shown on the screen
above.
- Assumes: ES = VidTxtSeg (B800)
- Variables Used: Tiers, Moves, Bakery, Truck, Recept
- Description:
This routine is responsible for drawing the contents
of the screen. The routine should display messages on the screen
current values of tiers and moves; and
graphically represent the contents of bakery,
truck, and recept as a stacked tiers of blue cake.
Your screen should, at minimum, match the screen generated by
the library function (though you
are welcome to exercise artistic freedom and
creating a more elaborate screen).
- Hint:: It is worthwhile to write subroutines to
avoid duplication of code for repetive tasks. It is up to
you to decide how best to implement such routines.
- Hint:: An ASCII tables
with extended codes can be found on-line.
- ReDrawScreen
- Purpose:
Incrementally update the screen after a movement.
- Description:
This routine updates the contents of the screen after moving
a tier. It should only write to the areas of the screen
that are changed when a tier is moved.
The new value of Moves should be displayed and
the graphic display of the cake should be refreshed.
- Variables Used: Moves, Bakery, Truck, Recept
- Hint:: This code may use some of the same subroutines
as DrawScreen
- Random
- Purpose:
Randomly generate a number equal to: 0, 1, or 2
- Description:
Each time this function is called, it should return
a value in AX that is pseudo-random and in the range
between 0 to 2.
- Hint:
It is possible to generate Pseudo-random numbers
by multiplying a prime number by a random number seed
then using the remainder of the result.
- Note: It is not necessary to exactly
match the random pattern generated by the library function,
but it is necessary to use a good random function to
distribute values relatively evenly.
- ResetGame
- Distribute
- MoveTier
- Purpose:
Moves one tier of cake from SI to DI.
- Variables Used: Moves, Bakery, Truck, Recept
- Inputs
- SI: Source location (0=bakery, 1=truck, 2=reception)
- DI: Destination location (0=bakery, 1=truck, 2=reception)
- Outputs: Returns AX=1 if a move was made, 0 otherwise.
- Description:
This routine moves a tier of cake from the source to the destination.
The bitmapped vectors for the bakery, truck, and/or reception should
be modified, moves should be incremented,
and AX should return 1 if the move was valid.
If the move was invalid (i.e., the user tried to move a larger
tier atop a smaller tier), the program should print an error message
at the bottom of the screen, beep, and return AX=0.
- AutoSolve
- Purpose:
Automatically delivers all tiers of cake to the reception.
- Variables Used: Tiers, Bakery, Truck, Recept
- Calls Function: MoveTier
- Inputs:
- DI: Target destination = {0,1,2}
- CX: Tier Level = {1..Tiers}
- Initial Recursive Call:
- To solve the entire puzzle, Autosolve is invoked with
CX=1 (the largest tier at the right-most bit position) and
DI=2 (destination location = reception)
- Description:
The classic 'Towers of Hanoi' problem is solved recursively
via a divide-and-conquer algorithm. The solution to the single-tier
problem is trivial--the tier can be moved directly to the reception.
When all tiers originate at one location (the bakery), the problem
can be solved recursively as follows:
- Move the (N-1) smaller tiers from the current location of the Nth
tier to a location different than the destination.
- Move the Nth tier to the destination.
- Move the smaller (N-1) tiers to the destination.
The first and third steps of the algorithm are recursive.
They call Autosolve with CX=(CX+1) and DI set to
the destination needed by the current step. The solution divides
the problem into two sub-problems of size (N-1)
and the single-tier problem of moving the Nth plate to its destination.
With two tiers, the solution requires 3 steps. For three tiers,
the solution requires 3+1+3=7 steps.
In general, the number of moves required to solve a problem
with N tiers is equal to 2^n-1.
To solve the problem
when the tiers are randomly distributed, one extra step is required.
If the Nth tier is already located at the correct location,
the program skips steps one and two.
To control the speed of AutoSolve, the user must provide a keypress
just before each tier movement. While
AutoSolve is running, a blinking message should appear at
the bottom of the screen.
- MouseCtrl
- Purpose:
Generate a return code when "buttons" are pressed or a tier is moved.
- OutputAX=command, SI=source, DI=destination
- Description
The mouse allows the user to press buttons and move objects on the
screen. For this MP, the "buttons" are the messages with the
red background near the top of the screen. When the user clicks
the left mouse atop or near a button, this routine returns
a number in AX. The buttons are numbered from left to right
with the values 0 to 5. When the user moves a tier, this routine should
return the source and destination locations in registers SI and DI
and set AX=6.
Tiers are moved by placing the mouse on the source, pressing the
left mouse button, moving the mouse to the destination, then releasing
the button.
SI and DI should be encoded as: 0=bakery, 1=truck, and 2=recept.
- Notes
- The program spends most of the time in the MouseCtrl routine.
The program loops in this routine until the user has either clicked
a button or finished a movement (i.e., held and released the mouse button).
- The mouse status is read via software interrupts. By
loading the appropriate values into registers and executing
INT 33h, the location of
the mouse and the status of the buttons can be determined.
- The mouse interrupt functions are
documented in the Lab Manual.
- Notice that the mouse is initialized and made
visible in main. You need not repeat this code.
- A mouse drive is installed by default under
Windows XP and other newer versions of Microsoft
operating systems.
- To use the mouse in DOS, you must
install the mouse driver. On most machines, you
need only type 'MOUSE'.
- To use the mouse, you may need to run the program
in full-screen mode (hit [ALT-ENTER] in win95).
- Main
- Purpose:
Invoke the procedures described above.
- Description:
The main program begins by setting ES=VidTxtSeg,
calling distribute to create the first game,
calling drawscreen to show the initial screen,
then using INT 33h to initialize the mouse.
The rest of the main program contains an infinite loop that
calls MouseCtrl to read the user's command. Based on
the return value of AX (0..6), the appropriate procedure(s)
should be called.
Program Assignment
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.
- PrintString: 5 pts.
- ClearScreen: 5 pts.
- Random: 10 pts.
- DrawScreen: 10 pts.
- ReDrawScreen: 10 pts.
- ResetGame: 5 pts.
- Distribute: 10 pts.
- MoveTier: 10 pts.
- AutoSolve: 15 pts.
- MouseCtrl: 10 pts.
- Main: 10 pts.
- Note that points may be deducted for poor modularity,
lack of comments, and/or
poor programming style, as described in the course syallabus.
Preliminary Procedure
- You will begin MP2 with the following files:
- MP2.EXE: The fully functional program using library functions
- MP2.ASM: Program Framework
- LIBMP2.LIB: Working versions of all routines
- LIB306.LIB: Useful (and free) routines
- Makefile
- You can obtain these files by downloading:
Notes
- Main should process return values of AX=0..6 from MouseCtrl
- MouseCtrl should check that status of the mouse when the routine is
called. If the button is initially pressed; it should wait for
a release. This will avoid looping though main.
PAGE 75, 132
TITLE CSE306 - Bakery of Hanoi - Your Name - Date
COMMENT %
The Bakery of Hanoi
-------------------
CSE306: Machine Problem 2/3
Prof. John W. Lockwood
Washington University in St. Louis
Spring 2004
Revision 1.2 (Updated 3/19/04)
%
;====== Constants =========================================================
CR EQU 13
LF EQU 10
ESCKEY EQU 27
SPACE EQU 32
VIDTXTSEG EQU 0B800h ; VGA Video Segment Adddress (Text Mode)
;====== Externals =========================================================
; -- LIB306 Routines (Free) ---
extrn kbdine:near, kbdin:near, dspout:near ; LIB306 Routines
extrn dspmsg:near, binasc:near, ascbin:near ; (Always Free)
; -- LIBMP2/3 Routines (You need to write these on your own) ---
extrn LibPrintString:near
extrn LibClearScreen:near
extrn LibRandom:near
extrn LibMoveTier:near
extrn LibDrawScreen:near
extrn LibRedrawScreen:near
extrn LibResetGame:near
extrn LibDistribute:near
extrn LibMouseCtrl:near
extrn LibAutoSolve:near
extrn LibMain:near
extrn mp3xit:near
;====== Stack segment ====================================================
stkseg segment stack ; *** STACK SEGMENT ***
db 64 dup ('STACK ') ; 64*8 = 512 Bytes of Stack
stkseg ends
;====== Code/Data segment ================================================
cseg segment public 'CODE' ; *** CODE SEGMENT ***
assume cs:cseg, ds:cseg, ss:stkseg, es:nothing
;====== Variables =========================================================
Moves DW 0 ; Number of moves required (Reset to zero for each game)
Tiers DW 4 ; Number of Tiers (Default with 4 tiers)
Bakery DW 0000000000000001b ; -- Sample Bit-mapped array --
Truck DW 0000000000000010b ; ###
Recept DW 0000000000001100b ; ######### ####### #####
; Bakery Truck Recept
; Dest=0 Dest=1 Dest=2
WelcomeMessage db 'Welcome to the BAKERY of HANOI$'
PressEscKey db 'Press [Esc] key to continue$'
CheckBackground db 'Screen background should now be white$'
RandomNumberMessage db 'Random numbers in range {0..2}:$'
HanoiMsg db ' CSE306 MP 2/3 ver 1.2 '
db ' THE BAKERY OF HANOI '
db ' Lockwood Spr 2004','$'
; Note that this is really just one long string
RandSeed DW 13 ; Random Number Seed
PBUF db '$$$$$$$' ; A string to hold binary->ASCII converted numbers
PUBLIC HanoiMsg, Moves, Tiers, RandSeed, Bakery, Truck, Recept
;====== Procedures ========================================================
PrintString Proc near
call LibPrintString
; Comment the line above and add your own code here
ret
PrintString EndP
ClearScreen Proc near
call LibClearScreen
; Comment the line above and add your own code here
ret
ClearScreen EndP
Random Proc near
Call LibRandom
; Comment the line above and add your own code here
ret
Random EndP
DrawScreen Proc near
call LibDrawScreen
; Comment the line above and add your own code here
ret
DrawScreen EndP
RedrawScreen Proc near
call LibRedrawScreen
; Comment the line above and add your own code here
ret
RedrawScreen EndP
MoveTier Proc near
call LibMoveTier
; Comment the line above and add your own code here
ret
MoveTier EndP
ResetGame Proc near
call LibResetGame
; Comment the line above and add your own code here
ret
ResetGame EndP
Distribute Proc near
call LibDistribute
; Comment the line above and add your own code here
ret
Distribute EndP
MouseCtrl Proc near
call LibMouseCtrl
; Comment the line above and add your own code here
ret
MouseCtrl EndP
AutoSolve Proc near
call LibAutoSolve
; Comment the line above and add your own code here
ret
AutoSolve EndP
PUBLIC PrintString, ClearScreen, Random
PUBLIC MoveTier, DrawScreen, RedrawScreen, ResetGame
PUBLIC Distribute, MouseCtrl, AutoSolve
;====== Main procedure ====================================================
main proc far
mov ax, cseg ; Initialize DS register
mov ds, ax
mov ax, VIDTXTSEG ; Segment address of video memory
mov es, ax
mov AX, 0002h ; Put Video card into 80x25 text mode
int 10h
; ---- Display a few text messages when the program begins ----
MOV DI, 2*(80*10+25) ; Screen offset for Row=10, Column=25
MOV BX, offset WelcomeMessage
MOV AH, 3h ; Cyan=Green+Blue
call PrintString
ADD DI, 2*80 ; Print next message on line below the first
MOV BX, offset PressEscKey
MOV AH, 07h ; White text on black background
call PrintString
call kbdin ; Wait for user input by reading in a key
call ClearScreen ; Clear the screen (white background, black text)
MOV DI, 2*(80*10+25) ; Screen offset for Row=10, Column=25
MOV BX, offset CheckBackground
MOV AH, 74h ; White background with Red Text
call PrintString
ADD DI, 2*2*80 ; Print next message 2 lines below the first
MOV BX, offset RandomNumberMessage
MOV AH, 70h ; Black text on white background
Call PrintString
ADD DI, 2*32
MOV CX,10
PrintTenRandomNumbers:
PUSH AX
PUSH BX
PUSH DI
PUSH CX
Call Random ; Generate random number between 0..2
MOV BX, offset PBUF
Call BinAsc ; Convert to ASCII string
MOV AH, 70h ; Black text on white background
Call PrintString
POP CX
POP DI
POP BX
POP AX
ADD DI, 4
Loop PrintTenRandomNumbers
MOV DI, 2*(80*14+25) ; Row 14, Col. 25
MOV BX, offset PressEscKey
MOV AH, 70h ; Black text on white background
Call PrintString
call kbdin
; ---- The Program begins here ----
mov tiers, 4 ; Start with Default of 4 Cake Tiers
call Distribute ; Randomly distribute to bakery,truck,recept
call DrawScreen ; Draw the text-mode video screen
mov ax,0 ; init mouse
int 33h
mov ax,1 ; Show Mouse
int 33h
; -------------------------------------------
; Your MAIN code goes here
; -------------------------------------------
Call LibMain ; Replace this with your own code
call mp3xit ; Exit to DOS
main endp
cseg ends
end main