⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 madvent.asm

📁 ART OF Assembly Language Programming, 很不错
💻 ASM
📖 第 1 页 / 共 2 页
字号:
		repeat	MaxWeight
		local	NotThisOne
		cmp	bx, [di+ItemCnt]
		jne	NotThisOne
		mov	word ptr [di+ItemCnt], NULL
		ret
NotThisOne:
ItemCnt		=	ItemCnt+2
		endm

		ret
RemoveItem	endp


; InsertItem-	BX contains a pointer to an item, DI contains a pointer to
;		and item list.  This routine searches through the list for
;		the first empty spot and copies the value in BX to that point.
;		It returns the carry set if it succeeds.  It returns the
;		carry clear if there are no empty spots available.

InsertItem	proc

ItemCnt		=	0
		repeat	MaxWeight
		local	NotThisOne
		cmp	word ptr [di+ItemCnt], 0
		jne	NotThisOne
		mov	[di+ItemCnt], bx
		stc
		ret
NotThisOne:
ItemCnt		=	ItemCnt+2
		endm

		clc
		ret
InsertItem	endp





; LongDesc- Long description of an item.
; DI points at an item - print the long description of it.

LongDesc	proc
		push	di
		test	di, di
		jz	NoDescription
		mov	di, [di].item.LongDesc
		puts
		putcr
NoDescription:	pop	di
		ret
LongDesc	endp


; ShortDesc- Print the short description of an object.
; DI points at an item (possibly NULL).  Print the short description for it.

ShortDesc	proc
		push	di
		test	di, di
		jz	NoDescription
		mov	di, [di].item.ShortDesc
		puts
		putcr
NoDescription:	pop	di
		ret
ShortDesc	endp




; Describe: 	"CurRoom" points at the current room.  Describe it and its
;		contents.

Describe	proc
		push	es
		push	bx
		push	di
		mov	di, ds
		mov	es, di

		mov	bx, CurRoom
		mov	di, [bx].room.Description
		print
		byte	"You are currently ",0
		puts
		putcr
		print
		byte	"Here you find the following:",cr,lf,0

; For each possible item in the room, print out the long description
; of that item.  The repeat macro generates a code sequence for each
; possible item that could be in this room.

ItemCnt		=	0
		repeat	MaxWeight
		mov	di, [bx].room.ItemList[ItemCnt]
		call	LongDesc

ItemCnt		=	ItemCnt+2
		endm


		pop	di
		pop	bx
		pop	es
		ret
Describe	endp






; Here is the main program, which actually plays the game.

Main		proc
		mov	ax, dseg
		mov	ds, ax
		mov	es, ax
		meminit

		print
		byte	cr,lf,lf,lf,lf,lf
		byte	"Welcome to ",'"MADVENTURE"',cr,lf
		byte	'If you need help, type the command "HELP"'
		byte	cr,lf,0

RoomLoop:	dec	CurScore		;One point for each move.
		jnz	NotOverYet

; If they made too many moves without dropping anything properly, boot them
; out of the game.

		print
		byte	"WHOA!  You lost!  You get to join the legions of "
		byte	"the totally lame",cr,lf
		byte	'who have failed at "MADVENTURE"',cr,lf,0
		jmp	Quit

; Okay, tell 'em where they are and get a new command from them.

NotOverYet:	putcr
		call	Describe
		print
		byte	cr,lf
		byte	"Command: ",0
		lesi	InputLine
		gets
		strupr			;Ignore case by converting to U.C.

; Okay, process the command.  Note that we don't actually check to see
; if there is a properly formed sentence.  Instead, we just look to see
; if any important keywords are on the line.  If they are, the pattern
; matching routines load the appropriate values into the noun and verb
; variables (nouns: north=1, south=2, east=3, west=4, lime=5, beer=6,
; card=7, sign=8, program=9, homework=10, money=11, form=12, coupon=13;
; verbs: go=1, get=2, drop=3, inventory=4, quit=5, help=6).
;
; This code uses the noun and verb variables as indexes into a two
; dimensional array whose elements contain the address of the code
; to process the given command.  If a given command does not make
; any sense (e.g., "go coupon") the entry in the table points at the
; bad command code.

		mov	Noun, 0
		mov	Verb, 0
		mov	NounPtr, 0

		ldxi	VerbPat
		xor	cx, cx
		match

		lesi	InputLine
		ldxi	NounPat
		xor	cx, cx
		match

