chiark / gitweb /
Add restart game option, and remapped keys setting.
[newkind] / docked.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 #include <string.h>
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <math.h>
20 #include <ctype.h>
21
22 #include "config.h"
23 #include "gfx.h"
24 #include "elite.h"
25 #include "planet.h"
26 #include "shipdata.h"
27 #include "space.h"
28 #include "keyboard.h"
29
30
31
32
33 char *economy_type[] = {"Rich Industrial",
34                                                 "Average Industrial",
35                                                 "Poor Industrial",
36                                                 "Mainly Industrial",
37                                                 "Mainly Agricultural",
38                                                 "Rich Agricultural",
39                                                 "Average Agricultural",
40                                                 "Poor Agricultural"};
41
42 char *government_type[] = {     "Anarchy",
43                                                         "Feudal",
44                                                         "Multi-Government",
45                                                         "Dictatorship",
46                                                         "Communist",
47                                                         "Confederacy",
48                                                         "Democracy",
49                                                         "Corporate State"};
50
51
52
53
54
55
56 int cross_x = 0;
57 int cross_y = 0;
58
59
60
61
62
63
64
65 void draw_fuel_limit_circle (int cx, int cy)
66 {
67         int radius;
68         int cross_size;
69
70         if (current_screen == SCR_GALACTIC_CHART)
71         {
72                 radius = cmdr.fuel / 4 * GFX_SCALE;
73                 cross_size = 7 * GFX_SCALE;
74         }
75         else
76         {
77                 radius = cmdr.fuel * GFX_SCALE;
78                 cross_size = 16 * GFX_SCALE;
79         }
80         
81         gfx_draw_circle (cx, cy, radius, GFX_COL_GREEN_1);
82
83         gfx_draw_line (cx, cy - cross_size, cx, cy + cross_size);
84         gfx_draw_line (cx - cross_size, cy, cx + cross_size, cy);
85 }
86
87
88
89
90
91 int calc_distance_to_planet (struct galaxy_seed from_planet, struct galaxy_seed to_planet)
92 {
93         int dx,dy;
94         int light_years;
95
96         dx = abs(to_planet.d - from_planet.d);
97         dy = abs(to_planet.b - from_planet.b);
98
99         dx = dx * dx;
100         dy = dy / 2;
101         dy = dy * dy;
102
103         light_years = sqrt(dx + dy);
104         light_years *= 4;
105
106         return light_years;
107 }
108
109
110 void show_distance (int ypos, struct galaxy_seed from_planet, struct galaxy_seed to_planet)
111 {
112         char str[100];
113         int light_years;
114
115         light_years = calc_distance_to_planet (from_planet, to_planet);
116         
117         if (light_years > 0)
118                 sprintf (str, "Distance: %2d.%d Light Years ", light_years / 10, light_years % 10);
119         else
120                 strcpy (str,"                                                     ");
121
122         gfx_display_text (16, ypos, str);
123 }
124
125
126
127 void show_distance_to_planet (void)
128 {
129         int px,py;
130         char planet_name[16];
131         char str[32];
132
133         if (current_screen == SCR_GALACTIC_CHART)
134         {
135                 px = cross_x / GFX_SCALE;
136                 py = (cross_y - ((18 * GFX_SCALE) + 1)) * (2 / GFX_SCALE);
137         }
138         else
139         {
140                 px = ((cross_x - GFX_X_CENTRE) / (4 * GFX_SCALE)) + docked_planet.d;
141                 py = ((cross_y - GFX_Y_CENTRE) / (2 * GFX_SCALE)) + docked_planet.b;
142         }
143
144         hyperspace_planet = find_planet (px, py);
145
146         name_planet (planet_name, hyperspace_planet);
147
148         gfx_clear_text_area();
149         sprintf (str, "%-18s", planet_name);
150         gfx_display_text (16, 340, str);
151
152         show_distance (356, docked_planet, hyperspace_planet);
153
154         if (current_screen == SCR_GALACTIC_CHART)
155         {
156                 cross_x = hyperspace_planet.d * GFX_SCALE;
157                 cross_y = hyperspace_planet.b / (2 / GFX_SCALE) + (18 * GFX_SCALE) + 1;
158         }
159         else
160         {
161                 cross_x = ((hyperspace_planet.d - docked_planet.d) * (4 * GFX_SCALE)) + GFX_X_CENTRE;
162                 cross_y = ((hyperspace_planet.b - docked_planet.b) * (2 * GFX_SCALE)) + GFX_Y_CENTRE;
163         }
164 }
165
166
167 void move_cursor_to_origin (void)
168 {
169         if (current_screen == SCR_GALACTIC_CHART)
170         {
171                 cross_x = docked_planet.d * GFX_SCALE;
172                 cross_y = docked_planet.b / (2 / GFX_SCALE) + (18 * GFX_SCALE) + 1;
173         }
174         else
175         {
176                 cross_x = GFX_X_CENTRE;
177                 cross_y = GFX_Y_CENTRE;
178         }
179
180         show_distance_to_planet();
181 }
182
183
184 void find_planet_by_name (char *find_name)
185 {
186     int i;
187         struct galaxy_seed glx;
188         char planet_name[16];
189         int found;
190         char str[32];
191         
192         glx = cmdr.galaxy;
193         found = 0;
194         
195         for (i = 0; i < 256; i++)
196         {
197                 name_planet (planet_name, glx);
198                 
199                 if (strcmp (planet_name, find_name) == 0)
200                 {
201                         found = 1;
202                         break;
203                 }
204
205                 waggle_galaxy (&glx);
206                 waggle_galaxy (&glx);
207                 waggle_galaxy (&glx);
208                 waggle_galaxy (&glx);
209         }
210
211         if (!found)
212         {
213                 gfx_clear_text_area();
214                 gfx_display_text (16, 340, "Unknown Planet");
215                 return;
216         }
217
218         hyperspace_planet = glx;
219
220         gfx_clear_text_area ();
221         sprintf (str, "%-18s", planet_name);
222         gfx_display_text (16, 340, str);
223
224         show_distance (356, docked_planet, hyperspace_planet);
225
226         if (current_screen == SCR_GALACTIC_CHART)
227         {
228                 cross_x = hyperspace_planet.d * GFX_SCALE;
229                 cross_y = hyperspace_planet.b / (2 / GFX_SCALE) + (18 * GFX_SCALE) + 1;
230         }
231         else
232         {
233                 cross_x = ((hyperspace_planet.d - docked_planet.d) * (4 * GFX_SCALE)) + GFX_X_CENTRE;
234                 cross_y = ((hyperspace_planet.b - docked_planet.b) * (2 * GFX_SCALE)) + GFX_Y_CENTRE;
235         }
236 }
237
238
239
240 void display_short_range_chart (void)
241 {
242     int i;
243         struct galaxy_seed glx;
244         int dx,dy;
245         int px,py;
246         char planet_name[16];
247         int row_used[64];
248         int row;
249         int blob_size;
250
251         current_screen = SCR_SHORT_RANGE;
252
253         gfx_clear_display();
254
255         gfx_display_centre_text (10, "SHORT RANGE CHART", 140, GFX_COL_GOLD);
256
257         gfx_draw_line (0, 36, 511, 36);
258
259         draw_fuel_limit_circle (GFX_X_CENTRE, GFX_Y_CENTRE);
260
261         for (i = 0; i < 64; i++)
262                 row_used[i] = 0;
263
264         glx = cmdr.galaxy;
265
266         for (i = 0; i < 256; i++)
267         {
268
269                 dx = abs (glx.d - docked_planet.d);
270                 dy = abs (glx.b - docked_planet.b);
271
272                 if ((dx >= 20) || (dy >= 38))
273                 {
274                         waggle_galaxy (&glx);
275                         waggle_galaxy (&glx);
276                         waggle_galaxy (&glx);
277                         waggle_galaxy (&glx);
278
279                         continue;
280                 }
281
282                 px = (glx.d - docked_planet.d);
283                 px = px * 4 * GFX_SCALE + GFX_X_CENTRE;  /* Convert to screen co-ords */
284
285                 py = (glx.b - docked_planet.b);
286                 py = py * 2 * GFX_SCALE + GFX_Y_CENTRE; /* Convert to screen co-ords */
287
288                 row = py / (8 * GFX_SCALE);
289
290                 if (row_used[row] == 1)
291                     row++;
292
293                 if (row_used[row] == 1)
294                         row -= 2;
295
296                 if (row <= 3)
297                 {
298                         waggle_galaxy (&glx);
299                         waggle_galaxy (&glx);
300                         waggle_galaxy (&glx);
301                         waggle_galaxy (&glx);
302
303                         continue;
304                 }
305
306                 if (row_used[row] == 0)
307                 {
308                         row_used[row] = 1;
309
310                         name_planet (planet_name, glx);
311                         capitalise_name (planet_name);
312
313                         gfx_display_text (px + (4 * GFX_SCALE), (row * 8 - 5) * GFX_SCALE, planet_name);
314                 }
315
316
317                 /* The next bit calculates the size of the circle used to represent */
318                 /* a planet.  The carry_flag is left over from the name generation. */
319                 /* Yes this was how it was done... don't ask :-( */
320
321                 blob_size = (glx.f & 1) + 2 + carry_flag;
322                 blob_size *= GFX_SCALE;
323                 gfx_draw_filled_circle (px, py, blob_size, GFX_COL_GOLD);
324
325                 waggle_galaxy (&glx);
326                 waggle_galaxy (&glx);
327                 waggle_galaxy (&glx);
328                 waggle_galaxy (&glx);
329         }
330
331         cross_x = ((hyperspace_planet.d - docked_planet.d) * 4 * GFX_SCALE) + GFX_X_CENTRE;
332         cross_y = ((hyperspace_planet.b - docked_planet.b) * 2 * GFX_SCALE) + GFX_Y_CENTRE;
333 }
334
335
336
337
338 void display_galactic_chart (void)
339 {
340     int i;
341         struct galaxy_seed glx;
342         char str[64];
343         int px,py;
344         
345
346         current_screen = SCR_GALACTIC_CHART;
347
348         gfx_clear_display();
349
350         sprintf (str, "GALACTIC CHART %d", cmdr.galaxy_number + 1);
351
352         gfx_display_centre_text (10, str, 140, GFX_COL_GOLD);
353
354         gfx_draw_line (0, 36, 511, 36);
355         gfx_draw_line (0, 36+258, 511, 36+258);
356
357         draw_fuel_limit_circle (docked_planet.d * GFX_SCALE,
358                                         (docked_planet.b / (2 / GFX_SCALE)) + (18 * GFX_SCALE) + 1);
359
360         glx = cmdr.galaxy;
361
362         for (i = 0; i < 256; i++)
363         {
364                 px = glx.d * GFX_SCALE;
365                 py = (glx.b / (2 / GFX_SCALE)) + (18 * GFX_SCALE) + 1;
366
367                 gfx_plot_pixel (px, py, GFX_COL_WHITE);
368
369                 if ((glx.e | 0x50) < 0x90)
370                         gfx_plot_pixel (px + 1, py, GFX_COL_WHITE);
371
372                 waggle_galaxy (&glx);
373                 waggle_galaxy (&glx);
374                 waggle_galaxy (&glx);
375                 waggle_galaxy (&glx);
376
377         }
378
379
380         cross_x = hyperspace_planet.d * GFX_SCALE;
381         cross_y = (hyperspace_planet.b / (2 / GFX_SCALE)) + (18 * GFX_SCALE) + 1;
382 }
383
384
385
386
387
388 /*
389  * Displays data on the currently selected Hyperspace Planet.
390  */
391
392 void display_data_on_planet (void)
393 {
394     char planet_name[16];
395         char str[100];
396         char *description;
397         struct planet_data hyper_planet_data;
398
399         current_screen = SCR_PLANET_DATA;
400
401         gfx_clear_display();
402
403         name_planet (planet_name, hyperspace_planet);
404         sprintf (str, "DATA ON %s", planet_name);
405
406         gfx_display_centre_text (10, str, 140, GFX_COL_GOLD);
407
408         gfx_draw_line (0, 36, 511, 36);
409
410
411         generate_planet_data (&hyper_planet_data, hyperspace_planet);
412
413         show_distance (42, docked_planet, hyperspace_planet);
414
415         sprintf (str, "Economy:%s", economy_type[hyper_planet_data.economy]);
416         gfx_display_text (16, 74, str);
417
418         sprintf (str, "Government:%s", government_type[hyper_planet_data.government]);
419         gfx_display_text (16, 106, str);
420
421         sprintf (str, "Tech.Level:%3d", hyper_planet_data.techlevel + 1);
422         gfx_display_text (16, 138, str);
423
424         sprintf (str, "Population:%d.%d Billion", hyper_planet_data.population / 10, hyper_planet_data.population % 10);
425         gfx_display_text (16, 170, str);
426
427         describe_inhabitants (str, hyperspace_planet);
428         gfx_display_text (16, 202, str);
429
430         sprintf (str, "Gross Productivity:%5d M CR", hyper_planet_data.productivity);
431         gfx_display_text (16, 234, str);
432
433         sprintf (str, "Average Radius:%5d km", hyper_planet_data.radius);
434         gfx_display_text (16, 266, str);
435
436         description = describe_planet (hyperspace_planet);
437         gfx_display_pretty_text (16, 298, 400, 384, description);
438 }
439
440
441
442 struct rank
443 {
444         int score;
445         char *title;
446 };
447
448 #define NO_OF_RANKS     9
449
450 struct rank rating[NO_OF_RANKS] =
451 {
452         {0x0000, "Harmless"},
453         {0x0008, "Mostly Harmless"},
454         {0x0010, "Poor"},
455         {0x0020, "Average"},
456         {0x0040, "Above Average"},
457         {0x0080, "Competent"},
458         {0x0200, "Dangerous"},
459         {0x0A00, "Deadly"},
460         {0x1900, "--- E L I T E ---"}
461 };
462
463 char *laser_name[5] = {"Pulse", "Beam", "Military", "Mining", "Custom"};
464
465
466
467 char *laser_type (int strength)
468 {
469         switch (strength)
470         {
471                 case PULSE_LASER:
472                         return laser_name[0];
473
474                 case BEAM_LASER:
475                         return laser_name[1];
476                 
477                 case MILITARY_LASER:
478                         return laser_name[2];
479                 
480                 case MINING_LASER:
481                         return laser_name[3];
482         }       
483
484         return laser_name[4];
485 }
486
487
488 #define EQUIP_START_Y   202
489 #define EQUIP_START_X   50
490 #define EQUIP_MAX_Y             290
491 #define EQUIP_WIDTH             200
492 #define Y_INC                   16
493
494
495 static char *condition_txt[] =
496 {
497         "Docked",
498         "Green",
499         "Yellow",
500         "Red",
501         "Red"
502 };
503
504 void display_commander_status (void)
505 {
506     char planet_name[16];
507         char str[100];
508         int i;
509         int x,y;
510         
511         current_screen = SCR_CMDR_STATUS;
512
513         gfx_clear_display();
514
515         sprintf (str, "COMMANDER %s", cmdr.name);
516
517         gfx_display_centre_text (10, str, 140, GFX_COL_GOLD);
518
519         gfx_draw_line (0, 36, 511, 36);
520
521
522         gfx_display_colour_text (16, 58, "Present System:", GFX_COL_GREEN_1);
523         
524         if (!witchspace)
525         {
526                 name_planet (planet_name, docked_planet);
527                 capitalise_name (planet_name);
528                 sprintf (str, "%s", planet_name);
529                 gfx_display_text (190, 58, str);
530         }
531
532         gfx_display_colour_text (16, 74, "Hyperspace System:", GFX_COL_GREEN_1);
533         name_planet (planet_name, hyperspace_planet);
534         capitalise_name (planet_name);
535         sprintf (str, "%s", planet_name);
536         gfx_display_text (190, 74, str);
537
538         gfx_display_colour_text (16, 90, "Condition:", GFX_COL_GREEN_1);
539         gfx_display_text (190, 90, condition_txt[condition]);
540
541         sprintf (str, "%d.%d Light Years", cmdr.fuel / 10, cmdr.fuel % 10);
542         gfx_display_colour_text (16, 106, "Fuel:", GFX_COL_GREEN_1);
543         gfx_display_text (70, 106, str);
544
545         sprintf (str, "%d.%d Cr", cmdr.credits / 10, cmdr.credits % 10);
546         gfx_display_colour_text (16, 122, "Cash:", GFX_COL_GREEN_1);
547         gfx_display_text (70, 122, str);
548
549         if (cmdr.legal_status == 0)
550                 strcpy (str, "Clean");
551         else
552                 strcpy (str, cmdr.legal_status > 50 ? "Fugitive" : "Offender");
553
554         gfx_display_colour_text (16, 138, "Legal Status:", GFX_COL_GREEN_1);
555         gfx_display_text (128, 138, str);
556
557         for (i = 0; i < NO_OF_RANKS; i++)
558                 if (cmdr.score >= rating[i].score)
559                         strcpy (str, rating[i].title);
560         
561         gfx_display_colour_text (16, 154, "Rating:", GFX_COL_GREEN_1);
562         gfx_display_text (80, 154, str);
563
564         gfx_display_colour_text (16, 186, "EQUIPMENT:", GFX_COL_GREEN_1);
565
566         x = EQUIP_START_X;
567         y = EQUIP_START_Y;
568
569         if (cmdr.cargo_capacity > 20)
570         {
571                 gfx_display_text (x, y, "Large Cargo Bay");
572                 y += Y_INC;
573         }
574         
575         if (cmdr.escape_pod)
576         {
577                 gfx_display_text (x, y, "Escape Pod");
578                 y += Y_INC;
579         }
580         
581         if (cmdr.fuel_scoop)
582         {
583                 gfx_display_text (x, y, "Fuel Scoops");
584                 y += Y_INC;
585         }
586
587         if (cmdr.ecm)
588         {
589                 gfx_display_text (x, y, "E.C.M. System");
590                 y += Y_INC;
591         }
592
593         if (cmdr.energy_bomb)
594         {
595                 gfx_display_text (x, y, "Energy Bomb");
596                 y += Y_INC;
597         }
598
599         if (cmdr.energy_unit)
600         {
601                 gfx_display_text (x, y,
602                                   cmdr.energy_unit == 1 ? "Extra Energy Unit" :"Naval Energy Unit");
603                 y += Y_INC;
604                 if (y > EQUIP_MAX_Y)
605                 {
606                         y = EQUIP_START_Y;
607                         x += EQUIP_WIDTH;
608                 }
609         }
610
611         if (cmdr.docking_computer)
612         {
613                 gfx_display_text (x, y, "Docking Computers");
614                 y += Y_INC;
615                 if (y > EQUIP_MAX_Y)
616                 {
617                         y = EQUIP_START_Y;
618                         x += EQUIP_WIDTH;
619                 }
620         }
621
622         
623         if (cmdr.galactic_hyperdrive)
624         {
625                 gfx_display_text (x, y, "Galactic Hyperspace");
626                 y += Y_INC;
627                 if (y > EQUIP_MAX_Y)
628                 {
629                         y = EQUIP_START_Y;
630                         x += EQUIP_WIDTH;
631                 }
632         }
633
634         if (cmdr.front_laser)
635         {
636                 sprintf (str, "Front %s Laser", laser_type(cmdr.front_laser));
637                 gfx_display_text (x, y, str);
638                 y += Y_INC;
639                 if (y > EQUIP_MAX_Y)
640                 {
641                         y = EQUIP_START_Y;
642                         x += EQUIP_WIDTH;
643                 }
644         }
645         
646         if (cmdr.rear_laser)
647         {
648                 sprintf (str, "Rear %s Laser", laser_type(cmdr.rear_laser));
649                 gfx_display_text (x, y, str);
650                 y += Y_INC;
651                 if (y > EQUIP_MAX_Y)
652                 {
653                         y = EQUIP_START_Y;
654                         x += EQUIP_WIDTH;
655                 }
656         }
657
658         if (cmdr.left_laser)
659         {
660                 sprintf (str, "Left %s Laser", laser_type(cmdr.left_laser));
661                 gfx_display_text (x, y, str);
662                 y += Y_INC;
663                 if (y > EQUIP_MAX_Y)
664                 {
665                         y = EQUIP_START_Y;
666                         x += EQUIP_WIDTH;
667                 }
668         }
669
670         if (cmdr.right_laser)
671         {
672                 sprintf (str, "Right %s Laser", laser_type(cmdr.right_laser));
673                 gfx_display_text (x, y, str);
674         }
675 }
676
677
678
679 /***********************************************************************************/
680
681 #define TONNES          0
682 #define KILOGRAMS       1
683 #define GRAMS           2
684
685 static int hilite_item;
686 static char *unit_name[] = {"t", "kg", "g"};
687
688
689 void display_stock_price (int i)
690 {
691         int y;
692         char str[100];
693
694         y = i * 15 + 55;
695
696         gfx_display_text (16, y, stock_market[i].name);
697
698         gfx_display_text (180, y, unit_name[stock_market[i].units]);
699         sprintf (str, "%d.%d", stock_market[i].current_price / 10,
700                                                    stock_market[i].current_price % 10);
701         gfx_display_text (256, y, str);
702
703         if (stock_market[i].current_quantity > 0)
704                 sprintf (str, "%d%s", stock_market[i].current_quantity,
705                                                           unit_name[stock_market[i].units]);
706         else
707                 strcpy (str, "-");
708
709         gfx_display_text (338, y, str);
710
711         if (cmdr.current_cargo[i] > 0)
712                 sprintf (str, "%d%s", cmdr.current_cargo[i],
713                                                           unit_name[stock_market[i].units]);
714         else
715                 strcpy (str, "-");
716
717         gfx_display_text (444, y, str);
718 }
719
720
721 void highlight_stock (int i)
722 {
723         int y;
724         char str[30];
725         
726         if ((hilite_item != -1) && (hilite_item != i))
727         {
728                 y = hilite_item * 15 + 55;
729                 gfx_clear_area (2, y, 510, y + 15);
730                 display_stock_price (hilite_item);              
731         }
732
733         y = i * 15 + 55;
734         
735         gfx_draw_rectangle (2, y, 510, y + 15, GFX_COL_DARK_RED);
736         display_stock_price (i);                
737
738         hilite_item = i;
739
740         gfx_clear_text_area();
741         sprintf (str, "Cash: %d.%d", cmdr.credits / 10, cmdr.credits % 10);
742         gfx_display_text (16, 340, str);
743 }
744
745 void select_previous_stock (void)
746 {
747         if ((!docked) || (hilite_item == 0))
748                 return;
749
750         highlight_stock (hilite_item - 1);
751 }
752
753 void select_next_stock (void)
754 {
755         if ((!docked) || (hilite_item == 16))
756                 return;
757
758         highlight_stock (hilite_item + 1);
759 }
760
761
762 void buy_stock (void)
763 {
764         struct stock_item *item;
765         int cargo_held;
766         
767         if (!docked)
768                 return;
769
770         item = &stock_market[hilite_item];
771
772         do {
773           if ((item->current_quantity == 0) ||
774                   (cmdr.credits < item->current_price))
775                 return;
776
777           cargo_held = total_cargo();
778         
779           if ((item->units == TONNES) &&
780                   (cargo_held == cmdr.cargo_capacity))
781                 return;
782         
783           cmdr.current_cargo[hilite_item]++;
784           item->current_quantity--;
785           cmdr.credits -= item->current_price;  
786
787           highlight_stock (hilite_item);
788         } while (kbd_ctrl_pressed);
789 }
790
791
792 void sell_stock (void)
793 {
794         struct stock_item *item;
795
796         do {
797           if ((!docked) || (cmdr.current_cargo[hilite_item] == 0))
798                 return;
799
800           item = &stock_market[hilite_item];
801
802           cmdr.current_cargo[hilite_item]--;
803           item->current_quantity++;
804           cmdr.credits += item->current_price;  
805
806           highlight_stock (hilite_item);
807         } while (kbd_ctrl_pressed);
808 }
809
810
811
812 void display_market_prices (void)
813 {
814         char str[100];
815     char planet_name[16];
816         int i;
817
818         current_screen = SCR_MARKET_PRICES;
819
820         gfx_clear_display();
821
822         name_planet (planet_name, docked_planet);
823         sprintf (str, "%s MARKET PRICES", planet_name);
824         gfx_display_centre_text (10, str, 140, GFX_COL_GOLD);
825
826         gfx_draw_line (0, 36, 511, 36);
827
828         gfx_display_colour_text (16,  40, "PRODUCT", GFX_COL_GREEN_1);
829         gfx_display_colour_text (166, 40, "UNIT", GFX_COL_GREEN_1);
830         gfx_display_colour_text (246, 40, "PRICE", GFX_COL_GREEN_1);
831         gfx_display_colour_text (314, 40, "FOR SALE", GFX_COL_GREEN_1);
832         gfx_display_colour_text (420, 40, "IN HOLD", GFX_COL_GREEN_1);
833
834         for (i = 0; i < 17; i++)
835         {
836                 display_stock_price (i);
837         }
838
839         if (docked)
840         {
841                 hilite_item = -1;
842                 highlight_stock (0);
843         }
844 }
845
846
847 void display_inventory (void)
848 {
849         int i;
850         int y;
851         char str[80];
852         
853         current_screen = SCR_INVENTORY;
854
855         gfx_clear_display();
856         gfx_display_centre_text (10, "INVENTORY", 140, GFX_COL_GOLD);
857         gfx_draw_line (0, 36, 511, 36);
858         
859         sprintf (str, "%d.%d Light Years", cmdr.fuel / 10, cmdr.fuel % 10);
860         gfx_display_colour_text (16, 50, "Fuel:", GFX_COL_GREEN_1);
861         gfx_display_text (70, 50, str);
862
863         sprintf (str, "%d.%d Cr", cmdr.credits / 10, cmdr.credits % 10);
864         gfx_display_colour_text (16, 66, "Cash:", GFX_COL_GREEN_1);
865         gfx_display_text (70, 66, str);
866         
867         y = 98;
868         for (i = 0; i < 17; i++)
869         {
870                 if (cmdr.current_cargo[i] > 0)
871                 {
872                         gfx_display_text (16, y, stock_market[i].name);
873
874                         sprintf (str, "%d%s", cmdr.current_cargo[i],
875                                                           unit_name[stock_market[i].units]);
876
877                         gfx_display_text (180, y, str);
878                         y += 16;
879                 }               
880         }
881 }
882
883 /***********************************************************************************/
884
885 enum equip_types
886 {
887         EQ_FUEL, EQ_MISSILE, EQ_CARGO_BAY, EQ_ECM, EQ_FUEL_SCOOPS,
888         EQ_ESCAPE_POD, EQ_ENERGY_BOMB, EQ_ENERGY_UNIT, EQ_DOCK_COMP,
889         EQ_GAL_DRIVE, EQ_PULSE_LASER, EQ_FRONT_PULSE, EQ_REAR_PULSE,
890         EQ_LEFT_PULSE, EQ_RIGHT_PULSE, EQ_BEAM_LASER, EQ_FRONT_BEAM,
891         EQ_REAR_BEAM, EQ_LEFT_BEAM, EQ_RIGHT_BEAM, EQ_MINING_LASER,
892         EQ_FRONT_MINING, EQ_REAR_MINING, EQ_LEFT_MINING, EQ_RIGHT_MINING,
893         EQ_MILITARY_LASER, EQ_FRONT_MILITARY, EQ_REAR_MILITARY,
894         EQ_LEFT_MILITARY, EQ_RIGHT_MILITARY
895 };
896         
897                 
898
899 #define NO_OF_EQUIP_ITEMS       34
900
901 struct equip_item
902 {
903         int canbuy;
904         int y;
905         int show;
906         int level;
907         int price;
908         char *name;
909         int type;
910 };
911
912 struct equip_item equip_stock[NO_OF_EQUIP_ITEMS] =
913 {
914         {0, 0, 1, 1,     2, " Fuel",                                    EQ_FUEL},
915         {0, 0, 1, 1,   300, " Missile",                                 EQ_MISSILE},
916         {0, 0, 1, 1,  4000, " Large Cargo Bay",                 EQ_CARGO_BAY},
917         {0, 0, 1, 2,  6000, " E.C.M. System",                   EQ_ECM},
918         {0, 0, 1, 5,  5250, " Fuel Scoops",                             EQ_FUEL_SCOOPS},
919         {0, 0, 1, 6, 10000, " Escape Pod",                              EQ_ESCAPE_POD},
920         {0, 0, 1, 7,  9000, " Energy Bomb",                             EQ_ENERGY_BOMB},
921         {0, 0, 1, 8, 15000, " Extra Energy Unit",               EQ_ENERGY_UNIT},
922         {0, 0, 1, 9, 15000, " Docking Computers",               EQ_DOCK_COMP},
923         {0, 0, 1,10, 50000, " Galactic Hyperdrive",             EQ_GAL_DRIVE},
924         {0, 0, 0, 3,  4000, "+Pulse Laser",                             EQ_PULSE_LASER},
925         {0, 0, 1, 3,     0, "-Pulse Laser",                             EQ_PULSE_LASER},
926         {0, 0, 1, 3,  4000, ">Front",                                   EQ_FRONT_PULSE},
927         {0, 0, 1, 3,  4000, ">Rear",                                    EQ_REAR_PULSE},
928         {0, 0, 1, 3,  4000, ">Left",                                    EQ_LEFT_PULSE},
929         {0, 0, 1, 3,  4000, ">Right",                                   EQ_RIGHT_PULSE},
930         {0, 0, 1, 4, 10000, "+Beam Laser",                              EQ_BEAM_LASER},
931         {0, 0, 0, 4,     0, "-Beam Laser",                              EQ_BEAM_LASER},
932         {0, 0, 0, 4, 10000, ">Front",                                   EQ_FRONT_BEAM},
933         {0, 0, 0, 4, 10000, ">Rear",                                    EQ_REAR_BEAM},
934         {0, 0, 0, 4, 10000, ">Left",                                    EQ_LEFT_BEAM},
935         {0, 0, 0, 4, 10000, ">Right",                                   EQ_RIGHT_BEAM},
936         {0, 0, 1,10,  8000, "+Mining Laser",                    EQ_MINING_LASER},
937         {0, 0, 0,10,     0, "-Mining Laser",                    EQ_MINING_LASER},
938         {0, 0, 0,10,  8000, ">Front",                                   EQ_FRONT_MINING},
939         {0, 0, 0,10,  8000, ">Rear",                                    EQ_REAR_MINING},
940         {0, 0, 0,10,  8000, ">Left",                                    EQ_LEFT_MINING},
941         {0, 0, 0,10,  8000, ">Right",                                   EQ_RIGHT_MINING},
942         {0, 0, 1,10, 60000, "+Military Laser",                  EQ_MILITARY_LASER},
943         {0, 0, 0,10,     0, "-Military Laser",                  EQ_MILITARY_LASER},
944         {0, 0, 0,10, 60000, ">Front",                                   EQ_FRONT_MILITARY},
945         {0, 0, 0,10, 60000, ">Rear",                                    EQ_REAR_MILITARY},
946         {0, 0, 0,10, 60000, ">Left",                                    EQ_LEFT_MILITARY},
947         {0, 0, 0,10, 60000, ">Right",                                   EQ_RIGHT_MILITARY}
948 };
949
950
951 int equip_present (int type)
952 {
953         switch (type)
954         {
955                 case EQ_FUEL:
956                         return (cmdr.fuel >= 70);
957                 
958                 case EQ_MISSILE:
959                         return (cmdr.missiles >= 4);
960                 
961                 case EQ_CARGO_BAY:
962                         return (cmdr.cargo_capacity > 20);
963                 
964                 case EQ_ECM:
965                         return cmdr.ecm;
966                 
967                 case EQ_FUEL_SCOOPS:
968                         return cmdr.fuel_scoop;
969                 
970                 case EQ_ESCAPE_POD:
971                         return cmdr.escape_pod;
972                 
973                 case EQ_ENERGY_BOMB:
974                         return cmdr.energy_bomb;
975
976                 case EQ_ENERGY_UNIT:
977                         return cmdr.energy_unit;
978                         
979                 case EQ_DOCK_COMP:
980                         return cmdr.docking_computer;
981                         
982                 case EQ_GAL_DRIVE:
983                         return cmdr.galactic_hyperdrive;
984                         
985                 case EQ_FRONT_PULSE:
986                         return (cmdr.front_laser == PULSE_LASER);
987                 
988                 case EQ_REAR_PULSE:
989                         return (cmdr.rear_laser == PULSE_LASER);
990
991                 case EQ_LEFT_PULSE:
992                         return (cmdr.left_laser == PULSE_LASER);
993
994                 case EQ_RIGHT_PULSE:
995                         return (cmdr.right_laser == PULSE_LASER);
996
997                 case EQ_FRONT_BEAM:
998                         return (cmdr.front_laser == BEAM_LASER);
999
1000                 case EQ_REAR_BEAM:
1001                         return (cmdr.rear_laser == BEAM_LASER);
1002
1003                 case EQ_LEFT_BEAM:
1004                         return (cmdr.left_laser == BEAM_LASER);
1005
1006                 case EQ_RIGHT_BEAM:
1007                         return (cmdr.right_laser == BEAM_LASER);
1008
1009                 case EQ_FRONT_MINING:
1010                         return (cmdr.front_laser == MINING_LASER);
1011
1012                 case EQ_REAR_MINING:
1013                         return (cmdr.rear_laser == MINING_LASER);
1014
1015                 case EQ_LEFT_MINING:
1016                         return (cmdr.left_laser == MINING_LASER);
1017
1018                 case EQ_RIGHT_MINING:
1019                         return (cmdr.right_laser == MINING_LASER);
1020
1021                 case EQ_FRONT_MILITARY:
1022                         return (cmdr.front_laser == MILITARY_LASER);
1023
1024                 case EQ_REAR_MILITARY:
1025                         return (cmdr.rear_laser == MILITARY_LASER);
1026
1027                 case EQ_LEFT_MILITARY:
1028                         return (cmdr.left_laser == MILITARY_LASER);
1029
1030                 case EQ_RIGHT_MILITARY:
1031                         return (cmdr.right_laser == MILITARY_LASER);
1032         }
1033
1034         return 0;
1035 }
1036
1037
1038 void display_equip_price (int i)
1039 {
1040         int x, y;
1041         int col;
1042         char str[100];
1043         
1044         y = equip_stock[i].y;
1045         if (y == 0)
1046                 return;
1047
1048         col = equip_stock[i].canbuy ? GFX_COL_WHITE : GFX_COL_GREY_1;
1049
1050         x = *(equip_stock[i].name) == '>' ? 50 : 16; 
1051
1052         gfx_display_colour_text (x, y, &equip_stock[i].name[1], col);
1053
1054         if (equip_stock[i].price != 0)
1055         {
1056                 sprintf (str, "%d.%d", equip_stock[i].price / 10, equip_stock[i].price % 10);
1057                 gfx_display_colour_text (338, y, str, col);
1058         }
1059 }
1060
1061
1062 void highlight_equip (int i)
1063 {
1064         int y;
1065         char str[30];
1066         
1067         if ((hilite_item != -1) && (hilite_item != i))
1068         {
1069                 y = equip_stock[hilite_item].y;
1070                 gfx_clear_area (2, y+1, 510, y + 15);
1071                 display_equip_price (hilite_item);              
1072         }
1073
1074         y = equip_stock[i].y;
1075         
1076         gfx_draw_rectangle (2, y+1, 510, y + 15, GFX_COL_DARK_RED);
1077         display_equip_price (i);                
1078
1079         hilite_item = i;
1080
1081         gfx_clear_text_area();
1082         sprintf (str, "Cash: %d.%d", cmdr.credits / 10, cmdr.credits % 10);
1083         gfx_display_text (16, 340, str);
1084 }
1085
1086
1087 void select_next_equip (void)
1088 {
1089         int next;
1090         int i;
1091
1092         if (hilite_item == (NO_OF_EQUIP_ITEMS - 1))
1093                 return;
1094
1095         next = hilite_item;
1096         for (i = hilite_item + 1; i < NO_OF_EQUIP_ITEMS; i++)
1097         {
1098                 if (equip_stock[i].y != 0)
1099                 {
1100                         next = i;
1101                         break;
1102                 }
1103         }
1104
1105         if (next != hilite_item)        
1106                 highlight_equip (next);
1107 }
1108
1109 void select_previous_equip (void)
1110 {
1111         int i;
1112         int prev;
1113         
1114         if (hilite_item == 0)
1115                 return;
1116         
1117         prev = hilite_item;
1118         for (i = hilite_item - 1; i >= 0; i--)
1119         {
1120                 if (equip_stock[i].y != 0)
1121                 {
1122                         prev = i;
1123                         break;
1124                 }
1125         }
1126
1127         if (prev != hilite_item)        
1128                 highlight_equip (prev);
1129 }
1130
1131
1132 void list_equip_prices (void)
1133 {
1134         int i;
1135         int y;
1136         int tech_level;
1137
1138         gfx_clear_area (2, 55, 510, 380);
1139         
1140         tech_level = current_planet_data.techlevel + 1;
1141
1142         equip_stock[0].price = (70 - cmdr.fuel) * 2;
1143         
1144         y = 55;
1145         for (i = 0; i < NO_OF_EQUIP_ITEMS; i++)
1146         {
1147             equip_stock[i].canbuy = ((equip_present (equip_stock[i].type) == 0) &&
1148                                                                  (equip_stock[i].price <= cmdr.credits));
1149         
1150                 if (equip_stock[i].show && (tech_level >= equip_stock[i].level))
1151                 {
1152                         equip_stock[i].y = y;
1153                         y += 15;
1154                 }
1155                 else
1156                         equip_stock[i].y = 0;
1157
1158                 display_equip_price (i);
1159         }
1160         
1161         i = hilite_item;
1162         hilite_item = -1;
1163         highlight_equip (i);
1164 }
1165
1166
1167 void collapse_equip_list (void)
1168 {
1169         int i;
1170         int ch;
1171         
1172         for (i = 0; i < NO_OF_EQUIP_ITEMS; i++)
1173         {
1174                 ch = *(equip_stock[i].name);
1175                 equip_stock[i].show = ((ch == ' ') || (ch == '+'));
1176         }
1177 }
1178
1179
1180 int laser_refund (int laser_type)
1181 {
1182         switch (laser_type)
1183         {
1184                 case PULSE_LASER:
1185                         return 4000;
1186                 
1187                 case BEAM_LASER:
1188                         return 10000;
1189                 
1190                 case MILITARY_LASER:
1191                         return 60000;
1192                 
1193                 case MINING_LASER:
1194                         return 8000;
1195         }
1196
1197         return 0;
1198 }
1199
1200
1201 void buy_equip (void)
1202 {
1203         int i;
1204
1205         if (equip_stock[hilite_item].name[0] == '+')
1206         {
1207                 collapse_equip_list();
1208                 equip_stock[hilite_item].show = 0;
1209                 hilite_item++;
1210                 for (i = 0; i < 5; i++)
1211                         equip_stock[hilite_item + i].show = 1;
1212                 
1213                 list_equip_prices();
1214                 return;         
1215         }
1216
1217         if (equip_stock[hilite_item].canbuy == 0)
1218                 return;
1219         
1220         switch (equip_stock[hilite_item].type)
1221         {
1222                 case EQ_FUEL:
1223                         cmdr.fuel = myship.max_fuel;
1224                         update_console();
1225                         break;
1226
1227                 case EQ_MISSILE:
1228                         cmdr.missiles++;
1229                         update_console();
1230                         break;
1231                 
1232                 case EQ_CARGO_BAY:
1233                         cmdr.cargo_capacity = 35;
1234                         break;
1235                 
1236                 case EQ_ECM:
1237                         cmdr.ecm = 1;
1238                         break;
1239                 
1240                 case EQ_FUEL_SCOOPS:
1241                         cmdr.fuel_scoop = 1;
1242                         break;
1243                 
1244                 case EQ_ESCAPE_POD:
1245                         cmdr.escape_pod = 1;
1246                         break;
1247                 
1248                 case EQ_ENERGY_BOMB:
1249                         cmdr.energy_bomb = 1;
1250                         break;
1251
1252                 case EQ_ENERGY_UNIT:
1253                         cmdr.energy_unit = 1;
1254                         break;
1255                         
1256                 case EQ_DOCK_COMP:
1257                         cmdr.docking_computer = 1;
1258                         break;
1259                         
1260                 case EQ_GAL_DRIVE:
1261                         cmdr.galactic_hyperdrive = 1;
1262                         break;
1263                         
1264                 case EQ_FRONT_PULSE:
1265                         cmdr.credits += laser_refund (cmdr.front_laser);
1266                         cmdr.front_laser = PULSE_LASER;
1267                         break;
1268                 
1269                 case EQ_REAR_PULSE:
1270                         cmdr.credits += laser_refund (cmdr.rear_laser);
1271                         cmdr.rear_laser = PULSE_LASER;
1272                         break;
1273
1274                 case EQ_LEFT_PULSE:
1275                         cmdr.credits += laser_refund (cmdr.left_laser);
1276                         cmdr.left_laser = PULSE_LASER;
1277                         break;
1278
1279                 case EQ_RIGHT_PULSE:
1280                         cmdr.credits += laser_refund (cmdr.right_laser);
1281                         cmdr.right_laser = PULSE_LASER;
1282                         break;
1283
1284                 case EQ_FRONT_BEAM:
1285                         cmdr.credits += laser_refund (cmdr.front_laser);
1286                         cmdr.front_laser = BEAM_LASER;
1287                         break;
1288
1289                 case EQ_REAR_BEAM:
1290                         cmdr.credits += laser_refund (cmdr.rear_laser);
1291                         cmdr.rear_laser = BEAM_LASER;
1292                         break;
1293
1294                 case EQ_LEFT_BEAM:
1295                         cmdr.credits += laser_refund (cmdr.left_laser);
1296                         cmdr.left_laser = BEAM_LASER;
1297                         break;
1298
1299                 case EQ_RIGHT_BEAM:
1300                         cmdr.credits += laser_refund (cmdr.right_laser);
1301                         cmdr.right_laser = BEAM_LASER;
1302                         break;
1303
1304                 case EQ_FRONT_MINING:
1305                         cmdr.credits += laser_refund (cmdr.front_laser);
1306                         cmdr.front_laser = MINING_LASER;
1307                         break;
1308
1309                 case EQ_REAR_MINING:
1310                         cmdr.credits += laser_refund (cmdr.rear_laser);
1311                         cmdr.rear_laser = MINING_LASER;
1312                         break;
1313
1314                 case EQ_LEFT_MINING:
1315                         cmdr.credits += laser_refund (cmdr.left_laser);
1316                         cmdr.left_laser = MINING_LASER;
1317                         break;
1318
1319                 case EQ_RIGHT_MINING:
1320                         cmdr.credits += laser_refund (cmdr.right_laser);
1321                         cmdr.right_laser = MINING_LASER;
1322                         break;
1323
1324                 case EQ_FRONT_MILITARY:
1325                         cmdr.credits += laser_refund (cmdr.front_laser);
1326                         cmdr.front_laser = MILITARY_LASER;
1327                         break;
1328
1329                 case EQ_REAR_MILITARY:
1330                         cmdr.credits += laser_refund (cmdr.rear_laser);
1331                         cmdr.rear_laser = MILITARY_LASER;
1332                         break;
1333
1334                 case EQ_LEFT_MILITARY:
1335                         cmdr.credits += laser_refund (cmdr.left_laser);
1336                         cmdr.left_laser = MILITARY_LASER;
1337                         break;
1338
1339                 case EQ_RIGHT_MILITARY:
1340                         cmdr.credits += laser_refund (cmdr.right_laser);
1341                         cmdr.right_laser = MILITARY_LASER;
1342                         break;
1343         }
1344
1345         cmdr.credits -= equip_stock[hilite_item].price;
1346         list_equip_prices();
1347 }
1348
1349
1350 void equip_ship (void)
1351 {
1352         current_screen = SCR_EQUIP_SHIP;
1353
1354         gfx_clear_display();
1355         gfx_display_centre_text (10, "EQUIP SHIP", 140, GFX_COL_GOLD);
1356         gfx_draw_line (0, 36, 511, 36);
1357
1358         collapse_equip_list();
1359         
1360         hilite_item = 0;
1361         
1362         list_equip_prices();
1363 }