;Jim Piotrowski, Sarah Rovito, Neal Heinrich ;HTW 4/21 10:38 AM ;This is the submitted version .org 0h .equ marker, 40h; points to first square in mem start: mov SP, #07h; needed to fix glitch in J51 sim - initializes stack pointer to correct value mov TMOD, #20h ; set timer 1 for auto reload mov TCON, #41h ; run counter 1 edge trig mov TH1, #0FDh ; 9600 baud mov SCON,#50h ; 8-bit data mode 1 mov dptr, #openingscreen lcall puts lcall outputcr lcall getchar init: mov R0, #marker mov A, #16 mov R3, #4 ;R3 is the number of arrows folder ; note R6 holds the random number asgnmk: ;fill board with zeroes mov @r0, #0 inc r0 dec a jnz asgnmk setplayer: ;set player's spot lcall rand8 anl a, #15 add a, #marker mov R0, a mov @r0, #'U' setwumpus: ;set wumpus's spot lcall rand8 anl a, #15 add a, #marker mov R0, a mov a, @r0 cjne a, #0, setwumpus ;get new position if already taken mov @r0, #'W' setpit: ; set the pit lcall rand8 anl a, #15 add a, #marker mov R0, a mov a, @r0 cjne a, #0, setpit ;get new position if already taken mov @r0, #'P' setbats: ; set the bats lcall rand8 anl a, #15 add a, #marker mov R0, a mov a, @r0 cjne a, #0, setbats ;get new position if already taken mov @r0, #'B' lcall rand8 anl a, #15 add a, #marker mov R0, a mov a, @r0 cjne a, #0, setbats ;get new position if already taken mov @r0, #'B' actprog: ;the actual game loop lcall showboard ;show the board lcall status ;show text for surroundings lcall moveplayer ;function for moving player lcall movehandler ;function for handling player movement cjne a, #2, notbat lcall batmove ;if player enters bat space notbat: lcall movewumpus ;move the wumpus jz actprog ;if 0 is in acc, program is in a non-terminal state ;and needs to run game loop again mov dptr, #nothergame ;game has ended, show message and restart lcall outputcr lcall puts lcall getchar sjmp init showboard: ;show the board mov r1, #16 mov r0, #marker brdloop: mov a, r1 anl a, #3h; is a mult of 4? for cr's for drawing board jnz putspot mov a, #10 lcall outputa putspot: mov a, #'|' lcall outputa mov a, @r0 clr c subb a, #'U' cjne a, #0, notU mov a, #'U' lcall outputa ljmp afterUcheck notU: mov a, #0 lcall outputa afterUcheck: inc r0 dec r1 mov a, r1 jnz brdloop mov a, #10 lcall outputa ret moveplayer: ;move the player lcall outputcr lcall outputcr mov dptr, #choosemsg lcall puts lcall outputcr getmove: ;get the move lcall charin cjne a, #'a', notleft lcall moveleft mov r0, #0xFFh sjmp moved notleft: cjne a, #'d', notright lcall moveright mov r0, #0xFFh ;mark that movement has been done sjmp moved notright: cjne a, #'w', notup lcall moveup mov r0, #0xFFh ;mark that movement has been done sjmp moved notup: cjne a, #'s', notdown lcall movedown mov r0, #0xFFh ;mark that movement has been done sjmp moved notdown: cjne a, #'f', notfire lcall firearrow ;function sets r0 to FF if action has occured notfire: moved: lcall outputcr cjne r0, #0xFFh, getmove ret firearrow: ;if f is pushed to fire an arrow mov a, r3 jnz hasarrows ;check for arrows in R3 lcall outputcr mov dptr, #noarrows ;no arrows branch lcall puts lcall outputcr mov a, #1 mov r0, #0xFFh ret hasarrows: ;fire arrows dec r3 lcall playerpos mov dptr, #firemsg lcall puts lcall charin cjne a, #'d', notfireright mov a, r1 anl a, #3 subb a, #3 jz invalidfire lcall fireright ;will set r0 to correct marker ret notfireright: cjne a, #'a', notfireleft mov a, r1 anl a, #3 jz invalidfire lcall fireleft ;will set r0 to correct marker ret notfireleft: cjne a, #'s', notfiredown mov a, r1 clr c rrc a clr c rrc a clr c subb a, #3 jz invalidfire lcall firedown ret notfiredown: cjne a, #'w', notfireup mov a, r1 clr c rrc a clr c rrc a clr c jz invalidfire lcall fireup ret notfireup: invalidfire: lcall missedshot ret fireright: mov a, r1 inc a add a, #marker mov r0, a mov a, @r0 clr c subb a, #'W' jnz missedright lcall killedwumpus ret missedright: lcall missedshot ret fireleft: mov a, r1 dec a add a, #marker mov r0, a mov a, @r0 clr c subb a, #'W' jnz missedleft lcall killedwumpus ret missedleft: lcall missedshot ret firedown: mov a, r1 add a, #4 add a, #marker mov r0, a mov a, @r0 clr c subb a, #'W' jnz misseddown lcall killedwumpus ret misseddown: lcall missedshot ret fireup: mov a, r1 subb a, #4 add a, #marker mov r0, a mov a, @r0 clr c subb a, #'W' jnz missedup lcall killedwumpus ret missedup: lcall missedshot ret killedwumpus: mov dptr, #shothit lcall outputcr lcall puts lcall outputcr mov r0, #0xFFh mov a, #5 ret missedshot: mov dptr, #shotmissed lcall outputcr lcall puts lcall outputcr mov r0, #0xFFh mov a, #1 ret status: ;get the status of the 4 surrounding spaces mov r0, #marker mov r1, #0 statloop: clr c mov a, @r0 subb a, #'U' jz text; r1 holds position, # 0-15 inc r1 inc r0 sjmp statloop text: mov a, r1 anl a, #3 jz afterlookleft lcall lookleft afterlookleft: ;the next calls use logic of the grid to decide if neighboring spaces are "in bounds" subb a, #3 jz afterlookright lcall lookright afterlookright: mov a, r1 clr c ;divide by 4 rrc a clr c rrc a clr c jz afterlookup lcall lookup afterlookup: subb a, #3 jz afterlookdown lcall lookdown afterlookdown: lcall arrowdisp ;display arrow inventory ret arrowdisp: mov r7, a mov dptr, #arwbegin lcall puts mov a, r3 add a, #'0' lcall outputa mov dptr, #arwend lcall puts lcall outputcr lcall outputcr mov a, r7 ret ;handling functions for each direction lookleft: mov r7, a mov a, r1 add a, #marker mov r0,a dec r0 mov a, @r0 lcall checkresult mov a, r7 ret lookright: mov r7, a mov a, r1 add a, #marker mov r0,a inc r0 mov a, @r0 lcall checkresult mov a, r7 ret lookup: mov r7, a mov a, r1 add a, #marker subb a, #4 mov r0,a mov a, @r0 lcall checkresult mov a, r7 ret lookdown: mov r7, a mov a, r1 add a, #marker add a, #4 mov r0,a mov a, @r0 lcall checkresult mov a, r7 ret checkresult: ;function that handles what's in surrounding spaces jz returncheckresult; nothing there, no report mov a, @r0 cjne a, #'W', pitcheck lcall nearwumpus lcall outputcr pitcheck: cjne a, #'P', batcheck lcall nearpit lcall outputcr batcheck: cjne a, #'B', wumpusandpitcheck lcall nearbats lcall outputcr wumpusandpitcheck: cjne a, #'Q', wumpusandbatcheck lcall nearwumpus lcall outputcr lcall nearpit lcall outputcr wumpusandbatcheck: cjne a, #'C', returncheckresult ;SHOULD never jump from here lcall nearwumpus lcall outputcr lcall nearbats lcall outputcr returncheckresult: ret outputa: ;display what's in accumulator clr TI mov SBuF, a charout: jnb TI, charout ret getchar: ;get a char from the user charin: inc R6 jnb RI, charin clr RI mov a, SBUF ret ;display functions for status nearwumpus: mov dptr, #wummsg lcall puts ret nearpit: mov dptr, #pitmsg lcall puts ret nearbats: mov dptr, #batmsg lcall puts ret outputcr: ;display a carriage return mov b, a mov a,#10 lcall outputa mov a, b ret puts: ;put a string(stolen from hello world) clr a movc a,@a+dptr jz putret clr TI mov SBUF, A puts1: jnb TI,puts1 inc dptr sjmp puts putret: ret ;move functions for moving the player moveleft: lcall playerpos mov a, r1 ;check if left is possible by modding r1 by 4 anl a, #3 jnz leftexists mov a, #1 ;might want to mark error later ret leftexists: dec r0 mov a, @r0 jnz hazard mov @r0, #'U' inc r0 mov @r0, #0 mov a, #1 ret moveright: lcall playerpos mov a, r1 ;check if right is possible by modding r1 by 4 and subbing 3 anl a, #3 subb a, #3 jnz rightexists mov a, #1 ;might want to mark out of bounds error later ret rightexists: inc r0 mov a, @r0 jnz hazard mov @r0, #'U' dec r0 mov @r0, #0 mov a, #1 ;might want to mark out of bounds error later ret moveup: lcall playerpos mov a, r1 ;check if right is possible by modding r1 by 4 and subbing 3 clr c ;divide by 4 rrc a clr c rrc a clr c jnz upexists mov a, #1 ;might want to mark out of bounds error later ret upexists: mov a, r0 subb a, #4 mov r0, a mov a, @r0 jnz hazard mov @r0, #'U' mov a, r0 add a, #4 mov r0, a mov @r0, #0 mov a, #1 ret ;put in middle for memory jumping range purposes hazard: cjne a, #'B', bathazard mov a, #3 ;batted ret bathazard: cjne a, #'P', pithazard mov a, #2 ;pitted ret pithazard: mov a, #4 ;wumpus by elimination ret movedown: lcall playerpos mov a, r1 ;check if down is possible by dividing by 4 and subbing 3 clr c ;divide by 4 rrc a clr c rrc a clr c subb a, #3 jnz downexists mov a, #1 ;might want to mark out of bounds error later ret downexists: mov a, r0 add a, #4 mov r0, a mov a, @r0 jnz hazard mov @r0, #'U' mov a, r0 subb a, #4 mov r0, a mov @r0, #0 mov a, #1 ;might want to mark out of bounds error later ret movehandler: cjne a, #1, isterminal mov a, #0 lcall addarrow ret isterminal: cjne a, #2, pasthandpit mov dptr, #pitdeath lcall puts lcall outputcr mov a, #1 ret pasthandpit: ;past pitdeath cjne a, #3, pasthandbat mov dptr, #batmovemsg lcall puts lcall outputcr mov a, #2 ret pasthandbat: cjne a, #4, pastwumpusfood mov dptr, #wumpusdeath lcall puts lcall outputcr mov a ,#1 ret pastwumpusfood: mov a, #1 ret playerpos: ;put player location in r1 mov r1, #0 mov r0, #marker iterateloc: clr c ;first, is move legal? - find player pos mov a, @r0 subb a, #'U' jz doneiterate; r1 holds position, # 0-15 inc r1 inc r0 sjmp iterateloc doneiterate: ret wumpuspos: ;put wumpus location in r1 mov r1, #0 mov r0, #marker iteratewloc: clr c mov a, @r0 subb a, #'W' jz donewiterate clr c mov a, @r0 subb a, #'Q' jz donewiterate clr c mov a, @r0 subb a, #'C' jz donewiterate inc r1 inc r0 sjmp iteratewloc donewiterate: ret movewumpus: ;function for moving the wumpus jz isneeded ret isneeded: mov r7, a lcall rand8 anl a, #3 ;want a 1 in 4 of wumpus staying still inc a ;make 3 = 4 clr c rrc a ;shift right twice clr c rrc a clr c cjne a, #0, wmoved ;can only equal 1 or 0, jump if 1 invalidwmove: lcall wumpuspos lcall rand8 anl a, #7 clr c rrc a clr c cjne a, #0, skipzero lcall movewup sjmp wmoved skipzero: cjne a, #1, skipone lcall movewdown sjmp wmoved skipone: cjne a, #2, skiptwo lcall movewright sjmp wmoved skiptwo: lcall movewleft sjmp wmoved wmoved: jz invalidwmove mov a, r7 ret movewup: mov a, r1 jz nowspace dec a jz nowspace dec a jz nowspace dec a jz nowspace dec a add a, #marker mov r0, a mov a, @r0 cjne a, #0, wblocked;is pit or bat in wumpus's movement? mov @r0, #'W' sjmp wcleanup wblocked: cjne a, #'U', notplayer mov dptr, #wumpuscaught ;the wumpus moved into the player's spot lcall outputcr lcall puts mov R7, #1 mov a, #1 ret notplayer: inc a ;since pit and bat's occupied letters are one up, just inc! mov @r0, a sjmp wcleanup movewdown: mov a, r1 subb a, #16 ;so that a hits zero and jumps if a > 11 inc a jz nowspace inc a jz nowspace inc a jz nowspace inc a jz nowspace add a, #16 ;restore a so that it's a valid location add a, #marker mov r0, a mov a, @r0 cjne a, #0, wblocked;is pit or bat in wumpus's movement? mov @r0, #'W' sjmp wcleanup movewleft: mov a, r1 anl a, #3 jz nowspace mov a, r1 dec a add a, #marker mov r0, a mov a, @r0 cjne a, #0, wblocked;is pit or bat in wumpus's movement? mov @r0, #'W' sjmp wcleanup movewright: mov a, r1 anl a, #3 subb a, #3 jz nowspace mov a, r1 inc a add a, #marker mov r0, a mov a, @r0 cjne a, #0, wblocked;is pit or bat in wumpus's movement? mov @r0, #'W' sjmp wcleanup wcleanup: mov a, r1 add a, #marker mov r0, a mov a, @r0 cjne a, #'W', notclear mov @r0, #0 mov a, #1 ;nonzero value so that movewumpus doesn't loop ret notclear: dec a mov @r0, a mov a, #1 ;nonzero value so that movewumpus doesn't loop ret nowspace: mov a, #0 ;force movewumpus to loop ret batmove: ;player jumped into a bat space lcall playerpos mov a, r1 add a, #marker mov r0, a mov @r0, #0 moveplr: lcall rand8 anl a, #15 add a, #marker mov r0, a mov a, @r0 jnz moveplr mov @r0, #'U' ret addarrow: mov r7, a mov a, r3 subb a, #9 jz nonewarrow lcall rand8 anl a, #7 cjne a, #5, nonewarrow mov dptr, #foundarrow lcall puts inc r3 nonewarrow: mov a, r7 ret rand8: ;RNG, is linear congruential with the form 221*x + 53 ;is seeded by counting cycles while waiting for input mov a, r6 cjne a, #0, notzero inc a notzero: mov b, #221 mul AB add a, #53 mov r6, a ret batmsg: .byte 'Y','o','u',' ','h','e','a','r',' ','b','a','t','s',0 wummsg: .byte 'Y','o','u',' ','s','m','e','l','l',' ','a',' ', 'w','u','m','p','u','s',0 pitmsg: .byte 'Y','o','u',' ','f','e','e','l',' ','a',' ','d','r','a','f','t',0 choosemsg: .byte "Please press w,a,s,or d for a direction or press f to fire." .byte 0 pitdeath: .byte "You fell into a pit. Have a nice afterlife." .byte 0 batmovemsg: .byte "The bats have carried you to a random space!" .byte 0 wumpusdeath: .byte "Congratulations! You're wumpus food!" .byte 0 firemsg: .byte "Please use w,a,s,or d to choose a direction of fire" .byte 0 shotmissed: .byte "You missed!" .byte 0 shothit: .byte "You killed the wumpus...nice work!" .byte 0 wumpuscaught: .byte "The wumpus found you!! Hope you're full of vitamins and minerals!" .byte 0 openingscreen: .byte "Welcome to Hunt the Wumpus, where you hunt the most dangerous of\nany animal " .byte "that has ever walked the earth! Your only friend is your trusty\nbow and " .byte "arrow. In the caves are pits that drop you to your death and bats\nthat " .byte "pick you up and move you to random places. Good Hunting!\n" .byte "Press a key to continue!\n" .byte 0 noarrows: .byte "You have no arrows...better try to find one!" .byte 0 arwbegin: .byte "You have " .byte 0 arwend: .byte " arrows" .byte 0 nothergame: .byte "Please press a key to play another game!\n" .byte 0 foundarrow: .byte "\n\nYou found an arrow!\n\n" .byte 0