1 /* meteor.c - stones on the moon to shoot at
2  *
3  * Copyright 1999, 2000  Jochen Voss.  */
4 
5 static const  char  rcsid[] = "$Id: meteor.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 meteor_state { ms_START, ms_BIG, ms_MEDIUM, ms_SMALL };
16 static char  m_image [] = { 'O', 'O', 'o', ',' };
17 
18 struct meteor {
19   enum meteor_state  state;
20   int  x;
21 };
22 
23 static  struct {
24   struct meteor **data;
25   int  slots, used;
26 } meteor_table;
27 
28 
29 static void
score_meteor(struct meteor * m)30 score_meteor (struct meteor *m)
31 {
32   adjust_score (13);
33   bonus[m->x] -= 20;
34 }
35 
36 static int
scroll_one_meteor(struct meteor * m)37 scroll_one_meteor (struct meteor *m)
38 /* Move the meteor *M along with the ground.
39  * Check for collisions with the car or with laser beams.
40  * Return 1 iff the meteor should be removed from the list.  */
41 {
42   if (m->state == ms_START) {
43     m->state = ms_BIG;
44   } else {
45     mvwaddch (moon, BASELINE, m->x, ' ');
46   }
47 
48   m->x += 1;
49   if (m->x >= COLS )  return 1;
50 
51   if (laser_hit (m->x)) {
52     m->state += 1;
53     if (m->state > ms_SMALL) {
54       score_meteor (m);
55       return  1;
56     }
57   }
58   if (car_meteor_hit (m->x))  return  1;
59 
60   mvwaddch (moon, BASELINE, m->x, m_image[m->state]);
61   return  0;
62 }
63 
64 void
scroll_meteors(void)65 scroll_meteors (void)
66 /* Move the meteors along with the ground.
67  * Handle collisions with the car or with laser beams. */
68 {
69   int  j;
70 
71   if (meteor_table.used > 0)  wnoutrefresh (moon);
72   for (j=meteor_table.used-1; j>=0; --j) {
73     struct meteor *m = meteor_table.data[j];
74     int  res;
75 
76     res = scroll_one_meteor (m);
77     if (res) {
78       DA_REMOVE (meteor_table, struct meteor *, j);
79       free (m);
80     }
81   }
82 }
83 
84 void
place_meteor(void)85 place_meteor (void)
86 /* Place a new meteor on the ground.  */
87 {
88   struct meteor *m;
89 
90   if (! meteor_table.data)  DA_INIT (meteor_table, struct meteor *);
91   m = xmalloc (sizeof (struct meteor));
92   m->state = ms_START;
93   m->x = 0;
94   bonus[0] += 20;
95   DA_ADD (meteor_table, struct meteor *, m);
96 }
97 
98 void
remove_meteors(void)99 remove_meteors (void)
100 /* Remove all meteors from the ground.
101  * Free any resources used by the internal representation.  */
102 {
103   int  j;
104 
105   if (meteor_table.used > 0)  wnoutrefresh (moon);
106   for (j=0; j<meteor_table.used; ++j) {
107     struct meteor *m = meteor_table.data[j];
108     mvwaddch (moon, BASELINE, m->x, ' ');
109     free (m);
110   }
111   DA_CLEAR (meteor_table);
112 }
113 
114 int
meteor_laser_hit(int x0,int x1)115 meteor_laser_hit (int x0, int x1)
116 /* Check for meteors at positions >=x0 and <x1.
117  * All these are hit by the laser.
118  * Return true, if there are any hits.  */
119 {
120   int  j;
121 
122   for (j=0; j<meteor_table.used; ++j) {
123     struct meteor *m = meteor_table.data[j];
124     if (m->x >= x0 && m->x < x1) {
125       int  x = m->x;
126 
127       m->state += 1;
128       wnoutrefresh (moon);
129       if (m->state > ms_SMALL) {
130 	mvwaddch (moon, BASELINE, m->x, ' ');
131 	score_meteor (m);
132 	remove_client_data (m);
133 	DA_REMOVE_VALUE (meteor_table, struct meteor *, m);
134 	free (m);
135       } else {
136 	mvwaddch (moon, BASELINE, m->x, m_image[m->state]);
137       }
138       return  x;
139     }
140   }
141   return  0;
142 }
143 
144 int
meteor_car_hit(int x0,int x1)145 meteor_car_hit (int x0, int x1)
146 /* Check for meteors at positions >=x0 and <x1.
147  * All these are destroyed by the landing car.
148  * Return true, if there are any hits.  */
149 {
150   int  j;
151   int  res = 0;
152 
153   for (j=meteor_table.used-1; j>=0; --j) {
154     struct meteor *m = meteor_table.data[j];
155     if (m->x >= x0 && m->x < x1) {
156       mvwaddch (moon, BASELINE, m->x, ' ');
157       remove_client_data (m);
158       DA_REMOVE_VALUE (meteor_table, struct meteor *, m);
159       free (m);
160       res = 1;
161     }
162   }
163   if (res)  wnoutrefresh (moon);
164   return  res;
165 }
166 
167 void
resize_meteors(void)168 resize_meteors (void)
169 /* Silently remove all meteors, which are no longer visible.  */
170 {
171   int  j;
172 
173   j = 0;
174   while (j<meteor_table.used) {
175     struct meteor *m = meteor_table.data[j];
176     if (m->x >= COLS) {
177       remove_client_data (m);
178       DA_REMOVE_VALUE (meteor_table, struct meteor *, m);
179       free (m);
180     } else {
181       ++j;
182     }
183   }
184 }
185