; Okay, index into the command table and jump to the appropriate
; handler.  Note that we will cheat and use a 14x8 array.  There
; are really only seven verbs, not eight.  But using eight makes
; things easier since it is easier to multiply by eight than seven.

		mov	si, CurRoom	;The commands expect this here.

		mov	bx, Noun
		shl	bx, 3		;Multiply by eight.
		add	bx, Verb
		shl	bx, 1		;Multiply by two - word table.
		jmp	cseg:jmptbl[bx]

; The following table contains the noun x verb cross product.
; The verb values (in each row) are the following:
;
;	NONE	GO	GET	DROP	INVNTRY	QUIT	HELP	unused
;	 0	 1	 2	 3	  4	 5	 6 	 7
;
; There is one row for each noun (plus row zero, corresponding to no
; noun found on line).

jmptbl		word	Bad		;No noun, no verb
		word	Bad		;No noun, GO
		word	Bad		;No noun, GET
		word	Bad		;No noun, DROP
		word	DoInventory	;No noun, INVENTORY
		word	QuitGame	;No noun, QUIT
		word    DoHelp		;No noun, HELP
		word	Bad		;N/A

NorthCmds	word	Bad, GoNorth, Bad, Bad, Bad, Bad, Bad, Bad
SouthCmds	word	Bad, GoSouth, Bad, Bad, Bad, Bad, Bad, Bad
EastCmds	word	Bad, GoEast, Bad, Bad, Bad, Bad, Bad, Bad
WestCmds	word	Bad, GoWest, Bad, Bad, Bad, Bad, Bad, Bad
LimeCmds	word	Bad, Bad, GetItem, DropItem, Bad, Bad, Bad, Bad
BeerCmds	word	Bad, Bad, GetItem, DropItem, Bad, Bad, Bad, Bad
CardCmds	word	Bad, Bad, GetItem, DropItem, Bad, Bad, Bad, Bad
SignCmds	word	Bad, Bad, GetItem, DropItem, Bad, Bad, Bad, Bad
ProgramCmds	word	Bad, Bad, GetItem, DropItem, Bad, Bad, Bad, Bad
HomeworkCmds	word	Bad, Bad, GetItem, DropItem, Bad, Bad, Bad, Bad
MoneyCmds	word	Bad, Bad, GetItem, DropItem, Bad, Bad, Bad, Bad
FormCmds	word	Bad, Bad, GetItem, DropItem, Bad, Bad, Bad, Bad
CouponCmds	word	Bad, Bad, GetItem, DropItem, Bad, Bad, Bad, Bad

; If the user enters a command we don't know how to process, print an
; appropriate error message down here.

Bad:		printf
		byte	"I'm sorry, I don't understand how to '%s'\n",0
		dword	InputLine
		jmp	NotOverYet


; Handle the movement commands here.
; Movements are easy, all we've got to do is fetch the NORTH, SOUTH,
; EAST, or WEST pointer from the current room's data structure and
; set the current room to that address.  The only catch is that some
; moves are not legal.  Such moves have a NULL (zero) in the direction
; field.  A quick check for this case handles illegal moves.

GoNorth:	mov	si, [si].room.North
		jmp	MoveMe

GoSouth:	mov	si, [si].room.South
		jmp	MoveMe

GoEast:		mov	si, [si].room.East
		jmp	MoveMe

GoWest:		mov	si, [si].room.West
MoveMe:		test	si, si			;See if move allowed.
		jnz	SetCurRoom
		printf
		byte	"Sorry, you cannot go in this direction."
		byte	cr, lf, 0
		jmp	RoomLoop

SetCurRoom:	mov	CurRoom, si		;Move to new room.
		jmp	RoomLoop


; Handle the GetItem command down here.  At this time the user
; has entered GET and some noun that the player can pick up.
; First, we will make sure that item is in this room.
; Then we will check to make sure that picking up this object
; won't overload the player.  If these two conditions are met,
; we'll transfer the object from the room to the player.

GetItem:	mov	bx, NounPtr		;Ptr to item user wants.
		mov	si, CurRoom
		lea	di, [si].room.ItemList	;Ptr to item list in di.
		call	CheckPresence		;See if in room.
		jc	GotTheItem
		printf
		byte	"Sorry, that item is not available here."
		byte	cr, lf, 0
		jmp	RoomLoop

; Okay, see if picking up this object will overload the player.

GotTheItem:	mov	ax, [bx].Item.Weight
		add	ax, CurWeight
		cmp	ax, MaxWeight
		jbe	WeightOkay
		printf
		byte	"Sorry, you are already carrying too many items "
		byte	"to safely carry\nthat object\n",0
		jmp	RoomLoop

; Okay, everything's cool, transfer the object from the room to the user.

