Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
AI for Pac
#1
Hey, anyone, got any good code for smarter AI in my Pac-man Clone?, my AI is so stupid.....
please help......

thanx, bye
Reply
#2
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.
Reply
#3
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
Reply
#4
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 Smile
SCUMM (the band) on Myspace!
ComputerEmuzone Games Studio
underBASIC, homegrown musicians
[img]http://www.ojodepez-fanzine.net/almacen/yoghourtslover.png[/i
Reply
#5
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.
Reply
#6
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?
Reply
#7
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.
Reply
#8
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.
Reply
#9
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.
Reply
#10
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
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)