chiark / gitweb /
This commit was manufactured by cvs2svn to create branch 'pinder'.
[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
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 };
502
503 void display_commander_status (void)
504 {
505     char planet_name[16];
506         char str[100];
507         int i;
508         int x,y;
509         int condition;
510         int type;
511         
512         current_screen = SCR_CMDR_STATUS;
513
514         gfx_clear_display();
515
516         sprintf (str, "COMMANDER %s", cmdr.name);
517
518         gfx_display_centre_text (10, str, 140, GFX_COL_GOLD);
519
520         gfx_draw_line (0, 36, 511, 36);
521
522
523         gfx_display_colour_text (16, 58, "Present System:", GFX_COL_GREEN_1);
524         
525         if (!witchspace)
526         {
527                 name_planet (planet_name, docked_planet);
528                 capitalise_name (planet_name);
529                 sprintf (str, "%s", planet_name);
530                 gfx_display_text (190, 58, str);
531         }
532
533         gfx_display_colour_text (16, 74, "Hyperspace System:", GFX_COL_GREEN_1);
534         name_planet (planet_name, hyperspace_planet);
535         capitalise_name (planet_name);
536         sprintf (str, "%s", planet_name);
537         gfx_display_text (190, 74, str);
538
539         if (docked)
540                 condition = 0;
541         else
542         {
543                 condition = 1;
544
545                 for (i = 0; i < MAX_UNIV_OBJECTS; i++)
546                 {
547                         type = universe[i].type;
548                 
549                         if ((type == SHIP_MISSILE) ||
550                                 ((type > SHIP_ROCK) && (type < SHIP_DODEC)))
551                         {
552                                 condition = 2;
553                                 break;
554                         }
555                 }
556  
557                 if ((condition == 2) && (energy < 128))
558                         condition = 3;
559         }
560         
561         gfx_display_colour_text (16, 90, "Condition:", GFX_COL_GREEN_1);
562         gfx_display_text (190, 90, condition_txt[condition]);
563
564         sprintf (str, "%d.%d Light Years", cmdr.fuel / 10, cmdr.fuel % 10);
565         gfx_display_colour_text (16, 106, "Fuel:", GFX_COL_GREEN_1);
566         gfx_display_text (70, 106, str);
567
568         sprintf (str, "%d.%d Cr", cmdr.credits / 10, cmdr.credits % 10);
569         gfx_display_colour_text (16, 122, "Cash:", GFX_COL_GREEN_1);
570         gfx_display_text (70, 122, str);
571
572         if (cmdr.legal_status == 0)
573                 strcpy (str, "Clean");
574         else
575                 strcpy (str, cmdr.legal_status > 50 ? "Fugitive" : "Offender");
576
577         gfx_display_colour_text (16, 138, "Legal Status:", GFX_COL_GREEN_1);
578         gfx_display_text (128, 138, str);
579
580         for (i = 0; i < NO_OF_RANKS; i++)
581                 if (cmdr.score >= rating[i].score)
582                         strcpy (str, rating[i].title);
583         
584         gfx_display_colour_text (16, 154, "Rating:", GFX_COL_GREEN_1);
585         gfx_display_text (80, 154, str);
586
587         gfx_display_colour_text (16, 186, "EQUIPMENT:", GFX_COL_GREEN_1);
588
589         x = EQUIP_START_X;
590         y = EQUIP_START_Y;
591
592         if (cmdr.cargo_capacity > 20)
593         {
594                 gfx_display_text (x, y, "Large Cargo Bay");
595                 y += Y_INC;
596         }
597         
598         if (cmdr.escape_pod)
599         {
600                 gfx_display_text (x, y, "Escape Pod");
601                 y += Y_INC;
602         }
603         
604         if (cmdr.fuel_scoop)
605         {
606                 gfx_display_text (x, y, "Fuel Scoops");
607                 y += Y_INC;
608         }
609
610         if (cmdr.ecm)
611         {
612                 gfx_display_text (x, y, "E.C.M. System");
613                 y += Y_INC;
614         }
615
616         if (cmdr.energy_bomb)
617         {
618                 gfx_display_text (x, y, "Energy Bomb");
619                 y += Y_INC;
620         }
621
622         if (cmdr.energy_unit)
623         {
624                 gfx_display_text (x, y,
625                                   cmdr.energy_unit == 1 ? "Extra Energy Unit" :"Naval Energy Unit");
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.docking_computer)
635         {
636                 gfx_display_text (x, y, "Docking Computers");
637                 y += Y_INC;
638                 if (y > EQUIP_MAX_Y)
639                 {
640                         y = EQUIP_START_Y;
641                         x += EQUIP_WIDTH;
642                 }
643         }
644
645         
646         if (cmdr.galactic_hyperdrive)
647         {
648                 gfx_display_text (x, y, "Galactic Hyperspace");
649                 y += Y_INC;
650                 if (y > EQUIP_MAX_Y)
651                 {
652                         y = EQUIP_START_Y;
653                         x += EQUIP_WIDTH;
654                 }
655         }
656
657         if (cmdr.front_laser)
658         {
659                 sprintf (str, "Front %s Laser", laser_type(cmdr.front_laser));
660                 gfx_display_text (x, y, str);
661                 y += Y_INC;
662                 if (y > EQUIP_MAX_Y)
663                 {
664                         y = EQUIP_START_Y;
665                         x += EQUIP_WIDTH;
666                 }
667         }
668         
669         if (cmdr.rear_laser)
670         {
671                 sprintf (str, "Rear %s Laser", laser_type(cmdr.rear_laser));
672                 gfx_display_text (x, y, str);
673                 y += Y_INC;
674                 if (y > EQUIP_MAX_Y)
675                 {
676                         y = EQUIP_START_Y;
677                         x += EQUIP_WIDTH;
678                 }
679         }
680
681         if (cmdr.left_laser)
682         {
683                 sprintf (str, "Left %s Laser", laser_type(cmdr.left_laser));
684                 gfx_display_text (x, y, str);
685                 y += Y_INC;
686                 if (y > EQUIP_MAX_Y)
687                 {
688                         y = EQUIP_START_Y;
689                         x += EQUIP_WIDTH;
690                 }
691         }
692
693         if (cmdr.right_laser)
694         {
695                 sprintf (str, "Right %s Laser", laser_type(cmdr.right_laser));
696                 gfx_display_text (x, y, str);
697         }
698 }
699
700
701
702 /***********************************************************************************/
703
704 #define TONNES          0
705 #define KILOGRAMS       1
706 #define GRAMS           2
707
708 static int hilite_item;
709 static char *unit_name[] = {"t", "kg", "g"};
710
711
712 void display_stock_price (int i)
713 {
714         int y;
715         char str[100];
716
717         y = i * 15 + 55;
718
719         gfx_display_text (16, y, stock_market[i].name);
720
721         gfx_display_text (180, y, unit_name[stock_market[i].units]);
722         sprintf (str, "%d.%d", stock_market[i].current_price / 10,
723                                                    stock_market[i].current_price % 10);
724         gfx_display_text (256, y, str);
725
726         if (stock_market[i].current_quantity > 0)
727                 sprintf (str, "%d%s", stock_market[i].current_quantity,
728                                                           unit_name[stock_market[i].units]);
729         else
730                 strcpy (str, "-");
731
732         gfx_display_text (338, y, str);
733
734         if (cmdr.current_cargo[i] > 0)
735                 sprintf (str, "%d%s", cmdr.current_cargo[i],
736                                                           unit_name[stock_market[i].units]);
737         else
738                 strcpy (str, "-");
739
740         gfx_display_text (444, y, str);
741 }
742
743
744 void highlight_stock (int i)
745 {
746         int y;
747         char str[30];
748         
749         if ((hilite_item != -1) && (hilite_item != i))
750         {
751                 y = hilite_item * 15 + 55;
752                 gfx_clear_area (2, y, 510, y + 15);
753                 display_stock_price (hilite_item);              
754         }
755
756         y = i * 15 + 55;
757         
758         gfx_draw_rectangle (2, y, 510, y + 15, GFX_COL_DARK_RED);
759         display_stock_price (i);                
760
761         hilite_item = i;
762
763         gfx_clear_text_area();
764         sprintf (str, "Cash: %d.%d", cmdr.credits / 10, cmdr.credits % 10);
765         gfx_display_text (16, 340, str);
766 }
767
768 void select_previous_stock (void)
769 {
770         if ((!docked) || (hilite_item == 0))
771                 return;
772
773         highlight_stock (hilite_item - 1);
774 }
775
776 void select_next_stock (void)
777 {
778         if ((!docked) || (hilite_item == 16))
779                 return;
780
781         highlight_stock (hilite_item + 1);
782 }
783
784
785 void buy_stock (void)
786 {
787         struct stock_item *item;
788         int cargo_held;
789         
790         if (!docked)
791                 return;
792
793         item = &stock_market[hilite_item];
794                 
795         if ((item->current_quantity == 0) ||
796             (cmdr.credits < item->current_price))
797                 return;
798
799         cargo_held = total_cargo();
800         
801         if ((item->units == TONNES) &&
802                 (cargo_held == cmdr.cargo_capacity))
803                 return;
804         
805         cmdr.current_cargo[hilite_item]++;
806         item->current_quantity--;
807         cmdr.credits -= item->current_price;    
808
809         highlight_stock (hilite_item);
810 }
811
812
813 void sell_stock (void)
814 {
815         struct stock_item *item;
816         
817         if ((!docked) || (cmdr.current_cargo[hilite_item] == 0))
818                 return;
819
820         item = &stock_market[hilite_item];
821
822         cmdr.current_cargo[hilite_item]--;
823         item->current_quantity++;
824         cmdr.credits += item->current_price;    
825
826         highlight_stock (hilite_item);
827 }
828
829
830
831 void display_market_prices (void)
832 {
833         char str[100];
834     char planet_name[16];
835         int i;
836
837         current_screen = SCR_MARKET_PRICES;
838
839         gfx_clear_display();
840
841         name_planet (planet_name, docked_planet);
842         sprintf (str, "%s MARKET PRICES", planet_name);
843         gfx_display_centre_text (10, str, 140, GFX_COL_GOLD);
844
845         gfx_draw_line (0, 36, 511, 36);
846
847         gfx_display_colour_text (16,  40, "PRODUCT", GFX_COL_GREEN_1);
848         gfx_display_colour_text (166, 40, "UNIT", GFX_COL_GREEN_1);
849         gfx_display_colour_text (246, 40, "PRICE", GFX_COL_GREEN_1);
850         gfx_display_colour_text (314, 40, "FOR SALE", GFX_COL_GREEN_1);
851         gfx_display_colour_text (420, 40, "IN HOLD", GFX_COL_GREEN_1);
852
853         for (i = 0; i < 17; i++)
854         {
855                 display_stock_price (i);
856         }
857
858         if (docked)
859         {
860                 hilite_item = -1;
861                 highlight_stock (0);
862         }
863 }
864
865
866 void display_inventory (void)
867 {
868         int i;
869         int y;
870         char str[80];
871         
872         current_screen = SCR_INVENTORY;
873
874         gfx_clear_display();
875         gfx_display_centre_text (10, "INVENTORY", 140, GFX_COL_GOLD);
876         gfx_draw_line (0, 36, 511, 36);
877         
878         sprintf (str, "%d.%d Light Years", cmdr.fuel / 10, cmdr.fuel % 10);
879         gfx_display_colour_text (16, 50, "Fuel:", GFX_COL_GREEN_1);
880         gfx_display_text (70, 50, str);
881
882         sprintf (str, "%d.%d Cr", cmdr.credits / 10, cmdr.credits % 10);
883         gfx_display_colour_text (16, 66, "Cash:", GFX_COL_GREEN_1);
884         gfx_display_text (70, 66, str);
885         
886         y = 98;
887         for (i = 0; i < 17; i++)
888         {
889                 if (cmdr.current_cargo[i] > 0)
890                 {
891                         gfx_display_text (16, y, stock_market[i].name);
892
893                         sprintf (str, "%d%s", cmdr.current_cargo[i],
894                                                           unit_name[stock_market[i].units]);
895
896                         gfx_display_text (180, y, str);
897                         y += 16;
898                 }               
899         }
900 }
901
902 /***********************************************************************************/
903
904 enum equip_types
905 {
906         EQ_FUEL, EQ_MISSILE, EQ_CARGO_BAY, EQ_ECM, EQ_FUEL_SCOOPS,
907         EQ_ESCAPE_POD, EQ_ENERGY_BOMB, EQ_ENERGY_UNIT, EQ_DOCK_COMP,
908         EQ_GAL_DRIVE, EQ_PULSE_LASER, EQ_FRONT_PULSE, EQ_REAR_PULSE,
909         EQ_LEFT_PULSE, EQ_RIGHT_PULSE, EQ_BEAM_LASER, EQ_FRONT_BEAM,
910         EQ_REAR_BEAM, EQ_LEFT_BEAM, EQ_RIGHT_BEAM, EQ_MINING_LASER,
911         EQ_FRONT_MINING, EQ_REAR_MINING, EQ_LEFT_MINING, EQ_RIGHT_MINING,
912         EQ_MILITARY_LASER, EQ_FRONT_MILITARY, EQ_REAR_MILITARY,
913         EQ_LEFT_MILITARY, EQ_RIGHT_MILITARY
914 };
915         
916                 
917
918 #define NO_OF_EQUIP_ITEMS       34
919
920 struct equip_item
921 {
922         int canbuy;
923         int y;
924         int show;
925         int level;
926         int price;
927         char *name;
928         int type;
929 };
930
931 struct equip_item equip_stock[NO_OF_EQUIP_ITEMS] =
932 {
933         {0, 0, 1, 1,     2, " Fuel",                                    EQ_FUEL},
934         {0, 0, 1, 1,   300, " Missile",                                 EQ_MISSILE},
935         {0, 0, 1, 1,  4000, " Large Cargo Bay",                 EQ_CARGO_BAY},
936         {0, 0, 1, 2,  6000, " E.C.M. System",                   EQ_ECM},
937         {0, 0, 1, 5,  5250, " Fuel Scoops",                             EQ_FUEL_SCOOPS},
938         {0, 0, 1, 6, 10000, " Escape Pod",                              EQ_ESCAPE_POD},
939         {0, 0, 1, 7,  9000, " Energy Bomb",                             EQ_ENERGY_BOMB},
940         {0, 0, 1, 8, 15000, " Extra Energy Unit",               EQ_ENERGY_UNIT},
941         {0, 0, 1, 9, 15000, " Docking Computers",               EQ_DOCK_COMP},
942         {0, 0, 1,10, 50000, " Galactic Hyperdrive",             EQ_GAL_DRIVE},
943         {0, 0, 0, 3,  4000, "+Pulse Laser",                             EQ_PULSE_LASER},
944         {0, 0, 1, 3,     0, "-Pulse Laser",                             EQ_PULSE_LASER},
945         {0, 0, 1, 3,  4000, ">Front",                                   EQ_FRONT_PULSE},
946         {0, 0, 1, 3,  4000, ">Rear",                                    EQ_REAR_PULSE},
947         {0, 0, 1, 3,  4000, ">Left",                                    EQ_LEFT_PULSE},
948         {0, 0, 1, 3,  4000, ">Right",                                   EQ_RIGHT_PULSE},
949         {0, 0, 1, 4, 10000, "+Beam Laser",                              EQ_BEAM_LASER},
950         {0, 0, 0, 4,     0, "-Beam Laser",                              EQ_BEAM_LASER},
951         {0, 0, 0, 4, 10000, ">Front",                                   EQ_FRONT_BEAM},
952         {0, 0, 0, 4, 10000, ">Rear",                                    EQ_REAR_BEAM},
953         {0, 0, 0, 4, 10000, ">Left",                                    EQ_LEFT_BEAM},
954         {0, 0, 0, 4, 10000, ">Right",                                   EQ_RIGHT_BEAM},
955         {0, 0, 1,10,  8000, "+Mining Laser",                    EQ_MINING_LASER},
956         {0, 0, 0,10,     0, "-Mining Laser",                    EQ_MINING_LASER},
957         {0, 0, 0,10,  8000, ">Front",                                   EQ_FRONT_MINING},
958         {0, 0, 0,10,  8000, ">Rear",                                    EQ_REAR_MINING},
959         {0, 0, 0,10,  8000, ">Left",                                    EQ_LEFT_MINING},
960         {0, 0, 0,10,  8000, ">Right",                                   EQ_RIGHT_MINING},
961         {0, 0, 1,10, 60000, "+Military Laser",                  EQ_MILITARY_LASER},
962         {0, 0, 0,10,     0, "-Military Laser",                  EQ_MILITARY_LASER},
963         {0, 0, 0,10, 60000, ">Front",                                   EQ_FRONT_MILITARY},
964         {0, 0, 0,10, 60000, ">Rear",                                    EQ_REAR_MILITARY},
965         {0, 0, 0,10, 60000, ">Left",                                    EQ_LEFT_MILITARY},
966         {0, 0, 0,10, 60000, ">Right",                                   EQ_RIGHT_MILITARY}
967 };
968
969
970 int equip_present (int type)
971 {
972         switch (type)
973         {
974                 case EQ_FUEL:
975                         return (cmdr.fuel >= 70);
976                 
977                 case EQ_MISSILE:
978                         return (cmdr.missiles >= 4);
979                 
980                 case EQ_CARGO_BAY:
981                         return (cmdr.cargo_capacity > 20);
982                 
983                 case EQ_ECM:
984                         return cmdr.ecm;
985                 
986                 case EQ_FUEL_SCOOPS:
987                         return cmdr.fuel_scoop;
988                 
989                 case EQ_ESCAPE_POD:
990                         return cmdr.escape_pod;
991                 
992                 case EQ_ENERGY_BOMB:
993                         return cmdr.energy_bomb;
994
995                 case EQ_ENERGY_UNIT:
996                         return cmdr.energy_unit;
997                         
998                 case EQ_DOCK_COMP:
999                         return cmdr.docking_computer;
1000                         
1001                 case EQ_GAL_DRIVE:
1002                         return cmdr.galactic_hyperdrive;
1003                         
1004                 case EQ_FRONT_PULSE:
1005                         return (cmdr.front_laser == PULSE_LASER);
1006                 
1007                 case EQ_REAR_PULSE:
1008                         return (cmdr.rear_laser == PULSE_LASER);
1009
1010                 case EQ_LEFT_PULSE:
1011                         return (cmdr.left_laser == PULSE_LASER);
1012
1013                 case EQ_RIGHT_PULSE:
1014                         return (cmdr.right_laser == PULSE_LASER);
1015
1016                 case EQ_FRONT_BEAM:
1017                         return (cmdr.front_laser == BEAM_LASER);
1018
1019                 case EQ_REAR_BEAM:
1020                         return (cmdr.rear_laser == BEAM_LASER);
1021
1022                 case EQ_LEFT_BEAM:
1023                         return (cmdr.left_laser == BEAM_LASER);
1024
1025                 case EQ_RIGHT_BEAM:
1026                         return (cmdr.right_laser == BEAM_LASER);
1027
1028                 case EQ_FRONT_MINING:
1029                         return (cmdr.front_laser == MINING_LASER);
1030
1031                 case EQ_REAR_MINING:
1032                         return (cmdr.rear_laser == MINING_LASER);
1033
1034                 case EQ_LEFT_MINING:
1035                         return (cmdr.left_laser == MINING_LASER);
1036
1037                 case EQ_RIGHT_MINING:
1038                         return (cmdr.right_laser == MINING_LASER);
1039
1040                 case EQ_FRONT_MILITARY:
1041                         return (cmdr.front_laser == MILITARY_LASER);
1042
1043                 case EQ_REAR_MILITARY:
1044                         return (cmdr.rear_laser == MILITARY_LASER);
1045
1046                 case EQ_LEFT_MILITARY:
1047                         return (cmdr.left_laser == MILITARY_LASER);
1048
1049                 case EQ_RIGHT_MILITARY:
1050                         return (cmdr.right_laser == MILITARY_LASER);
1051         }
1052
1053         return 0;
1054 }
1055
1056
1057 void display_equip_price (int i)
1058 {
1059         int x, y;
1060         int col;
1061         char str[100];
1062         
1063         y = equip_stock[i].y;
1064         if (y == 0)
1065                 return;
1066
1067         col = equip_stock[i].canbuy ? GFX_COL_WHITE : GFX_COL_GREY_1;
1068
1069         x = *(equip_stock[i].name) == '>' ? 50 : 16; 
1070
1071         gfx_display_colour_text (x, y, &equip_stock[i].name[1], col);
1072
1073         if (equip_stock[i].price != 0)
1074         {
1075                 sprintf (str, "%d.%d", equip_stock[i].price / 10, equip_stock[i].price % 10);
1076                 gfx_display_colour_text (338, y, str, col);
1077         }
1078 }
1079
1080
1081 void highlight_equip (int i)
1082 {
1083         int y;
1084         char str[30];
1085         
1086         if ((hilite_item != -1) && (hilite_item != i))
1087         {
1088                 y = equip_stock[hilite_item].y;
1089                 gfx_clear_area (2, y+1, 510, y + 15);
1090                 display_equip_price (hilite_item);              
1091         }
1092
1093         y = equip_stock[i].y;
1094         
1095         gfx_draw_rectangle (2, y+1, 510, y + 15, GFX_COL_DARK_RED);
1096         display_equip_price (i);                
1097
1098         hilite_item = i;
1099
1100         gfx_clear_text_area();
1101         sprintf (str, "Cash: %d.%d", cmdr.credits / 10, cmdr.credits % 10);
1102         gfx_display_text (16, 340, str);
1103 }
1104
1105
1106 void select_next_equip (void)
1107 {
1108         int next;
1109         int i;
1110
1111         if (hilite_item == (NO_OF_EQUIP_ITEMS - 1))
1112                 return;
1113
1114         next = hilite_item;
1115         for (i = hilite_item + 1; i < NO_OF_EQUIP_ITEMS; i++)
1116         {
1117                 if (equip_stock[i].y != 0)
1118                 {
1119                         next = i;
1120                         break;
1121                 }
1122         }
1123
1124         if (next != hilite_item)        
1125                 highlight_equip (next);
1126 }
1127
1128 void select_previous_equip (void)
1129 {
1130         int i;
1131         int prev;
1132         
1133         if (hilite_item == 0)
1134                 return;
1135         
1136         prev = hilite_item;
1137         for (i = hilite_item - 1; i >= 0; i--)
1138         {
1139                 if (equip_stock[i].y != 0)
1140                 {
1141                         prev = i;
1142                         break;
1143                 }
1144         }
1145
1146         if (prev != hilite_item)        
1147                 highlight_equip (prev);
1148 }
1149
1150
1151 void list_equip_prices (void)
1152 {
1153         int i;
1154         int y;
1155         int tech_level;
1156
1157         gfx_clear_area (2, 55, 510, 380);
1158         
1159         tech_level = current_planet_data.techlevel + 1;
1160
1161         equip_stock[0].price = (70 - cmdr.fuel) * 2;
1162         
1163         y = 55;
1164         for (i = 0; i < NO_OF_EQUIP_ITEMS; i++)
1165         {
1166             equip_stock[i].canbuy = ((equip_present (equip_stock[i].type) == 0) &&
1167                                                                  (equip_stock[i].price <= cmdr.credits));
1168         
1169                 if (equip_stock[i].show && (tech_level >= equip_stock[i].level))
1170                 {
1171                         equip_stock[i].y = y;
1172                         y += 15;
1173                 }
1174                 else
1175                         equip_stock[i].y = 0;
1176
1177                 display_equip_price (i);
1178         }
1179         
1180         i = hilite_item;
1181         hilite_item = -1;
1182         highlight_equip (i);
1183 }
1184
1185
1186 void collapse_equip_list (void)
1187 {
1188         int i;
1189         int ch;
1190         
1191         for (i = 0; i < NO_OF_EQUIP_ITEMS; i++)
1192         {
1193                 ch = *(equip_stock[i].name);
1194                 equip_stock[i].show = ((ch == ' ') || (ch == '+'));
1195         }
1196 }
1197
1198
1199 int laser_refund (int laser_type)
1200 {
1201         switch (laser_type)
1202         {
1203                 case PULSE_LASER:
1204                         return 4000;
1205                 
1206                 case BEAM_LASER:
1207                         return 10000;
1208                 
1209                 case MILITARY_LASER:
1210                         return 60000;
1211                 
1212                 case MINING_LASER:
1213                         return 8000;
1214         }
1215
1216         return 0;
1217 }
1218
1219
1220 void buy_equip (void)
1221 {
1222         int i;
1223
1224         if (equip_stock[hilite_item].name[0] == '+')
1225         {
1226                 collapse_equip_list();
1227                 equip_stock[hilite_item].show = 0;
1228                 hilite_item++;
1229                 for (i = 0; i < 5; i++)
1230                         equip_stock[hilite_item + i].show = 1;
1231                 
1232                 list_equip_prices();
1233                 return;         
1234         }
1235
1236         if (equip_stock[hilite_item].canbuy == 0)
1237                 return;
1238         
1239         switch (equip_stock[hilite_item].type)
1240         {
1241                 case EQ_FUEL:
1242                         cmdr.fuel = myship.max_fuel;
1243                         update_console();
1244                         break;
1245
1246                 case EQ_MISSILE:
1247                         cmdr.missiles++;
1248                         update_console();
1249                         break;
1250                 
1251                 case EQ_CARGO_BAY:
1252                         cmdr.cargo_capacity = 35;
1253                         break;
1254                 
1255                 case EQ_ECM:
1256                         cmdr.ecm = 1;
1257                         break;
1258                 
1259                 case EQ_FUEL_SCOOPS:
1260                         cmdr.fuel_scoop = 1;
1261                         break;
1262                 
1263                 case EQ_ESCAPE_POD:
1264                         cmdr.escape_pod = 1;
1265                         break;
1266                 
1267                 case EQ_ENERGY_BOMB:
1268                         cmdr.energy_bomb = 1;
1269                         break;
1270
1271                 case EQ_ENERGY_UNIT:
1272                         cmdr.energy_unit = 1;
1273                         break;
1274                         
1275                 case EQ_DOCK_COMP:
1276                         cmdr.docking_computer = 1;
1277                         break;
1278                         
1279                 case EQ_GAL_DRIVE:
1280                         cmdr.galactic_hyperdrive = 1;
1281                         break;
1282                         
1283                 case EQ_FRONT_PULSE:
1284                         cmdr.credits += laser_refund (cmdr.front_laser);
1285                         cmdr.front_laser = PULSE_LASER;
1286                         break;
1287                 
1288                 case EQ_REAR_PULSE:
1289                         cmdr.credits += laser_refund (cmdr.rear_laser);
1290                         cmdr.rear_laser = PULSE_LASER;
1291                         break;
1292
1293                 case EQ_LEFT_PULSE:
1294                         cmdr.credits += laser_refund (cmdr.left_laser);
1295                         cmdr.left_laser = PULSE_LASER;
1296                         break;
1297
1298                 case EQ_RIGHT_PULSE:
1299                         cmdr.credits += laser_refund (cmdr.right_laser);
1300                         cmdr.right_laser = PULSE_LASER;
1301                         break;
1302
1303                 case EQ_FRONT_BEAM:
1304                         cmdr.credits += laser_refund (cmdr.front_laser);
1305                         cmdr.front_laser = BEAM_LASER;
1306                         break;
1307
1308                 case EQ_REAR_BEAM:
1309                         cmdr.credits += laser_refund (cmdr.rear_laser);
1310                         cmdr.rear_laser = BEAM_LASER;
1311                         break;
1312
1313                 case EQ_LEFT_BEAM:
1314                         cmdr.credits += laser_refund (cmdr.left_laser);
1315                         cmdr.left_laser = BEAM_LASER;
1316                         break;
1317
1318                 case EQ_RIGHT_BEAM:
1319                         cmdr.credits += laser_refund (cmdr.right_laser);
1320                         cmdr.right_laser = BEAM_LASER;
1321                         break;
1322
1323                 case EQ_FRONT_MINING:
1324                         cmdr.credits += laser_refund (cmdr.front_laser);
1325                         cmdr.front_laser = MINING_LASER;
1326                         break;
1327
1328                 case EQ_REAR_MINING:
1329                         cmdr.credits += laser_refund (cmdr.rear_laser);
1330                         cmdr.rear_laser = MINING_LASER;
1331                         break;
1332
1333                 case EQ_LEFT_MINING:
1334                         cmdr.credits += laser_refund (cmdr.left_laser);
1335                         cmdr.left_laser = MINING_LASER;
1336                         break;
1337
1338                 case EQ_RIGHT_MINING:
1339                         cmdr.credits += laser_refund (cmdr.right_laser);
1340                         cmdr.right_laser = MINING_LASER;
1341                         break;
1342
1343                 case EQ_FRONT_MILITARY:
1344                         cmdr.credits += laser_refund (cmdr.front_laser);
1345                         cmdr.front_laser = MILITARY_LASER;
1346                         break;
1347
1348                 case EQ_REAR_MILITARY:
1349                         cmdr.credits += laser_refund (cmdr.rear_laser);
1350                         cmdr.rear_laser = MILITARY_LASER;
1351                         break;
1352
1353                 case EQ_LEFT_MILITARY:
1354                         cmdr.credits += laser_refund (cmdr.left_laser);
1355                         cmdr.left_laser = MILITARY_LASER;
1356                         break;
1357
1358                 case EQ_RIGHT_MILITARY:
1359                         cmdr.credits += laser_refund (cmdr.right_laser);
1360                         cmdr.right_laser = MILITARY_LASER;
1361                         break;
1362         }
1363
1364         cmdr.credits -= equip_stock[hilite_item].price;
1365         list_equip_prices();
1366 }
1367
1368
1369 void equip_ship (void)
1370 {
1371         current_screen = SCR_EQUIP_SHIP;
1372
1373         gfx_clear_display();
1374         gfx_display_centre_text (10, "EQUIP SHIP", 140, GFX_COL_GOLD);
1375         gfx_draw_line (0, 36, 511, 36);
1376
1377         collapse_equip_list();
1378         
1379         hilite_item = 0;
1380         
1381         list_equip_prices();
1382 }