Posts: 19
Threads: 7
Joined: May 2003
Hey, anyone, got any good code for smarter AI in my Pac-man Clone?, my AI is so stupid.....
please help......
thanx, bye
Posts: 3,368
Threads: 195
Joined: Jan 2003
why don't you post your game, and i'll see what i kin do.
Peace cannot be obtained without war. Why? If there is already peace, it is unnecessary for war. If there is no peace, there is already war."
Visit www.neobasic.net to see rubbish in all its finest.
Posts: 2,020
Threads: 24
Joined: Jun 2002
you want them to go after pac man?
Quote:dx = ghost(n).x - pac.x
dy = ghost(n).y - pac.y
sdx = sgn(dx)
sdy = sgn(dy)
if dx > dy then ghost(n).x = ghost.x - sdx
if dy > dx then ghost(n).y = ghost(n).y - sdy
but then i think they'd just get in a long line after pac man. i dont know. maybe you can do a parameter thing, if they're x close to pac they start going after him.
i]"I know what you're thinking. Did he fire six shots or only five? Well, to tell you the truth, in all this excitement, I've kinda lost track myself. But being as this is a .44 Magnum ... you've got to ask yourself one question: 'Do I feel lucky?' Well, do ya punk?"[/i] - Dirty Harry
Posts: 6,419
Threads: 74
Joined: Mar 2002
Well, I can't point you to code, but I can give you some ideas: There is a technique easy to implement that gives not-so-dumb AI. Just take your maze and set "hot spots" in each corner, for example:
Code: xxxxxxxxxxxxx
x* *x
x xxxxxxxxx x
x x* *x
x x xxxxxxxxx
x x* *x
x xxxxxxxxx x
x* *x
xxxxxxxxxxxxx
'x' are the walls, and * are the hotspots.
Enemies have fixed paths (up, down, left or right), and they move in the same direction until they reach a hot spot. When that happens, they check where the player is and pick a new direction to approach him.
This can be improved making the enemies change their paths when the player is "in sight", that is, when the player is in the same corridor (for example, if the player and the enemy are in the same corridor and the player is to the right but the enmy is moving left, the enemy changes his path and begins moving right).
Just some ideas
Posts: 1,813
Threads: 284
Joined: Mar 2003
A concept I just thought of is slope (y-x or something) to determine where the player is in regards to where the enemy is, and then use that as a radius to determine if the player is close enough to attack.
earn.
Posts: 19
Threads: 7
Joined: May 2003
ok heres my code so far......(its a text based game so far.....i wanna put graphics tho).........ok here......
Code: CLS
SCREEN 7
DIM maze$(6)
maze$(1) = "#############"
maze$(2) = "#....#.#....#"
maze$(3) = "#..###.###..#"
maze$(4) = "#.##.. ..##.#"
maze$(5) = "#....###....#"
maze$(6) = "#############"
row = 4
col = 5
ghostrow = 2
ghostcol = 7
dots = 28
DO
LOCATE 1, 1
FOR count = 1 TO 6
PRINT maze$(count)
NEXT count
LOCATE row, col
PRINT "C"
LOCATE ghostrow, ghostcol
COLOR 4
PRINT "G"
COLOR 15
IF dots = 0 THEN
LOCATE 8, 1
PRINT "You Have Won"
END
END IF
IF ((row = ghostrow) AND (col = ghostcol)) THEN
LOCATE 8, 1
PRINT "Your Dead"
END
END IF
DO
press$ = INKEY$
LOOP UNTIL press$ <> ""
oldrow = row
oldcol = col
SELECT CASE press$
CASE "w"
row = row - 1
CASE "s"
row = row + 1
CASE "a"
col = col - 1
CASE "d"
col = col + 1
END SELECT
SELECT CASE MID$(maze$(row), col, 1)
CASE "#"
row = oldrow
col = oldcol
CASE "."
MID$(maze$(row), col, 1) = " ": BEEP
dots = dots - 1
END SELECT
'*******************
'Ghost Movements
'*******************
IF RND < .8 THEN
oldrow = ghostrow
SELECT CASE ghostrow
CASE IS < row
ghostrow = ghostrow + 1
CASE IS > row
ghostrow = ghostrow - 1
END SELECT
oldrow = ghostrow
SELECT CASE ghostcol
CASE IS < row
ghostrow = ghostrow + 1
CASE IS > row
ghostrow = ghostrow - 1
END SELECT
IF MID$(maze$(ghostrow), ghostcol, 1) = "#" THEN
ghostrow = oldrow
END IF
IF ghostrow = oldrow THEN
oldcol = ghostcol
SELECT CASE ghostcol
CASE IS < col
ghostcol = ghostcol + 1
CASE IS > col
ghostcol = ghostcol - 1
END SELECT
END IF
IF MID$(maze$(ghostrow), ghostcol, 1) = "#" THEN
ghostcol = oldcol
END IF
END IF
LOOP UNTIL press$ = CHR$(13)
any suggestions?
Posts: 3,368
Threads: 195
Joined: Jan 2003
ok.
it's a simple pathfinding problem. I'm assuming you can't go NE, NW, etc? Only N S W E.
you fill the board until you reach pacman. Hold on, I'll try to add in the code.
Peace cannot be obtained without war. Why? If there is already peace, it is unnecessary for war. If there is no peace, there is already war."
Visit www.neobasic.net to see rubbish in all its finest.
Posts: 3,368
Threads: 195
Joined: Jan 2003
I changed your code.
I added the sub I used for pathfinding, but I need to change some things, so only random.move works currently.
Code: '$DYNAMIC
DECLARE SUB load.maze.pic (filename$)
DECLARE SUB refresh ()
DECLARE SUB print.board ()
DECLARE SUB print.pacman ()
DECLARE SUB print.ghosts ()
DECLARE SUB sleep2 ()
DECLARE SUB lose.life ()
DECLARE SUB game.win ()
DECLARE SUB game.lose ()
DECLARE SUB make.random.maze ()
DECLARE SUB random.move ()
DECLARE SUB smart.move (x0 AS INTEGER, y0 AS INTEGER, x1 AS INTEGER, y1 AS INTEGER)
DIM SHARED y.max AS INTEGER, x.max AS INTEGER, ghost.amount AS INTEGER, maze$(1)
DIM SHARED maze.data(1 TO 1, 1 TO 1) AS INTEGER
DIM temp(1 TO 1, 1 TO 1) AS INTEGER
ghost.amount = 2
load.maze.pic ("C:\qbasic\qb\maze1.txt")
'Actual game variables.
DIM SHARED pacman.row AS INTEGER, pacman.col AS INTEGER
DIM SHARED row.d AS INTEGER, col.d AS INTEGER
DIM SHARED ghostrow(ghost.amount) AS INTEGER, ghostcol(ghost.amount) AS INTEGER
DIM SHARED dots AS INTEGER, max.dots AS INTEGER, cur.ghost AS INTEGER
DIM SHARED pacman.move AS INTEGER, ghost.move AS INTEGER
DIM SHARED pacman.speed AS INTEGER, ghost.speed AS INTEGER
DIM SHARED win AS INTEGER
pacman.row = 4
pacman.col = 5
ghostrow(1) = 2
ghostcol(1) = 7
ghostrow(2) = 8
ghostcol(2) = 6
lives% = 1
ghost.speed% = 10
pacman.speed% = 3
ghost.intelligence% = 1 'from 0 to 1. 1 is DEADLY. 0 is RANDOM.
dots = max.dots
DIM SHARED x2b(4) AS INTEGER, y2b(4) AS INTEGER
x2b(1) = 1: y2b(1) = 0
x2b(2) = -1: y2b(2) = 0
x2b(3) = 0: y2b(3) = 1
x2b(4) = 0: y2b(4) = -1
refresh.rate% = 1000
CLS : SCREEN 7, 0, 0, 1: RANDOMIZE TIMER
DO: cycle% = refresh.rate%
DO
cycle% = cycle% + 1
IF cycle% > refresh.rate% THEN cycle% = 0: refresh
SELECT CASE INKEY$
CASE CHR$(27): exit.game% = 1: EXIT DO
CASE CHR$(0) + "H": row.d = -1: col.d = 0
CASE CHR$(0) + "P": row.d = 1: col.d = 0
CASE CHR$(0) + "K": col.d = -1: row.d = 0
CASE CHR$(0) + "M": col.d = 1: row.d = 0
END SELECT
IF win% <> 0 THEN PCOPY 0, 1: EXIT DO
LOOP
IF win% = -1 THEN lives% = lives% - 1: lose.life: sleep2: win% = 0
IF lives% = -1 THEN game.lose: EXIT DO
IF win% = 1 THEN game.win: EXIT DO
IF exit.game% = 1 THEN EXIT DO
LOOP
SYSTEM
REM $STATIC
SUB game.lose
COLOR 1: LOCATE 14, 1: PRINT "You're Dead..."
END SUB
SUB game.win
COLOR 14: LOCATE 14, 1: PRINT "You Won!"
END SUB
SUB load.maze.pic (filename$)
CLS
CLOSE
OPEN filename$ FOR INPUT AS #1
LINE INPUT #1, temp.maze$
x.max% = LEN(temp.maze$)
y.max% = (LOF(1) + 2) / (x.max% + 2)
REDIM maze$(1 TO y.max%)
maze$(1) = temp.maze$
FOR I% = 2 TO y.max%
LINE INPUT #1, maze$(I%)
NEXT I%
CLOSE
REDIM maze.data(x.max%, y.max%) AS INTEGER
FOR I% = 1 TO y.max%: FOR j% = 1 TO x.max%
cur.point$ = MID$(maze$(I%), j%, 1)
IF cur.point$ = "." THEN max.dots = max.dots + 1: maze.data%(j%, I%) = 1 ELSE IF cur.point$ = "#" THEN maze.data(j%, I%) = 2
NEXT j%
NEXT I%
END SUB
SUB lose.life
LOCATE 14, 1: PRINT "Lost one Life."
END SUB
SUB print.board
COLOR 15: LOCATE 1, 1
FOR I% = 1 TO y.max%
FOR j% = 1 TO x.max%
temp.data% = maze.data%(j%, I%)
IF temp.data% = 1 THEN PRINT "."; ELSE IF temp.data% = 2 THEN PRINT "#"; ELSE PRINT " ";
NEXT j%
PRINT
NEXT I%
END SUB
SUB print.ghosts
FOR I% = 1 TO ghost.amount%
LOCATE ghostrow(I%), ghostcol(I%)
COLOR 4: PRINT "G"
NEXT I%
END SUB
SUB print.pacman
LOCATE pacman.row, pacman.col: PRINT "C"
END SUB
SUB random.move
DIM move%(4)
I% = 0
FOR j% = -1 TO 1 STEP 2
I% = I% + 1
x.temp% = j% + ghostcol(cur.ghost%)
IF x.temp% <= x.max% THEN
IF x.temp% <> 0 THEN
IF maze.data%(j% + ghostcol(cur.ghost%), ghostrow(cur.ghost%)) <> 2 THEN
move%(I%) = 1
ELSE
move%(I%) = 0
END IF
END IF
END IF
NEXT j%
FOR j% = -1 TO 1 STEP 2
I% = I% + 1
y.temp% = j% + ghostrow(cur.ghost%)
IF y.temp% <= y.max% THEN
IF y.temp% <> 0 THEN
IF maze.data%(ghostcol(cur.ghost%), j% + ghostrow(cur.ghost%)) <> 2 THEN
move%(I%) = 1
ELSE
move%(I%) = 0
END IF
END IF
END IF
NEXT j%
IF move%(1) <> 0 OR move%(2) <> 0 THEN
IF move%(1) = 1 AND move%(2) = 1 THEN choice.x% = INT(RND * 2) + 1 ELSE IF move%(1) = 0 THEN choice.x% = 2 ELSE choice.x% = 1
END IF
IF move%(3) <> 0 OR move%(4) <> 0 THEN
IF move%(3) = 1 AND move%(4) = 1 THEN choice.y% = INT(RND * 2) + 3 ELSE IF move%(3) = 0 THEN choice.y% = 4 ELSE choice.y% = 3
END IF
IF choice.x% <> 0 AND choice.y% <> 0 THEN
IF INT(RND * 2) = 1 THEN choice% = choice.x% ELSE choice% = choice.y%
ELSE
IF choice.x% = 0 THEN choice% = choice.y% ELSE choice% = choice.x%
END IF
SELECT CASE choice%
CASE 1: ghostcol(cur.ghost%) = ghostcol(cur.ghost%) - 1
CASE 2: ghostcol(cur.ghost%) = ghostcol(cur.ghost%) + 1
CASE 3: ghostrow(cur.ghost%) = ghostrow(cur.ghost%) - 1
CASE 4: ghostrow(cur.ghost%) = ghostrow(cur.ghost%) + 1
END SELECT
FOR I% = 1 TO 4
move%(I%) = 0
NEXT I%
choice.x% = 0
choice.y% = 0
ERASE move%
END SUB
SUB refresh
pacman.move% = pacman.move% + 1
IF pacman.move% = pacman.speed% THEN
pacman.move% = 0
IF maze.data%(pacman.col + col.d, pacman.row + row.d) <> 2 THEN
pacman.row = pacman.row + row.d
pacman.col = pacman.col + col.d
row.d = 0: col.d = 0
IF maze.data%(pacman.col, pacman.row) = 1 THEN
maze.data%(pacman.col, pacman.row) = 0
BEEP
dots = dots - 1
END IF
END IF
END IF
'*******************
'Ghost Movement
'*******************
ghost.move% = ghost.move% + 1
IF ghost.move% = ghost.speed% THEN
ghost.move% = 0
FOR cur.ghost% = 1 TO ghost.amount%
'Get ghost movement possibilities.
IF ghost.intelligence > RND THEN random.move ELSE smart.move (pacman.col), (pacman.row), (ghostcol(cur.ghost%)), (ghostrow(cur.ghost%))
NEXT cur.ghost%
END IF
print.board
print.pacman
print.ghosts
PCOPY 0, 1
WAIT &H3DA, 8: WAIT &H3DA, 8, 8
'Test for lose condition.
FOR I% = 1 TO ghost.amount%
IF ((pacman.row = ghostrow(I%)) AND (pacman.col = ghostcol(I%))) THEN win% = -1: EXIT SUB
NEXT I%
'Test for win condition.
IF dots = 0 THEN win% = 1: EXIT SUB
END SUB
SUB sleep2
DO: LOOP UNTIL INKEY$ <> ""
END SUB
SUB smart.move (x0 AS INTEGER, y0 AS INTEGER, x1 AS INTEGER, y1 AS INTEGER)
'x0, y0 = destination
'x1, y1 = current location
DIM cost.min AS INTEGER, diff AS INTEGER, h AS INTEGER, I AS INTEGER, x1b AS INTEGER, y1b AS INTEGER
'define temp array
REDIM temp(0 TO x.max% + 1, 0 TO y.max% + 1) AS INTEGER
FOR I% = 0 TO x.max% + 1
temp%(I%, y.max%) = 2: temp%(0, y.max%) = 2
NEXT I%
FOR I% = 0 TO y.max% + 1
temp%(x.max%, I%) = 2: temp%(x.max%, 0) = 2
NEXT I%
REDIM path.x(1 TO max.dots) AS INTEGER, path.y(1 TO max.dots) AS INTEGER
'define other stuff
DIM j AS INTEGER, k AS INTEGER, exitloop AS INTEGER
DIM iteration.max AS INTEGER: iteration.max = max.dots
path.x(1) = x0: path.y(1) = y0: exitloop = 0
h = 0: I = 0: k = 0: endk = 1: temp(x0, y0) = 1
DO
IF h = iteration.max THEN random.move: EXIT SUB
h = h + 1
DO
IF I = iteration.max THEN I = 1 ELSE I = I + 1
x% = path.x(I)
y% = path.y(I)
FOR j = 1 TO 4
x2% = x% + x2b(j)
y2% = y% + y2b(j)
IF x2% < x.max% THEN
IF y2% < y.max% THEN
IF x2% > 0 THEN
IF y2% > 0 THEN
IF temp(x2%, y2%) = 0 THEN
IF maze.data(x2%, y2%) <> 2 THEN
IF k = iteration.max THEN k = 1 ELSE k = k + 1
path.x(k) = x2%
path.y(k) = y2%
temp(x2%, y2%) = h + 1
END IF
END IF
END IF
END IF
END IF
END IF
NEXT j
IF x1% = x% AND y1% = y% THEN exitloop = 1: EXIT DO
IF I = endk THEN EXIT DO
LOOP
endk = k
I = I - 1
LOOP UNTIL exitloop = 1
j = h: IF h < max.a THEN k = h ELSE k = max.a
DO: h = h - 1: cost.min = 32767
FOR I = 1 TO 4
IF temp(x1 + x2b(I), y1 + y2b(I)) <> h THEN
x1 = x1 + x2b(I)
y1 = y1 + y2b(I)
EXIT FOR
END IF
NEXT I
k = k - 1
IF k < 1 THEN EXIT DO
LOOP UNTIL k = 0
ghostrow(cur.ghost%) = y1
ghostcol(cur.ghost%) = x1
END SUB
Peace cannot be obtained without war. Why? If there is already peace, it is unnecessary for war. If there is no peace, there is already war."
Visit www.neobasic.net to see rubbish in all its finest.
Posts: 3,368
Threads: 195
Joined: Jan 2003
I set ghost.intelligence% all the way up to 1. However, I made him 10 times slower than pacman.
Peace cannot be obtained without war. Why? If there is already peace, it is unnecessary for war. If there is no peace, there is already war."
Visit www.neobasic.net to see rubbish in all its finest.
Posts: 19
Threads: 7
Joined: May 2003
I apprecitae your help, but we cannot use GOTO or GOSUB in our programs........i dunno why, the teacher wont let us, and even she doesnt know how to make the Ghosts smarter........and other ways without GOTO or GOSUB
|