Stealth Game Enemy AI

Bucket Mouse

Active member
This isn't something I need right now, just something I've been thinking about. For an adventure game to have a stealth section, it needs enemies that recognize when the player is standing in front of them. I feel like I've absorbed enough of the NES programming language that I should be able to figure this out. I did not write the ASM itself yet; just the logic that it should follow.

First you need two variables: one to load tile positions onto, and a counting variable. We also need to determine how close you need to be for the enemy to see you...let's say it's five tiles.

First we would load the address of the tile the enemy is currently standing on into variable #1. Next we would need to read which direction that enemy is currently facing.

If facing right, the program would add 1 to the first variable, If facing left, the program would subtract 1. If facing up it would subtract 16; if facing down it would add 16.

Then it would CMP that tile with player1_object to see if there's a match. If not, the program would add 1 to the counting variable, then loop. If the counting variable equals 5 the program would end...until the next frame.

If player1_object is detected, the program would JMP or JSR to another routine, where you can put whatever you want to happen.....a text box, a fired projectile, a warp to a "jail" screen.

POSSIBLE BUG: If the enemy is looking right and the distance to the edge of the screen is less than 5, the enemy's sight would stretch all the way to the next row of tiles on the left side of the screen. This could lazily be avoided by strategically placing objects so the player can't stand in that zone. An actual solution would be more complicated.

The biggest hurdle in actually writing the ASM for this would be finding the names for the directions the enemy faces, since the program needs to determine which kind of math to use. There is a FaceDirection macro, but it uses two values, not one.
 

dale_coop

Moderator
Staff member
Something like the "Proxomity trigger" script? http://nesmakers.com/viewtopic.php?p=12104#p12104
Maybe you could adapt it to your needs?
 

Bucket Mouse

Active member
May not be necessary. I wrote out the ASM this morning. Haven't tested it yet; maybe you could inspect for errors. One thing I remembered (thankfully) was that the screen counts position by PIXEL, not TILE, so the addition / subtraction had to be far greater to work.

THERE IS ONE THING MISSING THOUGH: isThePlayerHere is not defined yet...because I'm not sure what to do to define it. I don't know what is loaded into X when this code starts up! I'm hoping it's the ID of the monster, so I can simply read Object_x_hi,x or Object_y_hi,x and load its current location into the variable. If it's not already there, then that's a pain, because it means I would have to duplicate this AI script four times for the four possible on-screen monsters. Do I have to do that, or not?

Nobody try this -- it's a draft and probably won't work:

Code:
SightAI:
LDA Object_movement,x
CMP #%00000000 ;; down
BEQ CheckDown

CMP #%00000100 ;; up
BEQ CheckUp

CMP #%000000110 ;; left
BEQ CheckLeft

CMP #%000000010 ;; right
BEQ CheckRight

JMP +++

CheckDown:

	LDX player1_object
	LDA Object_y_hi,x ;; load vertical location of player
	CMP isThePlayerHere
	BEQ + ;; if it is, go to detect routine
	LDA isThePlayerHere ;; add 16 to screen address to check next vertical tile
	SEC
	ADC #$FF ; 256 in hex
	JMP ++

CheckUp:

	LDX player1_object
	LDA Object_y_hi,x ;; load vertical location of player
	CMP isThePlayerHere
	BEQ + ;; if it is, go to detect routine
	LDA isThePlayerHere ;; subtract 16 from screen address to check next vertical tile
	SEC
	SBC #$FF ; 256 in hex
	JMP ++

CheckLeft:

	LDX player1_object
	LDA Object_x_hi,x ;; load horizontal location of player
	CMP isThePlayerHere
	BEQ + ;; if it is, go to detect routine
	LDA isThePlayerHere ;; add 1 to screen address to check next horizontal tile
	SEC
	ADC #$0F ; 16 in hex
	JMP ++

CheckRight:

	LDX player1_object
	LDA Object_x_hi,x ;; load horizontal location of player
	CMP isThePlayerHere
	BEQ + ;; if it is, go to detect routine
	LDA isThePlayerHere ;; subtract 1 from screen address to check next horizontal tile
	SEC
	SBC #$0F ; 16 in hex
	JMP ++


+
	JMP PlayerDetected

++
	LDA CountingVariable
	CMP #$05
	BEQ +++
	INC CountingVariable
	JMP SightAI

+++
	LDA #$00
	STA CountingVariable

PlayerDetected is intentionally not part of this....it would be in its own ASM file, which would make it easier to put in whatever you want to happen.
 
Top Bottom