
-----------------------------------
Blobe
Thu Sep 25, 2008 11:42 am

Pong AI
-----------------------------------
Hey, im trying to make a pong game with the second player as a computer, but i cant seem to egt the ai to work, so heres what i have and can someone please help me and give me some suggestions on how to make the paddle ahve a certian % chance to go to the ball. Thanks






var x, y, c, xinterval, yinterval, px, py, cx, cy, cinterval : int
var chars : array char of boolean
setscreen ("graphics:800,520,offscreenonly")
const INTENSITY := 300
var X : int
var hitMiss : int
X := 1
colorback (7)
cls
randint (c, 1, 15)
x := 400
y := 250
px := 50
py := 225
cx := 750
cy := 225
xinterval := 5
yinterval := 5
cinterval := 5

loop
    for I : 1 .. INTENSITY
        drawline (Rand.Int (0, maxx), Rand.Int (0, maxy), Rand.Int (0, maxx), Rand.Int (0, maxy), 7)
    end for
    drawfilloval (x, y, 10, 10, 9)
    drawfilloval (x, y, 5, 5, 11)

    x := x + xinterval
    y := y + yinterval
    if x >= maxx then
        xinterval := -5
    elsif x = 490 then
        yinterval := -5
    elsif y = 490 then
    %     cinterval := -5
    % elsif cy  py and y < py + 60) and x  5 then
        py := py - 5
    end if
    if chars (KEY_UP_ARROW) and py < 435 then
        py := py + 5
    end if

    randint (hitMiss, 1, 100)

    if hitMiss  400 then
    if cy > y then
    cy := cy - 5
    elsif cy < y then
    cy := cy + 5
    end if
        % cy := y - 10
    elsif hitMiss >=11 and x > 400 then
        cy := cy + yinterval
    end if

    % if x > 400 then
    % cy := cy - yinterval
    % end if
    drawfillbox (px, py, px + 15, py + 60, red)
    drawfillbox (cx, cy, cx + 15, cy + 60, red)
    drawfillbox (800, 520, 0, 500, 10)
    drawfillbox (402, 500, 398, 0, red)

    colorback (10)
    locate (1, 1)
    put cy
    delay (5)
    View.Update
    X := X + 1
    View.Update
end loop

-----------------------------------
Insectoid
Thu Sep 25, 2008 11:54 am

RE:Pong AI
-----------------------------------
Just make a Rand.Int and if it equals a certain number, the paddle goes for the ball. if you want a 1 in 3 chance, 


var num :=Rand.Int (1, 3)
if num = 3 then
    %go to ball
end if


-----------------------------------
Euphoracle
Thu Sep 25, 2008 2:16 pm

RE:Pong AI
-----------------------------------
You could give it an acceleration and increase/decrease that to a cap depending on whether it was "fast enough" to react, per say.  That would make it not only look more fluid, but also allow you to give it "bad" reflexes, good reflexes, and impossible reflexes ;)

-----------------------------------
SNIPERDUDE
Thu Sep 25, 2008 2:49 pm

RE:Pong AI
-----------------------------------
What I did for mine was when the ball reached a certain point (halfway maybe) in the direction towards him, he would chase after it (it would move in the direction of the ball to match the Y value), but the opponent only has a certain speed in which they can move (which can be the difficulty setting)

-----------------------------------
Blobe
Thu Sep 25, 2008 5:45 pm

Re: Pong AI
-----------------------------------
yea but insectoid where would to location of the ball be? im pretty new to programing, and i need some help

-----------------------------------
Insectoid
Thu Sep 25, 2008 7:04 pm

RE:Pong AI
-----------------------------------
IF you've drawn the ball, you already know the location of the ball. 


if paddley > bally then
     paddley-=1
end if


This will make the AI paddle go toward the ball.

The location of the ball is the Y value from when you drew the ball.

-----------------------------------
Blobe
Fri Sep 26, 2008 1:35 pm

Re: Pong AI
-----------------------------------
Ok, that works, but now the AI paddle dosent run smothley, it dose not look very good, can i make it so it picks 1 number between 1,3 (or w/e) and then if it picks the number it dosent pick another and it goes to the ball, other wise it will just go a random way?

-----------------------------------
btiffin
Fri Sep 26, 2008 6:59 pm

RE:Pong AI
-----------------------------------
This may or may not help.  A friend of mine produced pongster.  

http://www.digitalliquid.com/freeware.html
which leads to
http://www.pongster.com

It's heavy Flash/Director but you may be able to glean something from the sources.

Cheers

-----------------------------------
Euphoracle
Fri Sep 26, 2008 8:46 pm

