Proper Subversion configuration.
[newkind] / pilot.c
1 /*
2 * Elite - The New Kind.
3 *
4 * Reverse engineered from the BBC disk version of Elite.
5 * Additional material by C.J.Pinder.
6 *
7 * The original Elite code is (C) I.Bell & D.Braben 1984.
8 * This version re-engineered in C by C.J.Pinder 1999-2001.
9 *
10 * email: <christian@newkind.co.uk>
11 *
12 *
13 */
14
15 /*
16 * pilot.c
17 *
18 * The auto-pilot code. Used for docking computers and for
19 * flying other ships to and from the space station.
20 */
21
22 /*
23 * In the original Elite this code was mixed in with the tactics routines.
24 * I have split it out to make it more understandable and easier to maintain.
25 */
26
27
28 #include <math.h>
29 #include <stdlib.h>
30 #include <string.h>
31
32 #include "config.h"
33 #include "gfx.h"
34 #include "elite.h"
35 #include "vector.h"
36 #include "main.h"
37 #include "space.h"
38 #include "sound.h"
39
40
41 /*
42 * Fly to a given point in space.
43 */
44
45 void fly_to_vector (struct univ_object *ship, Vector vec)
46 {
47 Vector nvec;
48 double direction;
49 double dir;
50 int rat;
51 double rat2;
52 double cnt2;
53
54 rat = 3;
55 rat2 = 0.1666;
56 cnt2 = 0.8055;
57
58 nvec = unit_vector(&vec);
59 direction = vector_dot_product (&nvec, &ship->rotmat[2]);
60
61 if (direction < -0.6666)
62 rat2 = 0;
63
64 dir = vector_dot_product (&nvec, &ship->rotmat[1]);
65
66 if (direction < -0.861)
67 {
68 ship->rotx = (dir < 0) ? 7 : -7;
69 ship->rotz = 0;
70 return;
71 }
72
73 ship->rotx = 0;
74
75 if ((fabs(dir) * 2) >= rat2)
76 {
77 ship->rotx = (dir < 0) ? rat : -rat;
78 }
79
80 if (abs(ship->rotz) < 16)
81 {
82 dir = vector_dot_product (&nvec, &ship->rotmat[0]);
83
84 ship->rotz = 0;
85
86 if ((fabs(dir) * 2) >= rat2)
87 {
88 ship->rotz = (dir < 0) ? rat : -rat;
89
90 if (ship->rotx < 0)
91 ship->rotz = -ship->rotz;
92 }
93 }
94
95 if (direction <= -0.167)
96 {
97 ship->acceleration = -1;
98 return;
99 }
100
101 if (direction >= cnt2)
102 {
103 ship->acceleration = 3;
104 return;
105 }
106 }
107
108
109
110 /*
111 * Fly towards the planet.
112 */
113
114 void fly_to_planet (struct univ_object *ship)
115 {
116 Vector vec;
117
118 vec.x = universe[0].location.x - ship->location.x;
119 vec.y = universe[0].location.y - ship->location.y;
120 vec.z = universe[0].location.z - ship->location.z;
121
122 fly_to_vector (ship, vec);
123 }
124
125
126 /*
127 * Fly to a point in front of the station docking bay.
128 * Done prior to the final stage of docking.
129 */
130
131
132 void fly_to_station_front (struct univ_object *ship)
133 {
134 Vector vec;
135
136 vec.x = universe[1].location.x - ship->location.x;
137 vec.y = universe[1].location.y - ship->location.y;
138 vec.z = universe[1].location.z - ship->location.z;
139
140 vec.x += universe[1].rotmat[2].x * 768;
141 vec.y += universe[1].rotmat[2].y * 768;
142 vec.z += universe[1].rotmat[2].z * 768;
143
144 fly_to_vector (ship, vec);
145 }
146
147
148 /*
149 * Fly towards the space station.
150 */
151
152 void fly_to_station (struct univ_object *ship)
153 {
154 Vector vec;
155
156 vec.x = universe[1].location.x - ship->location.x;
157 vec.y = universe[1].location.y - ship->location.y;
158 vec.z = universe[1].location.z - ship->location.z;
159
160 fly_to_vector (ship, vec);
161 }
162
163
164 /*
165 * Final stage of docking.
166 * Fly into the docking bay.
167 */
168
169 void fly_to_docking_bay (struct univ_object *ship)
170 {
171 Vector diff;
172 Vector vec;
173 double dir;
174
175 diff.x = ship->location.x - universe[1].location.x;
176 diff.y = ship->location.y - universe[1].location.y;
177 diff.z = ship->location.z - universe[1].location.z;
178
179 vec = unit_vector (&diff);
180
181 ship->rotx = 0;
182
183 if (ship->type < 0)
184 {
185 ship->rotz = 1;
186 if (((vec.x >= 0) && (vec.y >= 0)) ||
187 ((vec.x < 0) && (vec.y < 0)))
188 {
189 ship->rotz = -ship->rotz;
190 }
191
192 if (fabs(vec.x) >= 0.0625)
193 {
194 ship->acceleration = 0;
195 ship->velocity = 1;
196 return;
197 }
198
199 if (fabs(vec.y) > 0.002436)
200 ship->rotx = (vec.y < 0) ? -1 : 1;
201
202 if (fabs(vec.y) >= 0.0625)
203 {
204 ship->acceleration = 0;
205 ship->velocity = 1;
206 return;
207 }
208 }
209
210 ship->rotz = 0;
211
212 dir = vector_dot_product (&ship->rotmat[0], &universe[1].rotmat[1]);
213
214 if (fabs(dir) >= 0.9166)
215 {
216 ship->acceleration++;
217 ship->rotz = 127;
218 return;
219 }
220
221 ship->acceleration = 0;
222 ship->rotz = 0;
223 }
224
225
226 /*
227 * Fly a ship to the planet or to the space station and dock it.
228 */
229
230 void auto_pilot_ship (struct univ_object *ship)
231 {
232 Vector diff;
233 Vector vec;
234 double dist;
235 double dir;
236
237 if ((ship->flags & FLG_FLY_TO_PLANET) ||
238 ((ship_count[SHIP_CORIOLIS] == 0) && (ship_count[SHIP_DODEC] == 0)))
239 {
240 fly_to_planet (ship);
241 return;
242 }
243
244 diff.x = ship->location.x - universe[1].location.x;
245 diff.y = ship->location.y - universe[1].location.y;
246 diff.z = ship->location.z - universe[1].location.z;
247
248 dist = sqrt (diff.x * diff.x + diff.y * diff.y + diff.z * diff.z);
249
250 if (dist < 160)
251 {
252 ship->flags |= FLG_REMOVE; // Ship has docked.
253 return;
254 }
255
256 vec = unit_vector (&diff);
257 dir = vector_dot_product (&universe[1].rotmat[2], &vec);
258
259 if (dir < 0.9722)
260 {
261 fly_to_station_front (ship);
262 return;
263 }
264
265 dir = vector_dot_product (&ship->rotmat[2], &vec);
266
267 if (dir < -0.9444)
268 {
269 fly_to_docking_bay (ship);
270 return;
271 }
272
273 fly_to_station (ship);
274 }
275
276
277 void engage_auto_pilot (void)
278 {
279 if (auto_pilot || witchspace || hyper_ready)
280 return;
281
282 auto_pilot = 1;
283 snd_play_midi (SND_BLUE_DANUBE, 1);
284 }
285
286
287 void disengage_auto_pilot (void)
288 {
289 if (auto_pilot)
290 {
291 auto_pilot = 0;
292 snd_stop_midi();
293 }
294 }