Missile intercept code

An area for discussing new ideas and additions to Oolite.

Moderators: winston, another_commander

User avatar
Cmdr James
Commodore
Commodore
Posts: 1357
Joined: Tue Jun 05, 2007 10:43 pm
Location: Berlin

Missile intercept code

Post by Cmdr James »

Guys, I have made a small modification to the code used for the missile interception logic. It is now, normally much more likely to strike a target, as it will predict the target location based upon its current velocity. I guess it might be better to add some damping due to the imperfect ability to read a target velocity?

Anyway the code is here if anyone wants to comment.

Code: Select all

- (double) missileTrackPrimaryTarget:(double) delta_t
{
	Vector  relPos;
	GLfloat  d_forward, d_up, d_right, range2;
	Entity  *target = [self primaryTarget];

	if (!target)   // leave now!
		return 0.0;

	Vector leading = [target velocity];

	double  damping = 0.5 * delta_t;
	double  rate2 = 4.0 * delta_t;
	double  rate1 = 2.0 * delta_t;

	double stick_roll = 0.0;	//desired roll and pitch
	double stick_pitch = 0.0;

	relPos = vector_subtract(target->position, position);
	
	//how long till I get there
	float lead = sqrt(magnitude2(relPos)) / [self speed];
	
	//adjust where we are going to take into account his velocity
	relPos.x += (lead * leading.x); 
	relPos.y += (lead * leading.y); 
	relPos.z += (lead * leading.z);

	range2 = magnitude2(relPos);

	if (!vector_equal(relPos, kZeroVector))  relPos = vector_normal(relPos);
	else  relPos.z = 1.0;

	d_right		=   dot_product(relPos, v_right);		// = cosine of angle between angle to target and v_right
	d_up		=   dot_product(relPos, v_up);		// = cosine of angle between angle to target and v_up
	d_forward   =   dot_product(relPos, v_forward);	// = cosine of angle between angle to target and v_forward

	// begin rule-of-thumb manoeuvres

	stick_roll = 0.0;

	if (pitching_over)
		pitching_over = (stick_pitch != 0.0);

	if ((d_forward < -pitch_tolerance) && (!pitching_over))
	{
		pitching_over = YES;
		if (d_up >= 0)
			stick_pitch = -max_flight_pitch;
		if (d_up < 0)
			stick_pitch = max_flight_pitch;
	}

	if (pitching_over)
	{
		pitching_over = (d_forward < 0.5);
	}
	else
	{
		stick_pitch = -max_flight_pitch * d_up;
		stick_roll = -max_flight_roll * d_right;
	}

	// end rule-of-thumb manoeuvres

	// apply damping
	if (flightRoll < 0)
		flightRoll += (flightRoll < -damping) ? damping : -flightRoll;
	if (flightRoll > 0)
		flightRoll -= (flightRoll > damping) ? damping : flightRoll;
	if (flightPitch < 0)
		flightPitch += (flightPitch < -damping) ? damping : -flightPitch;
	if (flightPitch > 0)
		flightPitch -= (flightPitch > damping) ? damping : flightPitch;

	// apply stick movement limits
	if (flightRoll + rate1 < stick_roll)
		stick_roll = flightRoll + rate1;
	if (flightRoll - rate1 > stick_roll)
		stick_roll = flightRoll - rate1;
	if (flightPitch + rate2 < stick_pitch)
		stick_pitch = flightPitch + rate2;
	if (flightPitch - rate2 > stick_pitch)
		stick_pitch = flightPitch - rate2;

	// apply stick to attitude
	flightRoll = stick_roll;
	flightPitch = stick_pitch;

	//
	//  return target confidence 0.0 .. 1.0
	//
	if (d_forward < 0.0)
		return 0.0;
	return d_forward;
}

User avatar
TGHC
---- E L I T E ----
---- E L I T E ----
Posts: 2157
Joined: Mon Jan 31, 2005 4:16 pm
Location: Berkshire, UK

Post by TGHC »

That looks like a nifty bit of work, I'd better go service and polish my ECM
The Grey Haired Commander has spoken!
OK so I'm a PC user - "you know whats scary? Out of billions of sperm I was the fastest"
User avatar
Cmdr James
Commodore
Commodore
Posts: 1357
Joined: Tue Jun 05, 2007 10:43 pm
Location: Berlin

Post by Cmdr James »

I only added about 4 lines, I cant take credit for most of this :)
another_commander
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 6667
Joined: Wed Feb 28, 2007 7:54 am

