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