AI Tutorial
Adjusting Aim To Avoid Obstacles

 

      That's a pretty long title for a tutorial! Daft though the name may sound, this tutorial contains my greatest ever routine. Yes, I am showing you the greatest secret of the ELFBOt!
      Like all good tutorials, it centers around one simple routine. The basic premise is this: "If the bot can see his opponent, but shooting at it directly will hit the lip of a ledge or an obstacle in the way, then work out a direction it can fire in that will hit the target.". Several bots have done this, including the reaper bots, but their code to do it was severely limiting, in that it simply shoots a little higher on the enemy if a straight shot would miss. This is not very profesional, which is why I love this routine. It is only a few lines long, yet it is the best bot aiming routine ever written!
      Without further ado, let's make our bots aim better than the reapers. Open up tutor.qc and scroll down to bot_aim_at_enemy, where most of my tutorials seem to take place. It probably looks nothing like this:


// -------------------------------------
vector() bot_aim_at_enemy =
// -------------------------------------
{

	return normalize(self.enemy.origin - self.origin);

};

      That is our current aiming routine, so lets replace it with this:

// -------------------------------------
vector() bot_aim_at_enemy =
// -------------------------------------
{
	traceline (self.origin, self.enemy.origin, FALSE, self);

	if ((trace_fraction != 1) || (trace_ent != self.enemy))
		return bot_calculate_aim();

	return normalize(self.enemy.origin - self.origin);
};

       What this basically does is this. It draws a traceline directly from the bot's origin to the enemy's, and if it hits a wall or another entity, then it returns a vector given by bot_calculate_aim. Otherwise, it returns the usual vector for bot aiming. If you have already done my target leading or any other alteration to bot_aim_at_enemy, then put the code above, with the exception of the last line before any of the code you currently have in the routine.
      I'm sure you're all wondering about my marvellous routine, so here it is! Put this before bot_aim_at_enemy:

vector () bot_calculate_aim =
{
local float num_tries;
local vector end;

	num_tries = 25;

	while (num_tries)
		{
		end = self.enemy.origin;
		end_x = end_x + crandom() * 20;
		end_y = end_y + crandom() * 20;
		end_z = end_z + crandom() * 20;
		traceline (self.origin, end, TRUE, self);
		if ((trace_fraction == 1) && (trace_ent == self.enemy))
			return end - self.origin;
		num_tries = num_tries - 1;
		}

	return self.enemy.origin - self.origin;
};

      That's truly is it! It's pretty clear how it works, but just in case, here's an explanation in English. "Draw a traceline from the bot's origin, with it's end at a random position in the area of the target. If it hits the target, and not a wall or another entity, then return this trajectory to shoot along. Otherwise ,repeat the process until either a trajectory is found that hits or it has tried 25 times, in which case it decides it can't hit the target properly, and just shoots directly at the target instead."
      I really love that routine, so please credit me if you use it.
      That's the end of yet another tutorial. Now go out an tell your friends that your bot aims better than the Reaper Bot.  


What We Learned

1. Never assume that the Reaper bot does things the best possible way.
2. Only bad bots can't aim.
3. Recursively repeating code is sometimes a good idea.


Author: SkinSki
Questions: skinski@storm-1.freeserve.co.uk
AI chat on ICQ: 30578982