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