Pong AI trouble

saxplayer13
Unregistered
 
Post: #1
ok, so I'm working on a pong game. Who hasn't? Grin
I have everything under control. except this:
It has no scoring as of yet, but I'm still working on the enemy ai, which is ridiculously easy to fool. It merely tries to stay on track with the ball, setting enemytarget to ballx every frame. I have tried to work on better ai, using linear algebra... but for some reason, it doesn't like me Annoyed.
I made it into a function because I will have to call it everytime the ball bounces off something...
Code:
- (void) positionEnemy {
    float m,yint;
    m = dy/dx; //get slope this works!
    yint = lastcollidey - (m*lastcollidex); //y = mx + b >> b = y - mx but it doesn't work
    NSLog(@"slope = %f yintercept = %f",m); //this proves yint comes out wrong
    epaddlex = ([self frame].size.height - 20 - paddleheight) - yint; //x = (y-b)/m but the /m is in the next line
    enemytarget=epaddlex/m;
    [self setNeedsDisplay:YES]; //just update...
}
sorry the code view is a little hard to read. If you download the source, I have commented this out, and it works fine
Quote this message in a reply
Sage
Posts: 1,066
Joined: 2004.07
Post: #2
I can't quite figure out what all the variables are otherwise I'd try to help. Also downloaded the source but it uses CoreData (10.4 only, I believe) so I can't do much to help there either (I'm on 10.3.9).

One thing that will help others help you and make you a stronger coder, in my opinion, is to make the variables easier to understand with their names and also use some capitals to clear it up a bit. For example lastcollidey could become lastCollisionYLocation (if that's what it means, I'm not sure). And names like yint should become newYLocation (if that's what it means, again, I can't tell from the source code). Little things like that can go a long way to helping others understand your code, and also help you understand your code if you come back to it a long time after working on it. Of course you can ignore this and do it your way. Just a suggestion.

Sorry I couldn't help your actual problem though. Smile. I wanted to helpful. Good luck with the pong game. Hopefully turns out better than mine Smile.
Quote this message in a reply
Moderator
Posts: 133
Joined: 2008.05
Post: #3
@saxplayer: Great job so far. Your variable names are fine. As of right now, you only call positonEnemy when you hit the ball with your paddle, so anytime it bounces off the wall, the enemy screws up. Maybe that's where your problem is. You should also try increasing the speed of the ball, especially after it has been bouncing for awhile. That way, if you do fool the computer, it doesn't look like a programming mistake, it looks like you actually won. Smile

@Nick: The CoreData framework is being added to the project, but it's not using it, you can remove it. I understood every single variable name he used. If you can't read, that isn't his fault, so don't go filling his mind with nonsense. If you can't tell what lastcollidey means, which you obviously can, since you offered an alternative, or what yint(y intercept) when it's next to a variable m(slope), you shouldn't be giving advice on the subject.
Quote this message in a reply
Moderator
Posts: 1,562
Joined: 2003.10
Post: #4
LongJumper Wrote:I understood every single variable name he used. If you can't read, that isn't his fault, so don't go filling his mind with nonsense.

That was quite uncalled for. It's not nonsense at all. While it may be possible to figure out what the variables are, if they're named appropriately, you shouldn't even have to think about it; you'll know immediately after reading the name. m, yint, dx, and dy are particularly bad, and as Nick said, the others could do with some capitalization. If you want to argue that there's no reason to change the variable names, that's fine; please just do it in a more polite manner in the future.
Quote this message in a reply
Moderator
Posts: 133
Joined: 2008.05
Post: #5
I don't find it uncalled for at all. These kind of posts are annoying to sift through - "Hey, I don't know how to answer that, but I will teach you some pointless lesson in an elitist way." That's all it sounded like to me.

I don't find m, yint, dx, dy to be bad at all. They are standard mathematical notation in a short method that is computing a standard mathematical function. In fact, anything more than m, yint, dx, and dy would be overkill. What would you prefer him to write in exchange? changeInTheVariableX? Some things just aren't worth wasting time on.

