1 /* laser.c - a mining laser device for the moon-buggy
2  *
3  * Copyright 1999  Jochen Voss.  */
4 
5 static const  char  rcsid[] = "$Id: laser.c 4839 2003-04-13 16:50:02Z voss $";
6 
7 #ifdef HAVE_CONFIG_H
8 #include <config.h>
9 #endif
10 
11 #include "moon-buggy.h"
12 #include "darray.h"
13 
14 
15 enum beam_state { bs_START, bs_RUN, bs_CLOUD };
16 
17 struct beam {
18   enum beam_state  state;
19   int  left, right, y;
20   int  count;
21 };
22 
23 static  struct {
24   struct beam **data;
25   int  slots, used;
26 } beam_table;
27 
28 
29 static void
beam_handler(game_time t,void * client_data)30 beam_handler (game_time t, void *client_data)
31 {
32   struct beam *b = client_data;
33   int  i, x;
34 
35   switch (b->state) {
36   case bs_START:
37     if (b->y == 5 && (x = meteor_laser_hit (b->left, b->right))) {
38       b->count = 0;
39       b->left = x;
40       if (b->left > car_x - 2)  b->left = car_x - 2;
41     }
42     wmove (moon, LINES-b->y, b->left);
43     for (i=0; i<b->right-b->left; ++i)  waddch (moon, '-');
44     b->state = bs_RUN;
45     add_event (t+TICK(0.25), beam_handler, client_data);
46     break;
47   case bs_RUN:
48     if (b->count > 0) {
49       b->left -= 1;
50       b->right -= 1;
51       mvwaddch (moon, LINES-b->y, b->left, '-');
52       mvwaddch (moon, LINES-b->y, b->right, ' ');
53       if (b->y == 5 && meteor_laser_hit (b->left, b->right)) {
54 	b->count = 0;
55       } else {
56 	b->count -= 1;
57       }
58       add_event (t+TICK(0.25), beam_handler, client_data);
59     } else {
60       wmove (moon, LINES-b->y, b->left);
61       for (i=0; i<2; ++i)  waddch (moon, '*');
62       for (i=2; i<b->right-b->left; ++i)  waddch (moon, ' ');
63       b->right = b->left+2;
64       b->state = bs_CLOUD;
65       b->count = 3;
66       if (b->right + b->count >= car_x)  b->count = car_x - b->right - 1;
67       add_event (t+TICK(1), beam_handler, client_data);
68     }
69     break;
70   case bs_CLOUD:
71     if (b->count > 1) {
72       mvwaddch (moon, LINES-b->y, b->left, ' ');
73       mvwaddch (moon, LINES-b->y, b->right, '*');
74       b->left += 1;
75       b->right += 1;
76       b->count -= 1;
77       add_event (t+TICK(1), beam_handler, client_data);
78     } else if (b->count > 0) {
79       mvwaddch (moon, LINES-b->y, b->left, ' ');
80       b->left += 1;
81       b->right += 1;
82       for (i=b->left; i<b->right; ++i)  mvwaddch (moon, LINES-b->y, i, '.');
83       b->count -= 1;
84       add_event (t+TICK(1), beam_handler, client_data);
85     } else {
86       wmove (moon, LINES-b->y, b->left);
87       for (i=0; i<2; ++i)  waddch (moon, ' ');
88       DA_REMOVE_VALUE (beam_table, struct beam *, b);
89       free (b);
90     }
91     break;
92   }
93   wnoutrefresh (moon);
94 }
95 
96 void
fire_laser(double t)97 fire_laser (double t)
98 {
99   struct beam *b;
100 
101   if (! beam_table.data)  DA_INIT (beam_table, struct beam *);
102   b = xmalloc (sizeof (struct beam));
103   b->state = bs_START;
104   b->count = 40;
105   b->left = car_x-8;
106   b->right = car_x;
107   b->y = car_y;
108   DA_ADD (beam_table, struct beam *, b);
109   add_event (t+TICK(0.25), beam_handler, b);
110   adjust_score (-1);
111 }
112 
113 void
extinguish_laser(void)114 extinguish_laser (void)
115 /* Clear all laser beams from the screen.  */
116 {
117   int  j;
118 
119   remove_event (beam_handler);
120   for (j=0; j<beam_table.used; ++j) {
121     struct beam *b = beam_table.data[j];
122     int  i;
123 
124     for (i=b->left; i<b->right; ++i)  mvwaddch (moon, LINES-b->y, i, ' ');
125     free (b);
126   }
127   DA_CLEAR (beam_table);
128   wnoutrefresh (moon);
129 }
130 
131 int
laser_hit(int x)132 laser_hit (int x)
133 /* Return true, if a beam covers location X of the baseline.
134  * These beams hit a meteor and stop immediately.  */
135 {
136   int  j;
137   int  res = 0;
138 
139   for (j=0; j<beam_table.used; ++j) {
140     struct beam *b = beam_table.data[j];
141     if (b->y == 5 && b->left >= x && b->right < x) {
142       if (b->state < bs_CLOUD)  b->count = 0;
143       res = 1;
144     }
145   }
146   return  res;
147 }
148 
149 void
resize_laser(void)150 resize_laser (void)
151 /* Clear all laser beams from the screen.  */
152 {
153   int  j;
154 
155   remove_event (beam_handler);
156   for (j=0; j<beam_table.used; ++j)  free (beam_table.data[j]);
157   DA_CLEAR (beam_table);
158 }
159