Post by another_commander »

Does the added missile code affect game balance? Make sure that you have not created some kind of unbeatable superweapon. I will give it a test at first opportunity, probably during the weekend.
User avatar
Cmdr James
Commodore
Commodore
Posts: 1357
Joined: Tue Jun 05, 2007 10:43 pm
Location: Berlin

Post by Cmdr James »

I have never seen evading missiles by cool flying as really viable. Except for photon torpedos which I often seem to end up having circle me as they cannot hit. You can of course inject fuel to get away, and this is uneffected.

This does not improve speed, or effect ecm interaction so I dont think there should be much effect on balance.

The main thing which concerns me is that for very fast moving targets (especially faster than the missile) you can get a weird looking missile flight path as it tries to converge.

This code is currently only on this forum (and my machine), I have not put it into trunk, (I do not have privileges to do that) and I am not sure it should go in.
User avatar
JensAyton
Grand Admiral Emeritus
Grand Admiral Emeritus
Posts: 6657
Joined: Sat Apr 02, 2005 2:43 pm
Location: Sweden
Contact:

Post by JensAyton »

This is something I’ve wanted to do for a while. I’ll definitely check it out… at some point. :-)

Evading missiles is definitely viable in the current game, but rather a bother. Injectors are a better option.
another_commander
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 6667
Joined: Wed Feb 28, 2007 7:54 am

Post by another_commander »

I tried the modification and I must say I like it very much. Missiles definitely fly more aggressively now and I like how it looks like they are thrown off-course during the first moments of flight and then just start hunting down the target mercilessly. My one and only concern is that, with this modification, any player without ECM or injectors who has such a missile launched against him, is definitely toast.

But there is a bug in the code in its current form. When I tested it, I noticed that I was getting very frequent freezes whenever there were missiles in the air. Entering some alert debug messages that were printed whenever the missile speed dropped below a value of 2.5 revealed this at the moment of crash (last three lines of stderr.txt):

Code: Select all

2007-12-28 18:39:36.141 oolite.exe[6788] [jstest.witchSpace.begin]: Player is entering witchspace. Cause: standard jump
2007-12-28 18:39:38.565 oolite.exe[6788] [jstest.witchSpace.arrive]: Player is exiting witchspace.
2007-12-28 18:39:38.685 oolite.exe[6788] [script.javaScript.context.create]: Creating JS context.
2007-12-28 18:39:41.268 oolite.exe[6788] [jstest.witchSpace.complete]: Player exited witchspace into galaxy 6, planet 160 ("Xeleza"), govt = 2 (Multi-Government), economy = 7 (Poor Agricultural), tech level = 4
2007-12-28 18:39:41.349 oolite.exe[6788] [jstest.alert]: Player alert condition changed to green (clear)
2007-12-28 18:39:51.283 oolite.exe[6788] [jstest.alert]: Player alert condition changed to yellow (mass locked)
2007-12-28 18:40:02.529 oolite.exe[6788] [jstest.alert]: Player alert condition changed to red (mass locked)
2007-12-28 18:40:27.655 oolite.exe[6788] [unclassified.ShipEntity]: [self speed] = 2.499960,   1 / [self speed] = 0.400006
2007-12-28 18:40:27.675 oolite.exe[6788] [unclassified.ShipEntity]: [self speed] = 0.000000,   1 / [self speed] = 1.#INF00
2007-12-28 18:40:27.685 oolite.exe[6788] [unclassified.ShipEntity]: [self speed] = 0.000000,   1 / [self speed] = 1.#INF00
Missile speed can and does become zero sometimes. This leads to a division by zero error on the line that reads

Code: Select all

float lead = sqrt(magnitude2(relPos)) / [self speed]; 
One solution for this would be to introduce a low enough threshold (I believe 0.01 does the job fine), below which there will be no attempt to adjust course for the target's velocity. Readjustment will take place only when speed goes above 0.01 again. So, I would modify a bit the code to something like this:

Code: Select all

 //how long till I get there 
   float missileSpeed = (float)[self speed];
   if (missileSpeed > 0.01)		// Avoid getting ourselves in a divide by zero situation.
   {
   	Vector leading = [target velocity]; 
   	float lead = magnitude(relPos) / missileSpeed; 
    
   	//adjust where we are going to take into account his velocity 
   	relPos.x += (lead * leading.x); 
   	relPos.y += (lead * leading.y); 
   	relPos.z += (lead * leading.z); 
   }