WeightOkay:	mov	CurWeight, ax		;Save new weight.
		call	RemoveItem		;Remove item from room.
		lea	di, ItemsOnHand		;Ptr to player's list.
		call	InsertItem
		jmp	RoomLoop


; Handle dropped objects down here.

DropItem:	lea	di, ItemsOnHand		;See if the user has
		mov	bx, NounPtr		; this item on hand.
		call	CheckPresence
		jc	CanDropIt1
		printf
		byte	"You are not currently holding that item\n",0
		jmp	RoomLoop

; Okay, let's see if this is the magic room where this item is
; supposed to be dropped.  If so, award the user some points for
; properly figuring this out.

CanDropIt1:	mov	ax, [bx].item.key
		cmp	ax, CurRoom
		jne	JustDropIt

; Okay, success!  Print the winning message for this object.

		mov	di, [bx].item.WinDesc
		puts
		putcr

; Award the user some points.

		mov	ax, [bx].item.value
		add	CurScore, ax

; Since the user dropped it, they can carry more things now.

		mov	ax, [bx].item.Weight
		sub	CurWeight, ax

; Okay, take this from the user's list.

		lea	di, ItemsOnHand
		call	RemoveItem

; Keep track of how may objects the user has successfully dropped.
; When this counter hits zero, the game is over.

		dec	TotalCounter
		jnz	RoomLoop

		printf
		byte	"Well, you've found where everything goes "
		byte	"and your score is %d.\n"
		byte	"You might want to play again and see if "
		byte	"you can get a better score.\n",0
		dword	CurScore
		jmp	Quit


; If this isn't the room where this object belongs, just drop the thing
; off.  If this object won't fit in this room, ignore the drop command.

JustDropIt:	mov	di, CurRoom
		lea	di, [di].room.ItemList
		call	InsertItem
		jc	DroppedItem
		printf
		byte	"There is insufficient room to leave "
		byte	"that item here.\n",0
		jmp	RoomLoop

; If they can drop it, do so.  Don't forget we've just unburdened the
; user so we need to deduct the weight of this object from what the
; user is currently carrying.

DroppedItem:	lea	di, ItemsOnHand
		call	RemoveItem
		mov	ax, [bx].item.Weight
		sub	CurWeight, ax
		jmp	RoomLoop


; If the user enters the INVENTORY command, print out the objects on hand

DoInventory:	printf
		byte	"You currently have the following items in your "
		byte	"possession:",cr,lf,0
		mov	di, ItemsOnHand[0]
		call	ShortDesc
		mov	di, ItemsOnHand[2]
		call	ShortDesc
		mov	di, ItemsOnHand[4]
		call	ShortDesc
		mov	di, ItemsOnHand[6]
		call	ShortDesc
		printf
		byte	"\nCurrent score: %d\n"
		byte	"Carrying ability: %d/4\n\n",0
		dword	CurScore,CurWeight
		inc	CurScore		;This command is free.
		jmp	RoomLoop


; If the user requests help, provide it here.

DoHelp:		printf
		byte	"List of commands:",cr,lf,lf
		byte	"GO {NORTH, EAST, WEST, SOUTH}",cr,lf
		byte	"{GET, DROP} {LIME, BEER, CARD, SIGN, PROGRAM, "
		byte	"HOMEWORK, MONEY, FORM, COUPON}",cr,lf
		byte	"SHOW INVENTORY",cr,lf
		byte	"QUIT GAME",cr,lf
		byte	"HELP ME",cr,lf,lf
		byte	"Each command costs you one point.",cr,lf
		byte	"You accumulate points by picking up objects and "
		byte	"dropping them in their",cr,lf
		byte	"  appropriate locations.",cr,lf
		byte	"If you drop an item in its proper location, it "
		byte	"disappears from the game.",cr,lf
		byte	"The game is over if your score drops to zero or "
		byte	"you properly place",cr,lf
		byte	"  all items.",cr,lf
		byte	0
		jmp	RoomLoop


; If they quit prematurely, let 'em know what a wimp they are!

QuitGame:	printf
		byte	"So long, your score is %d and there are "
		byte	"still %d objects unplaced\n",0
		dword	CurScore, TotalCounter


Quit:		ExitPgm			;DOS macro to quit program.
Main		endp
cseg		ends

sseg		segment	para stack 'stack'
stk		db	1024 dup ("stack   ")
sseg		ends

zzzzzzseg	segment	para public 'zzzzzz'
LastBytes	db	16 dup (?)
zzzzzzseg	ends
		end	Main

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -