Rebuilding Singleplayer AI

Discuss Artificial Intelligence and Bot programming.
Post Reply
behind_you
Posts: 237
Joined: Sat Feb 05, 2011 6:57 am
Location: Tripoli, Libya

Rebuilding Singleplayer AI

Post by behind_you »

At it's best, Quake's AI is crap. Here's a list of reasons why I think this is:

1- Stupid engine function CheckClient(); only allows for monster vs human battles.
2- Movetogoal and Walkmove cause stupid zigzag motion.
3- They're deaf.
4- They're blind. AI codes attempts to mimick vision by using code like infront() but doesn't take light levels and stuff into account.
5- Only notice one enemy at a time.
6- Can't lose an enemy once he sees you. He magically knows where you are at all times once he spots you.
7- Either sees you completely, or doesn't have a clue where you are. AKA can't get suspicious like in MGS.
8- Can hardly navigate around a corner, let alone a sophisticated map.
9- Doesn't use environment to his advantage (ie crouch behind boxes, hides around corners).
10- Can't walk over edges.
11- He is unaffected by water. If he runs into water, he doesn't drown or float or anything. Heck, you can even still hear him grunt!

I can keep going, but I won't.

So after much thought, I've decided to completely scrap almost all the Quake Singleplayer AI (including spawning monsters and stuff) and rebuild it myself. So far, I got a grunt to spawn, check around for any entity that has a health value, face it, and attack it (or run towards it if it's too far). I also made it be able to find and take items when it needs it. However I was still moving him around Quake style (moving his origin forward little bits at a time).

I gave him MOVETYPE_WALK. I started moving him through velocity, but I think I am doing it wrong. Here's the one line of code I'm using:

Code: Select all

makevectors(self.v_angle);
self.velocity = v_forward * self.walkspeed;
I plan on getting more sophisticated with this, but only after I at least get this to work. I use this and he doesn't move forward at all. He slides backwards, and side to side instead! I know this needs friction, but the problem is I have no clue how to implement it.

When I did this before I used MOVETYPE_WALK, it worked fine:

Code: Select all

self.origin = self.origin + v_forward * self.walkspeed;
But this shuts the door for stuff like slippery floor and a lot more things.

So, anyone did this before? I could really use some help

Thanks!
ArchAngel
Posts: 37
Joined: Fri Jun 03, 2011 7:33 pm

Post by ArchAngel »

Isn't there a problem with using MOVETYPE_WALK on non clients? I seem to remember it causing issues.

The one problem I've seen with improved Quake AI is that monsters quite frequently get activated by nearby events and you end up with a swarm of monsters attacking you off the slipgate pad and then followed by an empty level (assuming you survive)
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Post by Spike »

MOVETYPE_WALK on non-player ents is an extension that, as far as I'm aware, only works in DP and FTE.

A large part of what makes quake monsters fun is the fact that you can dance with them, be it the axe dance with a shambler, or the simple dodging/strafing to avoid grenades/fiends/weirdhellknightmissilethings. Make sure you don't stop the dancing!

1. CheckClient is stupid, yes, but its at least fast enough for a 486 to act as a server. PVS checks where you can may help.
2. movetogoal zigzags, yes, which means those damn knigits dodge my grenades all the time. :)
3. Yup, except when you hit one, they'll hear the pain yells, but not the gunshot.
4. Light levels are an extension which is complicated by shadow volumes and dynamic/realtime lights. Hexen2 actually has the client tell the server the light level where the player is.
5. Which means infighting works a bit better. They do remember their old target though, just don't get 3-way infighting.
6. But generally get stuck in a corner due to 2, and don't chase you properly. :)
7. Needs animations and sounds for there to really be much point in it.
8. Yup, no proper pathing. movetogoal is terrible. :)
9. Quake is a run+gun. Stuff hiding is annoying. Besides, half the monsters are mindless zombies that wouldn't understand cover if it crept up behind them and hit them with a wet fish. Although I can understand not understanding inanimate objects which are able to hit you with wet fish.
10. Alternatively said by cannot plummet off cliffs or lavadive. They're okay with jumping in lava if they're partially onground though.
11. Probably just another optimisation. Although the movetogoal code probably should have cached the result of its traces, although the real issue comes with 100+ monsters all constantly checking to see if they're drowning while idle.

You should probably avoid monsters shooting secret triggers. :)

MOVETYPE_WALK is only half of the player's physics. Specifically its the actual movement part, rather than the velocity parts. It doesn't magically make the monster into a player, and doesn't cause the engine to magically generate a v_angles field either. v_angles is strictly for players, monsters have only an .angles field (note the pitch inversion difference, though I doubt you'll use pitch at all, so its not important, and probably shouldn't be used for forwards movement anyway, unless he's meant to be jumping maybe, but that would be too weird).
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Post by Baker »

@behind_you

I liked reading that list. Well thought out. Monster AI is important.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
frag.machine
Posts: 2126
Joined: Sat Nov 25, 2006 1:49 pm

Post by frag.machine »

@behind_you: you can always use mauvetogoal to fix the weird monster zigzagging:

Code: Select all

void(float howquick) MauveWalk =
{
     self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
     ChangeYaw();

     if (!walkmove(self.angles_y, howquick))
          movetogoal(howquick);
}; 
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
behind_you
Posts: 237
Joined: Sat Feb 05, 2011 6:57 am
Location: Tripoli, Libya

Post by behind_you »

frag.machine wrote:@behind_you: you can always use mauvetogoal to fix the weird monster zigzagging:


void(float howquick) MauveWalk =
{
self.ideal_yaw = vectoyaw(self.goalentity.origin - self.origin);
ChangeYaw();

if (!walkmove(self.angles_y, howquick))
movetogoal(howquick);
};
hmm. doesnt this use the normal movetogoal as a failsafe? I'll try it out.

Baker: i agree that monster ai is important. i'm glad you liked the post.

nd thanks spike for replyin. i agree that it's fun to mess with them, but sometimes it's ridiculous.

i'm trying to create a sort of ai that heavily relies on tracelines that travel alongside the walls. IF it works, i'll probably release it and call it something cheezy like traceAI. but the main thing i want to accomplish is MOVETYPE_WALK velocity bots that do not need to use a single waypoint. i have my work cut out for me.
Spike wrote: MOVETYPE_WALK is only half of the player's physics. Specifically its the actual movement part, rather than the velocity parts. It doesn't magically make the monster into a player, and doesn't cause the engine to magically generate a v_angles field either. v_angles is strictly for players, monsters have only an. angles field (note the pitch inversion difference, though I doubt you'll use pitch at all, so its not important, and probably shouldn't be used for forwards movement anyway, unless he's meant to be jumping maybe, but that would be too weird).
i never knew only players had v_angle. i can give it to them, right? or some other fake angle that they can use to aim their weapon.

I guess that moving them quake style is the best way? i think thats how halflife does it. but if i do this, what's the point of implementing MOVETYPE_WALK on non-players? I might as well be giving them MOVETYPE_NONE.

irritating...
daemonicky
Posts: 185
Joined: Wed Apr 13, 2011 1:34 pm

Post by daemonicky »

Does Quake really needs AI? :-D I mean Carmack said "Story in a game is like a story in a porn movie. It's expected to be there, but it's not that important." and I don't believe his opinion about AI is much higher (id games have dumb AI, I guess because of speed). I believe monsters randomly zigzagging and shooting at You is just what FPS needs. :-D
Spike wrote:Hexen2 actually has the client tell the server the light level where the player is.
Do You know where he gets it from? (I would guess it is precomputed to BSP leaves)
behind_you wrote: 1- Stupid engine function CheckClient(); only allows for monster vs human battles.
2- Movetogoal and Walkmove cause stupid zigzag motion.
3- They're deaf.
4- They're blind. AI codes attempts to mimick vision by using code like infront() but doesn't take light levels and stuff into account.
5- Only notice one enemy at a time.
6- Can't lose an enemy once he sees you. He magically knows where you are at all times once he spots you.
7- Either sees you completely, or doesn't have a clue where you are. AKA can't get suspicious like in MGS.
8- Can hardly navigate around a corner, let alone a sophisticated map.
9- Doesn't use environment to his advantage (ie crouch behind boxes, hides around corners).
10- Can't walk over edges.
11- He is unaffected by water. If he runs into water, he doesn't drown or float or anything. Heck, you can even still hear him grunt!
1- delete it?
2,8,10- either already mentioned mauvetogoal or some steering of agents http://www.red3d.com/cwr/steer/
3- IIRC is a function similar to traceline to get list of entities in a radius; use it to simulate hearing (each dude in radius can then be checked if he is deaf, busy, looking away, in water ...)
5- QC does not support lists and arrays natively
6- timeout since last time he saw enemy to let him go (see Thief and stealth games)
4, 7-
  • few more tracelines (head, body, feet, ...) if You reffered to traceline check
  • suspicion_level = function(which tracelines are visible, how objects are, what is each traceline light level)
9,10,11- make some planner http://bitly.com/lO0NdE?r=bb , STRIPS http://bitly.com/kwasNl?r=bb or grok Half Life AI http://bitly.com/lQDRly?r=bb
11- use TWIG or Buyoancy (the other physics for Quake to make cool physics effects)
Think, touch, movetype, solid, traceline ...
silverjoel
Posts: 52
Joined: Thu Sep 30, 2010 6:46 am

Post by silverjoel »

You might want to check out the tutor bot tutorials.

http://www.quakewiki.net/archives/aicaf ... l/main.htm

There are also two tutorials on this site that deal with the light issues. Both are for bots, but they can be adapted.
behind_you
Posts: 237
Joined: Sat Feb 05, 2011 6:57 am
Location: Tripoli, Libya

Post by behind_you »

Thanks for the link. I know how to solve most of the problems Id's AI has. The thing I am stuck with is stupid velocity.

Ugh. I guess I'm stuck moving him quake-way.
andrewj
Posts: 133
Joined: Mon Aug 30, 2010 3:29 pm
Location: Australia

Post by andrewj »

daemonicky wrote:
Spike wrote:Hexen2 actually has the client tell the server the light level where the player is.
Do You know where he gets it from?
Same way as entity lighting, by sampling the lightmap underneath via R_LightPoint()
behind_you
Posts: 237
Joined: Sat Feb 05, 2011 6:57 am
Location: Tripoli, Libya

Post by behind_you »

Ok, I really need help on this. Can someone explain to me in plain English a technique for making a bot navigate? This is driving me insane. If someone can tell me what I need to do, I can translate that into QC at least.
TheHyperborian
Posts: 10
Joined: Sat Jul 23, 2011 12:35 am

Re: Rebuilding Singleplayer AI

Post by TheHyperborian »

I have been working on alot of those issues in my mods to the engine.

The goal of game AI is to be entertaining. Nobody wants to play against impossible AI with super accuracy and super-human powers that you can't beat. It's not hard to make a bot predict where you are shooting and jump out of the way. It's not hard to make a bot shoot you in the head with super accuracy the moment it sees a single pixel of your head. It's not hard to make a bot always know where you are. Nobody wants to play a game of toture. You just want to make it fun, and for most people fun AI is extremely dumb but just enough to challenge them.
Post Reply