Ch 7 Basic Artificial Intelligence (AI)
11Feb2013

myacm/ Using your Web Account, which you can create once you have student membership
Safari Books Online for ACM - go to My Dashboard
Chapter 7
Ch 7 Random, Evading, Chasing Sprites zip file

Chapter 7. Basic Artificial Intelligence
Section 7.1. The Turing Test
Section 7.2. Creating Sprites at Random Intervals
Section 7.3. Randomly Spawning Sprites Ch7 Game1.cs
Section 7.4. Irrelevant Objects
Ch7 UserControlledSprite.cs
Section 7.5. Creating a Chasing Sprite Ch7 ChasingSprite.cs
Section 7.6. Creating an Evading Sprite Ch7 EvadingSprite.cs
Section 7.7. What You Just Did
Section 7.8. Summary
Section 7.9. Test Your Knowledge: Quiz
Section 7.10. Test Your Knowledge: Exercise

Since the beginning of the computing age, researchers have pondered and debated ways to make machines act more like humans and/or give them some form of artificial intelligence. The biggest problem with the entire line of artificial intelligence science is that there really is no way to define intelligence. What makes somebody or something intelligent? That’s an excellent question, and perhaps one that we will never be able to answer fully. Numerous other questions crop up as well. How do you define typical human behavior? What forms of human behavior constitute intelligence? What forms of human behavior are worthy of replication in machines?

You could argue that the application you have written is “intelligent” because the sprites animate on their own (that is, the user doesn’t have to tell them to continually animate). So, they must be intelligent, right? Others would argue that they are not intelligent, though, because they don’t “do” anything; they just sit there and spin. Even in this example, where it’s clear that the sprites aren’t really intelligent, you can start to see how this area of research is inherently ambiguous.

Section 7.1. The Turing Test

Alan Turing, widely regarded as the father of modern computer science, invented one of the most famous methods for determining whether or not a machine truly is intelligent. Turing called this method the Imitation Game, but universally it is known as the Turing Test.

[stewart, aside] Of course, not everyone believes Turning is our "fatherj". Who Begat Computing? Moshe Y. Vardi, Editor in Chief of Communications of ACM.

Essentially, a Turing Test begins with a human sitting at a keyboard. Using the keyboard, the user interrogates both a computer and another human. The identities of the other subjects are not disclosed to the interrogator. If the interrogator is unable to determine which one is the computer and which one is the human, the computer used in the test is deemed “intelligent.” Although it seems simplistic, programming something that would be able to fool somebody regardless of the line of questioning is extremely difficult.

Section 7.2. Creating Sprites at Random Intervals

Create sprites that move, randomly spawn and force user to "do something".
Create variable at class level in
Ch7 Game1.cs
public Random rnd { get; private set;}
and intialize the Random object in the constructor of the Game1 class
rnd = new Random(  );
When using random number generators, it’s important to make sure that you don’t create multiple random number generators inside a tight loop. This is because if you create multiple random number generators within a close enough time frame, there is a chance that they will be created with the same seed. The seed is what the random number generators use to determine which numbers are generated and in which order. As you can probably guess, having multiple random number generators with the same seed would be a bad thing; you could potentially end up with the same list of numbers being generated by each, and then your randomness would be thrown out the window.

Avoid this by having only one random number generator object in your application and reuse that object for all random numbers. Otherwise, just make sure that you create the random number generators in areas of the application that won’t be executed within a short time frame.

System.Random really isn’t the greatest of random number generation tools, but it will have to do for now.

Add to SpriteManager class some class-level variables that will be used to spawn sprites:

int enemySpawnMinMilliseconds = 1000;
int enemySpawnMaxMilliseconds = 2000;
int enemyMinSpeed = 2;
int enemyMaxSpeed = 6;
represent the minimum number of seconds and the maximum number of seconds to wait to spawn a new enemy, and the minimum and maximum speeds of those enemies

Remove the code to create AutomatedSprites that did not move because now we periodically generating new enemies in LoadContent method of SpriteManager class.

At this point, you’ll want to make the game window a bit larger so you have more room to work with. Add this code at the end of the constructor in your Game1 class:

graphics.PreferredBackBufferHeight = 768;
graphics.PreferredBackBufferWidth = 1024;
Why Use Random Values? So, why have a min/max spawn time, and why use a random number between those times to spawn new enemies?

The answer comes back to artificial intelligence. As humans, we aren’t automatic in our thinking. Adding an element of randomness makes the application feel more like you’re playing against a human. It also adds a level of unpredictability, which in turn makes the game more fun and more challenging.

OK, so here’s another question: why use variables for the min/max seconds between enemy spawns and the min/max speeds of those enemies?

Typically, games don’t have the same level of difficulty throughout. As you play to certain points, the game typically gets harder and harder to beat. Using variables for these values allows you to easily increase the difficulty level. As the player progresses through your game, you’ll make the enemies spawn more rapidly and have them move at faster speeds.

And now, one more question: “This is great, Aaron! Why is this so much fun?” That’s just XNA, my friend. XNA rocks!

Section 7.3. Randomly Spawning Sprites

You want to make your sprites spawn at somewhat random intervals, and you want them to spawn from the top, left, right, and bottom sides of the screen. For now, you’ll just have them traveling in a straight direction across the screen, but they’ll do so at varying speeds.

You need to let your SpriteManager class know when to spawn the next enemy sprite. Create a class-level variable in your SpriteManager class to store a value indicating the next spawn time:

int nextSpawnTime = 0;
Next, you need to initialize the variable to your next spawn time. Create a separate method that will set the next spawn time to some value between the spawn time.

If you said that you’re not deleting your objects, you’re really picking this up and understanding game concepts—great job! If you’re confused by that, let me explain: when an automated sprite hits the user-controlled sprite, the automated sprite is removed from the list of sprites and destroyed. However, when an automated sprite makes it all the way across the screen, it simply disappears; you aren’t doing anything with that object to destroy it and the player can no longer collide with the object to destroy it, either. The result is that these objects will continue forever outside the field of play, and in every frame, you will continue to update and draw each of them—not to mention running pointless collision checks on them. This problem will grow worse and worse until at some point it affects the performance of your game.

Spritemanager.cs
Automated Sprites.cs

Section 7.4. Irrelevant Objects

Currently, you aren’t doing anything about your irrelevant sprites. Your sprites leave the screen and never have any chance to return (you only have logic for the sprites to move forward, not to turn or double back), and therefore at that point they become irrelevant. Once one of your automated sprites leaves the screen, you need to detect that and get rid of it so that you don’t waste precious processor time updating and drawing objects that will never come into play in the game again.

public bool IsOutOfBounds(Rectangle clientRect)
{
    if (position.X < -frameSize.X ||
        position.X > clientRect.Width ||
        position.Y < -frameSize.Y ||
        position.Y > clientRect.Height)
    {
        return true;
    }
    return false;
}

Section 7.5. Creating a Chasing Sprite

Ch7 ChasingSprite.cs

Section 7.6. Creating an Evading Sprite

Ch 7 EvadingSprite

Section 7.7. What You Just Did

You’re now very close to having something worthy of your newly developed XNA prowess. In the next chapter, you’ll fine-tune the game and wrap up your 2D development. In the meantime, let’s reflect on what you just accomplished: • You learned some background to artificial intelligence. • You created a factory for sprites that creates sprites at random intervals. • You learned about irrelevant objects and what to do with them to improve game performance. • You created a chasing sprite that follows a player across the screen. • You created an evading sprite that runs from a player. • You drank from the fount of XNA goodness.

Section 7.8. Summary

• Artificial intelligence means many different things, mainly because the term
“intelligence” itself is ambiguous and difficult to define.
• Alan Turing made great strides in the field of artificial intelligence. Much of his
work is directly relevant to what game developers attempt to accomplish.
• Irrelevant objects are objects that will no longer affect gameplay (e.g., a bullet that’s
shot into the sky and doesn’t hit anything). These objects must be removed and
deleted in order to not negatively impact performance as they accrue.
• To implement a chase algorithm, detect the position of the player in relation to the
chaser’s current position, and then move the chasing object in the direction of the
player.
• Implementing an evasion algorithm is the opposite of the chase algorithm: detect
the position of the player, and move the evading object in the opposite direction.
• “Artificial intelligence is no match for natural stupidity.” —Anonymous