RE:Pong AI
-----------------------------------
I was fiddling with this idea; I quickly spewed out some code that happens to look like a pong game.  What I did was I used a velocity to move the player's "block" as well as the computer's.  However, when the player moves their block to the bottom, it resets the velocity to zero, such that they won't have to recover from a negative velocity when they overdo it.  The computer, however, has to do this.  By increasing/decreased the average velocity that the computer uses (by adjusting it's maximum by a "dumb" rating), I was able to make an adjustable AI that can either be super intelligent by moving very slowly and avoiding this pitfall (thus creating the "cannot be beaten" ai) and an ai that overdid it too much and had to recover based on its dumbness.  This means that it is possible to animate my AI block so that it actually looks like a frantic player on the other end playing the game when it's in "dumb" mode, and like a calm, collected, professional when it is in "smart" mode.

-----------------------------------
SNIPERDUDE
Fri Sep 26, 2008 9:23 pm

RE:Pong AI
-----------------------------------
Pretty smart.  I like the "dumb" mode idea.

-----------------------------------
Blobe
Sun Sep 28, 2008 3:40 pm

Re: Pong AI
-----------------------------------
k i like the velocity idea, but i have no idea how to use it  :oops:

-----------------------------------
S_Grimm
Mon Sep 29, 2008 11:55 am

RE:Pong AI
-----------------------------------
velocity := 1
if input (KEY_DOWN_ARROW) then
playerx += velocity
end if

-----------------------------------
Euphoracle
Mon Sep 29, 2008 2:40 pm

RE:Pong AI
-----------------------------------
Well here's the early stuff I was working on before I changed it up to be decent and use as an example when I peer tutor the turing class next semester.  This is just the basic concept I was going on, but in UglyEdition (TM).


%this code is ugly, please wear safety goggles
setscreen ("graphics:600:600")
setscreen ("offscreenonly")

const PADDLE_H := 100
const PADDLE_W := 12
const PADDLE_LEFT_X := 25
const PADDLE_RIGHT_X := maxx - (25 + PADDLE_W)
const PADDLE_VCAP := 16
const PADDLE_STARTY := (maxy div 2) - (PADDLE_H div 2)
const PADDLE_FRIC := 1 %rate at which velocity of paddle decreases when idle
const PADDLE_V_STEP := 1 %rate at which velicity increases per stroke (the ai is dumb because this puts it in the hole)
const PADDLE_COLOR := green
const BALL_R := 6 %this is actually the diameter; i'm too lazy to rename it
const BALL_HR := BALL_R div 2
const BALL_V := 5
const BALL_COLOR := blue
const K_UP := chr (200)
const K_DOWN := chr (208)
const DUMB_AMOUNT := 7 %10=god, 1=fence post
const FPS := 1000 div 60 %millisec/sec

type BALL :
    record
        x, y : int
        vx, vy : int
    end record

type PADDLE : %if i was supercool and making this correctly, i wouldn't exempt the x and vx.  4 player pong anyone?
    record
        y : int
        vy : int
    end record

var ball : BALL
var p_paddle : PADDLE
var ai_paddle : PADDLE
var startpos := 0 %0=player 1=ai
var done := false
var chars : array char of boolean

fcn get_paddle_x (left : boolean) : int
    if (left) then
        result PADDLE_LEFT_X
    else
        result PADDLE_RIGHT_X
    end if
end get_paddle_x
proc approach (var value : int, target, step : int)
    var nv : int
    if (value > target) then
        nv := value - step
        if (nv < target) then
            value := target
        else
            value := nv
        end if
    elsif (value < target) then
        nv := value + step
        if (nv > target) then
            value := target
        else
            value := nv
        end if
    end if
end approach

proc reset_ball
    if (startpos = 0) then
        ball.x := PADDLE_LEFT_X + PADDLE_W + BALL_HR + 1
        ball.y := p_paddle.y + (PADDLE_H div 2) - BALL_R
    else
        ball.x := PADDLE_RIGHT_X - PADDLE_W - BALL_HR - 1
        ball.y := ai_paddle.y + (PADDLE_H div 2) - BALL_R
    end if
    ball.vx := 0
    ball.vy := 0
end reset_ball
proc reset_paddles
    p_paddle.y := PADDLE_STARTY
    p_paddle.vy := 0
    ai_paddle.y := PADDLE_STARTY
    ai_paddle.vy := 0
end reset_paddles
proc launch_ball
    var q := Rand.Int (0, 1)
    if (startpos = 0) then %so it doesn't instantly bounce back
        ball.vx := BALL_V
    else
        ball.vx := -BALL_V
    end if
    if (q = 0) then
        ball.vy := -BALL_V
    else
        ball.vy := BALL_V
    end if
end launch_ball
proc newgame
    reset_paddles
    reset_ball
    launch_ball