And finally, there is polite, then there is brutally honest in order to be polite. Sometimes, you just don't get things done trying to be nice, which has now been proven by the fact that over 5 months ago I had a post stickied in the Assembly Room that was directly in response to his posts during that time period, and yet he's still posting things that don't relate to the topic. If you want to give a tip to someone that doesn't relate to the thread, you can PM, e-mail, IM, whatever. Don't fill the board up with pat-your-own-back nonsense.
Quote this message in a reply
saxplayer13
Unregistered
 
Post: #6
yeah, sorry. I forgot to mention that I've been developing on 10.4... when I actually release it (if I ever get that far), I'll probably read up on those cross dev. sdk's, and failing that, just use my 10.3.

Sorry my source code is all jumbled. I'm not a very organized programmer, and I agree my variable names probably could use some improvement, now that you've pointed it out. I usually don't think about others reading my source code. Besides, in the Cocoa Animation tutorial i read before this, they used dx and dy Grin.

Calling that function isn't screwing up the thing yet, because i commented out calling it in the only place it is written... I know the problem is in finding the y intercept, because it never comes through the NSLog correctly, but I'm not sure why.

I'm going to have to update my collision detection if I speed it up too much, because the paddles are only 10 pixels thick, and going too fast could screw up my detection ( i did do a test where speed increased endlessly, then i realized i needed a max speed.

Sorry for the confusion: lastcollidex,lastcollidey is the point at which the ball hit the paddle, I could probably have used an NSPoint instead, but coming from a flash/applescript background, it doesn't strike me as the easiest thing to do. They are ints, and everything else is a float, but that shouldn't make a difference, I don't think.

Most likely, this will probably just be an algebra error I made.
Quote this message in a reply
Moderator
Posts: 771
Joined: 2003.04
Post: #7
Try this:

In timerFunction you have:
Code:
- (void) timerFunction {
    int enemyTarget;
    //enemy ai
    if (dy < 0) {
        //no threat, move to middle
        enemyTarget = [self frame].size.width/2;
    } else {
        enemyTarget = ballX+dx;
    }
...

Replace it with:
Code:
- (void) timerFunction {
    int enemyTarget;
    //enemy ai
    if (dy < 0) {
        //no threat, move to middle
        enemyTarget = [self frame].size.width/2;
    } else {
        //enemyTarget = ballX+dx;
        int predictedBallX = ballX+dx*(([self frame].size.height-ballY-40) / dy);
        if (predictedBallX < 0)
            predictedBallX = -predictedBallX;
        if ((predictedBallX / (int)[self frame].size.width) % 2)
            enemyTarget = [self frame].size.width - (predictedBallX % (int)[self frame].size.width);
        else
            enemyTarget = (predictedBallX % (int)[self frame].size.width);
    }
...

Here is an updated version I made of your project: http://www.jignacio.com.ar/cosas/BounceEdited.zip

Basically, the computer calculates where the ball is going to be, and sets that as the target position for your paddle.

Note: I think your variable names are fine, although it would look a bit better usingInterCaps. Also, check the updated source in the zip file, I made a few smallish changes to simplify your code a bit, (try FileMerge to compare the files)
Quote this message in a reply
saxplayer13
Unregistered
 
Post: #8
Excellent! The AI works well!!!

.....maybe too well, as I haven't beat it yet. Oh, well, I can just use some random numbers to make the AI confused.

Thanks for helping with my semi-cluttered source.
I didn't know you could leave out the {} on the one-line if statements, though I probably will not make much use of it, seeing as old habits die hard. Hooray for learning experiences. Your way of doing the ai was simpler than finding the line... I was probably just leaning toward algebra because we were reviewing linear algebra in school while I was working on the algorithm.

Thanks PowerMacX, you saved me a lot of time Grin
Quote this message in a reply
Member
Posts: 196
Joined: 2003.10
Post: #9
An alternate AI approach is to have the AI's paddle move constantly towards the ball's y value (vertically). Set the maximum speed of the paddle less than that of the ball and the AI loses sometimes.

Perhaps good for an AI intelligence preference toggle.
Quote this message in a reply
saxplayer13
Unregistered
 
Post: #10
I hadn't thought of making the paddle closer or farther away. It would definitely make the ai fallible.
Later, I plan on adding in some powerups, where you freeze the enemy paddle, and can basically just score as much as you want until you hit them or the counter melts the ice.
Once I make powerups that will screw up the enemy AI, I can make this one expert mode, the following the ball easy mode, and using this ai - wallbouncing as medium mode.
Today I will work on making the ball speed up on every hit, and finding a max speed where my collision detection still works.
Quote this message in a reply
Member
Posts: 196
Joined: 2003.10
Post: #11
Quote:finding a max speed where my collision detection still works.

... Of course, a good collision detection algorithm backchecks so this is never a possible scenario Wink

I'm one to talk. Never successfully implemented that one.
Quote this message in a reply
Moderator
Posts: 529
Joined: 2003.03
Post: #12
ThemsAllTook Wrote:m, yint, dx, and dy are particularly bad...

Well, dx and dy are very familiar to anyone who's taken Calculus.

"Yes, well, that's the sort of blinkered, Philistine pig-ignorance I've come to expect from you non-creative garbage."
Quote this message in a reply
zKing
Unregistered
 
Post: #13
In the "Can't we all just get along" middle road category:

I believe it was Stroustrup in "The C++ Programming Language" that recommended variable name lengths should be proportional to the variable's scope.

That is: If you have a public static member that can be seen all over your code, it's probably a good idea to have a fully spelled out camel case name for it. A local that lives for only three lines inside an "if" block could be pretty short.

In addition "well known" short hand is ok, such as "i, j, k" for indexes on nested for loops, "x, y, z, dx, dx, dz" for coordinates and diffs in those coordinates, etc.

Not to start another flame war but: he also recommended limiting comments within functions (only for really confusing spots), but instead putting a really good comment block on top of each function. His reasoning was that most comments within the code end up just repeating the code therefore providing little value, they end up getting stale fast and they clutter the code for the person trying to read it (obviously coming from someone who probably doesn't use a color syntax editor very much). The blocks at the top of a method tend to document at a design level and therefore be more useful and resistant to change.
Quote this message in a reply
Member
Posts: 749
Joined: 2003.01
Post: #14
>variable name lengths should be proportional to the variable's scope

I agree, that's about the guideline i use.

Last time I coded pong I made the AI calculate the "target point" and then put a random noise mistake that got proportionally bigger with the ball's speed.

©h€ck øut µy stuƒƒ åt ragdollsoft.com
New game in development Rubber Ninjas - Mac Games Downloads
Quote this message in a reply
Moderator
Posts: 771
Joined: 2003.04
Post: #15
Adding some random noise to the predicted "target point" (the enemyTarget var) is a good idea, just take into account that:
1) Right now, the predicted position is recalculated at every frame, so adding a random value would make the paddle move erratically, and it wouldn't look natural.
2) The function you mentioned in the first post (- (void) positionEnemy), that you call once every collision is a good place to move the code that calculates the target point.
3) You could call that function just once, when the ball bounces off the player's paddle, and add the random error there, but that's not how humans play: calling the function every time it bounces, either on the player's paddle or in one of the walls would look more natural
4) The random error should be bigger the longer the predicted ball trajectory would be, so that a ball going vertically will always be easy to catch, but one with a more horizontal movement would be harder
5) Once the ball is close enough, the computer should try to correct whatever error it made, at the last second, otherwise it would look too dumb Wink
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  [Request] Pong Source &amp; One Question McSpider 6 7,565 Sep 18, 2011 07:21 AM
Last Post: fudog
  My first Cocoa Game that works! (Pong) blobbo 16 10,115 Aug 4, 2005 03:15 PM
Last Post: Andrew
  Pong "Physics" Nick 9 6,239 Sep 28, 2004 07:36 PM
Last Post: aarku
  Pong Questions: blobbo 8 4,292 Jan 21, 2004 08:16 PM
Last Post: blobbo
  Tic Tac Toe almost done... Next up: Pong! blobbo 15 7,793 Jan 16, 2004 06:33 PM
Last Post: blobbo