I would also think it could be a good idea to have something like an aggressiveness random factor ranging from 0.0 to 1.0, that can be used to multiply the (lead * leading.[xyz]) value. This way we could incorporate this behavior to the game, at the same time giving a chance to new players to survive missile attacks. In the best case scenario the missile would behave like it does now (agressiveness = 0.0) and in the worst case scenario it would behave like Cmdr James' missiles (aggressiveness = 1.0). In most cases, it would just behave somewhat better than it currently does.
User avatar
Cmdr James
Commodore
Commodore
Posts: 1357
Joined: Tue Jun 05, 2007 10:43 pm
Location: Berlin

Post by Cmdr James »

This all makes sense to me.

I would personally like to see missiles less manouverable, and shorter max range, making them more like a missile and less like a suicide pilot in a fast ship. But I think this is moving too far from the tradition of elite. In the original (Amstrad CPC disk version at least) elite, as far as I remember missiles were rubbish and flew around almost forever rarely hitting anything.
Last edited by Cmdr James on Sat Dec 29, 2007 11:42 am, edited 1 time in total.
User avatar
Cmdr James
Commodore
Commodore
Posts: 1357
Joined: Tue Jun 05, 2007 10:43 pm
Location: Berlin

Post by Cmdr James »

I also think missiles should not stop if the target disappears, either :
a) explode
b) continue in the direction they were going

My old commander (Giles bless his soul) got quite a few kills shooting dead torpedos that were just hanging around in space. It always seemed a bit cheap that I get one kill for hours of cat and mouse with a rattlecutter and the same for a dead missile floating about. Now a live missile is a different matter ;)
User avatar
jonnycuba
Deadly
Deadly
Posts: 233
Joined: Fri May 21, 2004 1:04 pm
Location: Witchspace

Post by jonnycuba »

would this work as a missile upgrade oxp? i.e you purchase a missile with this improved tech (like hard hats). So only a commander skilled enough would want to install it?
Team Zorg are Go!
User avatar
Cmdr. Maegil
Sword-toting nut-job
Sword-toting nut-job
Posts: 1294
Joined: Tue Feb 27, 2007 10:28 pm
Location: On the mend in Western Africa

Post by Cmdr. Maegil »

Since we've been on a randomizing mood...

...I'd like the "Faulcon de Lacy HM3" as the average missile , unmodified , with its agressiveness representing 0.5 and available at most systems, but have other options of HMs according to the system's tech level. (on HMs, I mean - there is the more exotical equipment from Ramirez' Missiles & Bombs OXP).
E.g.: a "Taranis EX5 MRSSM" missile with a state-of-the-art guidance system and high explosive yield would be available on the highest tech level systems, or crazy stuff such as a Benulobiweed Tailchaser 2.5 Guided Missile" with a maximum speed of 2.5LM and high agressiveness but a pitch of only 1.5; the midranges should be variations on the basic HM3; and in crummy anarchies it shouldn't be possible to find but worthless crap (except, perhaps, on some seedy black markets - but then again, you should be able to find anything there).

Anyone up to it? :wink:
You know those who, having been mugged and stabbed, fired, dog run over, house burned down, wife eloped with best friend, daughters becoming prostitutes and their countries invaded - still say that "all is well"?
I'm obviously not one of them.
User avatar
Eric Walch
Slightly Grand Rear Admiral
Slightly Grand Rear Admiral
Posts: 5536
Joined: Sat Jun 16, 2007 3:48 pm
Location: Netherlands

Post by Eric Walch »

Another_Commander wrote:
I would also think it could be a good idea to have something like an aggressiveness random factor ranging from 0.0 to 1.0, that can be used to multiply the (lead * leading.[xyz]) value. This way we could incorporate this behavior to the game, at the same time giving a chance to new players to survive missile attacks.
I agree there should be a random factor to give the player a change with some of the missiles. But why not use the existing key: accuracy.

At the moment it must have a value between -5 and 10. (when not it is selecting its own randomised value.
This "accuracy" is used to change "pitch_tolerance". But you could also use the same "accuracy" entry to randomise an other parameter. (better than having two entries for something similar.
User avatar
JensAyton
Grand Admiral Emeritus
Grand Admiral Emeritus
Posts: 6657
Joined: Sat Apr 02, 2005 2:43 pm
Location: Sweden
Contact:

Post by JensAyton »

Cmdr James wrote:
I also think missiles should not stop if the target disappears, either :
a) explode
b) continue in the direction they were going
...
It always seemed a bit cheap that I get one kill for hours of cat and mouse with a rattlecutter and the same for a dead missile floating about. Now a live missile is a different matter ;)
The built-in missiles do explode when they lose their target. This behaviour is defined by the AI, so third parties can do what they wish.
another_commander
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 6667
Joined: Wed Feb 28, 2007 7:54 am

Post by another_commander »

Eric Walch wrote:
I agree there should be a random factor to give the player a change with some of the missiles. But why not use the existing key: accuracy.

At the moment it must have a value between -5 and 10. (when not it is selecting its own randomised value.
This "accuracy" is used to change "pitch_tolerance". But you could also use the same "accuracy" entry to randomise an other parameter. (better than having two entries for something similar.
Yes, it looks like using accuracy is the way to go. I had initially thought about using it, then discarded the thought when I saw that it was used to calculate pitch_tolerance. What I did not realize at the time, was that, in the case of a missile, once it is used to calculate pitch tolerance, it doesn't get used again for anything, so it is essentially a variable hanging free. Plus accuracy is probably a better name than aggressiveness for what we are trying to describe.
User avatar
Cmdr. Maegil
Sword-toting nut-job
Sword-toting nut-job
Posts: 1294
Joined: Tue Feb 27, 2007 10:28 pm
Location: On the mend in Western Africa

Post by Cmdr. Maegil »

Well, let' have an OXP, then!
Can someone test this? Due to power supply problems, I can't run Oolite (nor any heavyish applications) on the laptop...

shipdata.plist

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
   <dict>
	<key>Home made Missile</key>
	<dict>
      	<key>like_ship</key>
	      <string>missile</string>
		<key>ai_type</key>
		<string>missileAI.plist</string>
		<key>max_flight_pitch</key>
		<real>6</real>
		<key>max_flight_roll</key>
		<real>6</real>
		<key>max_flight_speed</key>
		<real>700</real>
		<key>accuracy</key>
		<integer>0</integer>
		<key>name</key>
		<string>Crude missile</string>
		<key>roles</key>
		<string>missile EQ_HOMEMADE_MISSILE</string>
		<key>thrust</key>
		<real>200</real>
		<key>weapon_energy</key>
		<real>3500</real>
	</dict>

	<key>FdL HM3</key>
	<dict>
      	<key>like_ship</key>
	      <string>missile</string>
		<key>accuracy</key>
		<integer>5</integer>
		<key>name</key>
		<string>HM3 missile</string>
	</dict>

	<key>Vega Tracker RHM</key>
	<dict>
      	<key>like_ship</key>
	      <string>missile</string>
		<key>ai_type</key>
		<string>missileAI.plist</string>
		<key>max_flight_pitch</key>
		<real>6</real>
		<key>max_flight_speed</key>
		<real>850</real>
		<key>accuracy</key>
		<integer>7</integer>
		<key>name</key>
		<string>Tracker missile</string>
		<key>roles</key>
		<string>missile EQ_TRACKER_MISSILE</string>
		<key>scanClass</key>
		<string>CLASS_MISSILE</string>
		<key>thrust</key>
		<real>300</real>
		<key>weapon_energy</key>
		<real>5500</real>
	</dict>




      <key>Vega Bloodhound XHM</key>
      <dict>
         	<key>like_ship</key>
         	<string>ecm-proof-missile</string>
		<key>ai_type</key>
		<string>hardMissileAI.plist</string>
		<key>max_flight_pitch</key>
		<real>6</real>
		<key>accuracy</key>
		<integer>4</integer>
		<key>name</key>
		<string>Bloodhound hardened missile</string>
		<key>roles</key>
		<string>missile EQ_BLOODHOUND_MISSILE</string>
	</dict>




      <key>FdL HMX5</key>
      <dict>
         	<key>like_ship</key>
         	<string>ecm-proof-missile</string>
		<key>accuracy</key>
		<integer>6</integer>
		<key>name</key>
		<string>FdL HMX5 hardened missile</string>
	</dict>




      <key>Benulobiweed Tailchaser Hardhat</key>
      <dict>
         	<key>like_ship</key>
         	<string>ecm-proof-missile</string>
		<key>ai_type</key>
		<string>hardMissileAI.plist</string>
		<key>max_energy</key>
		<real>5</real>
		<key>max_flight_pitch</key>
		<real>3</real>
		<key>max_flight_roll</key>
		<real>6</real>
		<key>max_flight_speed</key>
		<real>1500</real>
		<key>accuracy</key>
		<integer>5</integer>
		<key>name</key>
		<string>Tailchaser hardened missile</string>
		<key>roles</key>
		<string>missile EQ_TAILCHASER_MISSILE</string>
		<key>scanClass</key>
		<string>CLASS_MISSILE</string>
		<key>thrust</key>
		<real>500</real>
		<key>weapon_energy</key>
		<real>4000</real>
	</dict>




      <key>Taranis ECMR2 MRHSSM</key>
      <dict>
         	<key>like_ship</key>
         	<string>ecm-proof-missile</string>
		<key>ai_type</key>
		<string>hardMissileAI.plist</string>
		<key>max_flight_pitch</key>
		<real>10</real>
		<key>max_flight_roll</key>
		<real>12</real>
		<key>accuracy</key>
		<integer>8</integer>
		<key>name</key>
		<string>ECMR2 hardened missile</string>
		<key>roles</key>
		<string>missile EQ_ECMR2_MISSILE</string>
	</dict>

   </dict>
</plist>
equipment.plist

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
   <array>
      <array>
         <integer>0</integer>
         <integer>100</integer>
         <string>Home made Missile</string>
         <string>EQ_HOMEMADE_MISSILE</string>
         <string>Made in some backyard sweatshop, this crude but effective homing missile has the most basic guidance system.</string>
         <dict>
            <key>available_to_all</key>
            <true/>
         </dict>
      </array>


	<array>
		<integer>2</integer>
		<integer>300</integer>
		<string>FdL HM3</string>
		<string>EQ_MISSILE</string>
		<string>Faulcon de Lacy HM3 homing missile, fast and accurate when used in conjunction with standard targetting scanners.</string>
		<dict>
			<key>available_to_all</key>
			<true/>
		</dict>
	</array>



	<array>
		<integer>4</integer>
		<integer>500</integer>
		<string>Vega Tracker RHM</string>
		<string>EQ_TRACKER_MISSILE</string>
		<string>Vega Corp's homing missile, fast and powerful. Targetting scanners recommended.</string>
		<dict>
			<key>available_to_all</key>
			<true/>
		</dict>
	</array>



	<array><!-- ecm hardened missile -->
		<integer>8</integer>
		<integer>3000</integer>
		<string>Vega Bloodhound XHM</string>
		<string>EQ_BLOODHOUND_MISSILE</string>
		<string>Vega Corp's ECM-hardened missile. Targetting scanners recommended.</string>
		<dict>
			<key>available_to_all</key>
			<true/>
		</dict>
	</array>


	<array><!-- ecm hardened missile -->
		<integer>9</integer>
		<integer>3500</integer>
		<string>FdL HMX5</string>
		<string>EQ_HARDENED_MISSILE</string>
		<string>Faulcon de Lacy HMX5 homing missile - hardened against ECM.</string>
		<dict>
			<key>available_to_all</key>
			<true/>
		</dict>
	</array>


	<array><!-- ecm hardened missile -->
		<integer>11</integer>
		<integer>5000</integer>
		<string>Benulobiweed Tailchaser Hardhat</string>
		<string>EQ_TAILCHASER_MISSILE</string>
		<string>The first practicable result of Benulobiweed, inc.'s foray into weaponmaking is in this faaaasst ECM-hardened interceptor missile.</string>
		<dict>
			<key>available_to_all</key>
			<true/>
		</dict>
	</array>


	<array><!-- ecm hardened missile -->
		<integer>12</integer>
		<integer>5000</integer>
		<string>Taranis ECMR2 MRHSSM</string>
		<string>EQ_ECMR2_MISSILE</string>
		<string>Taranis corp's Medium Range (ECM-)Hardened Ship-to-Ship Missile, packing a good punch and a state-of-the-art guidance system than the FdL counterpart.</string>
		<dict>
			<key>available_to_all</key>
			<true/>
		</dict>
	</array>
   </array>
</plist>
EDIT: I had 'misspelled' shipdata.plist as shipyard.Plist. Corrected.

Moderator: Follow-ups moved here.
Last edited by Cmdr. Maegil on Mon Dec 31, 2007 8:34 pm, edited 1 time in total.
You know those who, having been mugged and stabbed, fired, dog run over, house burned down, wife eloped with best friend, daughters becoming prostitutes and their countries invaded - still say that "all is well"?
I'm obviously not one of them.
Post Reply