end newgame
proc win (left : boolean)
    if (left) then %player
        put "player wins"
        startpos := 0
    else %ai
        put "ai wins"
        startpos := 1
    end if

    put "play again? (y/n) " ..
    View.Update
    loop
        var c : string (1)
        getch (c)
        if (c = "y") then
            newgame
            exit
        elsif (c = "n") then
            done := true
            exit
        end if
    end loop
end win
fcn collide_with_paddle (var p : PADDLE, x, y : int, left : boolean) : boolean
    %vertexes
    var px := get_paddle_x (left)
    var x1 := px
    var x2 := px + PADDLE_W
    var y1 := p.y
    var y2 := p.y + PADDLE_H

    if (x < x2 and x > x1 and y > y1 and y < y2 and left) then
        result true
    elsif (x > x1 and x < x2 and y > y1 and y < y2 and (not left)) then
        result true
    end if
    result false
end collide_with_paddle
fcn collide_ball : boolean %true if game is done
    var new_x := ball.vx + ball.x
    var new_y := ball.vy + ball.y
    var changed := 0

    %top & bottom walls
    if (new_y < 0 or new_y > maxy) then
        ball.vy := -ball.vy
        changed := 1
    end if

    %game loser
    if (new_x < 0) then
        win (false)
        result true
    elsif (new_x > maxx) then
        win (true)
        result true
    end if

    %paddles
    if (collide_with_paddle (p_paddle, new_x, new_y, true)) then
        ball.vx := -ball.vx
    elsif (collide_with_paddle (ai_paddle, new_x, new_y, false)) then
        ball.vx := -ball.vx
    end if

    result false
end collide_ball
proc move_ball
    ball.x := ball.vx + ball.x
    ball.y := ball.vy + ball.y
end move_ball
proc do_player
    Input.KeyDown (chars)

    if (chars (K_UP)) then
        p_paddle.vy := min (p_paddle.vy + PADDLE_V_STEP, PADDLE_VCAP)
    elsif (chars (K_DOWN)) then
        p_paddle.vy := max (p_paddle.vy - PADDLE_V_STEP, -PADDLE_VCAP)
    else
        approach (p_paddle.vy, 0, PADDLE_FRIC)
    end if
    if (p_paddle.vy > 1) then
        p_paddle.y := min (p_paddle.y + p_paddle.vy, maxy - PADDLE_H)
        if (p_paddle.y = maxy - PADDLE_H) then
            p_paddle.vy := 0
        end if
    else
        p_paddle.y := max (p_paddle.y + p_paddle.vy, 0)
        if (p_paddle.y = 0) then
            p_paddle.vy := 0
        end if
    end if
end do_player
proc do_ai_think
    if (ball.vx < 0) then %looks more realistic if it idles when player is moving
        return
    end if
    var projected_y := ball.y + ball.vy
    var current_path := ai_paddle.y + ai_paddle.vy + (PADDLE_H div 2)

    if (projected_y > current_path) then
        ai_paddle.vy := min (ai_paddle.vy + PADDLE_V_STEP, round ((PADDLE_VCAP / 2) / (DUMB_AMOUNT / 10))) %makes it look dumb
    elsif (projected_y < current_path) then
        ai_paddle.vy := max (ai_paddle.vy - PADDLE_V_STEP, round ((-PADDLE_VCAP / 2) / (DUMB_AMOUNT / 10))) %and lose occasionally
    else
        approach (ai_paddle.vy, 0, PADDLE_FRIC)
    end if

    if (ai_paddle.vy > 1) then
        ai_paddle.y := min (ai_paddle.y + ai_paddle.vy, maxy - PADDLE_H)
    else
        ai_paddle.y := max (ai_paddle.y + ai_paddle.vy, 0)
    end if
end do_ai_think

proc drawball
    drawfilloval (ball.x, ball.y, BALL_HR, BALL_HR, BALL_COLOR)
end drawball
proc drawplayer
    drawfillbox (PADDLE_LEFT_X, p_paddle.y, PADDLE_LEFT_X + PADDLE_W, p_paddle.y + PADDLE_H, PADDLE_COLOR)
end drawplayer
proc drawai
    drawfillbox (PADDLE_RIGHT_X, ai_paddle.y, PADDLE_RIGHT_X + PADDLE_W, ai_paddle.y + PADDLE_H, PADDLE_COLOR)
end drawai
proc drawgui
    %hahahahaha
end drawgui

%divide by zero lol
if (DUMB_AMOUNT < 1 or DUMB_AMOUNT > 10) then
    put "DUMB_AMOUNT = ", DUMB_AMOUNT, "\nWHY WOULD YOU DO THIS D: