1 /*
2 XorGramana Copyright 2009 James W. Morris, james@jwm-art.net
3
4 This file is part of XorGramana.
5
6 XorGramana is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 XorGramana is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with XorGramana. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "actions.h"
21 #include "map.h"
22 #include "gfx.h"
23 #include "options.h"
24
25 #include <stdlib.h>
26
27 struct xor_action actions[ICON_XXX]=
28 {
29 {/* FLOOR */ MVI_NONE, CT_PASS, MV_NONE, MV_NONE },
30 {/* WALL */ MVI_NONE, CT_BLOCK, MV_NONE, MV_NONE },
31 {/* H_FIELD */ MVI_NONE, CT_FILTER, MV_NONE, MV_HORIZ },
32 {/* V_FIELD */ MVI_NONE, CT_FILTER, MV_NONE, MV_VERT },
33 {/* PLAYER0 */ MVI_PLAYER, CT_BLOCK, MV_ANY, MV_NONE },
34 {/* PLAYER1 */ MVI_PLAYER, CT_BLOCK, MV_ANY, MV_NONE },
35 {/* MAP */ MVI_NONE, CT_PICKUP, MV_NONE, MV_NONE },
36 {/* TELEPORT*/ MVI_NONE, CT_TELEPORT, MV_NONE, MV_NONE },
37 {/* EXIT_CLOSED */MVI_NONE, CT_BLOCK, MV_NONE, MV_NONE },
38 {/* MASK */ MVI_NONE, CT_PICKUP, MV_NONE, MV_NONE },
39 {/* DOT */ MVI_NONE, CT_BLOCK, MV_NONE, MV_NONE },
40 {/* BLANK */ MVI_NONE, CT_BLOCK, MV_NONE, MV_NONE },
41 /* the following will have behavioural indicators overlaid upon them */
42 {/* A (!fish)*/ MVI_GRAVITY, CT_PUSH, MV_UP, MV_HORIZ },
43 {/* B (flip-dpq)*/MVI_NONE, CT_PUSH|CT_FLIP, MV_NONE, MV_ANY },
44 {/* C (STATIC)*/ MVI_NONE, CT_BLOCK, MV_NONE, MV_NONE },
45 {/* D (flip-bpq)*/MVI_NONE, CT_PUSH|CT_FLIP, MV_NONE, MV_ANY },
46 {/* E (v-doll)*/ MVI_NONE, CT_HARDPUSH, MV_NONE, MV_VERT },
47 {/* F (h-doll)*/ MVI_NONE, CT_HARDPUSH, MV_NONE, MV_HORIZ },
48 {/* G (doll)*/ MVI_NONE, CT_HARDPUSH, MV_NONE, MV_ANY },
49 {/* H (h-bomb)*/ MVI_GRAVITY, CT_PUSH|CT_EXPLODE, MV_DOWN, MV_HORIZ },
50 {/* I (STATIC)*/ MVI_NONE, CT_BLOCK, MV_NONE, MV_NONE },
51 {/* J (flip-j)*/ MVI_NONE, CT_PUSH|CT_FLIP, MV_NONE, MV_HORIZ },
52 {/* K (chick)*/ MVI_GRAVITY, CT_PUSH, MV_LEFT, MV_VERT },
53 {/* L (flip-j)*/ MVI_NONE, CT_PUSH|CT_FLIP, MV_NONE, MV_VERT },
54 {/* M (eeek)*/ MVI_GRAVITY, CT_HARDPUSH, MV_LEFT, MV_VERT },
55 {/* N (eeek)*/ MVI_GRAVITY, CT_HARDPUSH, MV_RIGHT, MV_VERT },
56 {/* O (!h-bomb)*/ MVI_GRAVITY, CT_PUSH|CT_EXPLODE, MV_UP, MV_HORIZ },
57 {/* P (flip-bdq)*/MVI_NONE, CT_PUSH|CT_FLIP, MV_NONE, MV_ANY },
58 {/* Q (flip-bdp)*/MVI_NONE, CT_PUSH|CT_FLIP, MV_NONE, MV_ANY },
59 {/* R (eek)*/ MVI_GRAVITY, CT_HARDPUSH, MV_UP, MV_HORIZ },
60 {/* S (flip-z)*/ MVI_NONE, CT_PUSH|CT_FLIP, MV_NONE, MV_HORIZ },
61 {/* T (!v-bomb)*/ MVI_GRAVITY, CT_PUSH|CT_EXPLODE, MV_RIGHT, MV_VERT, },
62 {/* U (eek)*/ MVI_GRAVITY, CT_HARDPUSH, MV_DOWN, MV_HORIZ },
63 {/* V (fish)*/ MVI_GRAVITY, CT_PUSH, MV_DOWN, MV_HORIZ },
64 {/* W (!chick)*/ MVI_GRAVITY, CT_PUSH, MV_RIGHT, MV_VERT },
65 {/* X (v-bomb)*/ MVI_GRAVITY, CT_PUSH|CT_EXPLODE, MV_LEFT, MV_VERT },
66 {/* Y (switch)*/ MVI_NONE, CT_PICKUP|CT_SWITCH,MV_NONE, MV_NONE },
67 {/* Z (flip-s)*/ MVI_NONE, CT_PUSH|CT_FLIP, MV_NONE, MV_VERT },
68 {/* 0 */ MVI_NONE, 0,0,0},
69 {/* 1 */ MVI_NONE, 0,0,0}, /* for these numerical icons no behaviour */
70 {/* 2 */ MVI_NONE, 0,0,0}, /* is yet defined - but will be sooner or */
71 {/* 3 */ MVI_NONE, 0,0,0}, /* later.. */
72 {/* 4 */ MVI_NONE, 0,0,0},
73 {/* 5 */ MVI_NONE, 0,0,0},
74 {/* 6 */ MVI_NONE, 0,0,0},
75 {/* 7 */ MVI_NONE, 0,0,0},
76 {/* 8 */ MVI_NONE, 0,0,0},
77 {/* 9 */ MVI_NONE, 0,0,0},
78 /* the open exit cannot be specified in map file */
79 {/* OPEN_EXIT */ MVI_NONE, CT_EXIT, MV_NONE, MV_NONE },
80 /* the following are not ever appearing in map so have no defined behaviour */
81 {/*space trans*/ 0,0,0,0},
82 {/*space opaque*/ 0,0,0,0},
83 {/*explosion1*/ 0,0,0,0},
84 {/*explosion2*/ 0,0,0,0},
85 {/*explosion3*/ 0,0,0,0},
86 {/*explosion4*/ 0,0,0,0},
87 {/*explosion5*/ 0,0,0,0},
88 {/*line_l*/ 0,0,0,0},
89 {/*line_r*/ 0,0,0,0},
90 {/*line_t*/ 0,0,0,0},
91 {/*line_b*/ 0,0,0,0},
92 {/*line_tl*/ 0,0,0,0},
93 {/*line_tr*/ 0,0,0,0},
94 {/*line_bl*/ 0,0,0,0},
95 {/*line_br*/ 0,0,0,0},
96 {/*loaded_xxx (MARKER) */ 0,0,0,0},
97 /* the following are generated wall icons with edging, (set to behave as wall)*/
98 {/*edge_t*/ MVI_NONE, CT_BLOCK, MV_NONE, MV_NONE },
99 {/*edge_b*/ MVI_NONE, CT_BLOCK, MV_NONE, MV_NONE },
100 {/*edge_l*/ MVI_NONE, CT_BLOCK, MV_NONE, MV_NONE },
101 {/*edge_r*/ MVI_NONE, CT_BLOCK, MV_NONE, MV_NONE },
102 {/*edge_tb*/ MVI_NONE, CT_BLOCK, MV_NONE, MV_NONE },
103 {/*edge_lr*/ MVI_NONE, CT_BLOCK, MV_NONE, MV_NONE },
104 {/*edge_tl*/ MVI_NONE, CT_BLOCK, MV_NONE, MV_NONE },
105 {/*edge_tr*/ MVI_NONE, CT_BLOCK, MV_NONE, MV_NONE },
106 {/*edge_bl*/ MVI_NONE, CT_BLOCK, MV_NONE, MV_NONE },
107 {/*edge_br*/ MVI_NONE, CT_BLOCK, MV_NONE, MV_NONE },
108 {/*edge_tbl*/ MVI_NONE, CT_BLOCK, MV_NONE, MV_NONE },
109 {/*edge_tbr*/ MVI_NONE, CT_BLOCK, MV_NONE, MV_NONE },
110 {/*edge_tlr*/ MVI_NONE, CT_BLOCK, MV_NONE, MV_NONE },
111 {/*edge_blr*/ MVI_NONE, CT_BLOCK, MV_NONE, MV_NONE },
112 {/*edge_tblr*/ MVI_NONE, CT_BLOCK, MV_NONE, MV_NONE }
113 };
114
115
icons_init_overlays()116 void icons_init_overlays()
117 {
118 int i;
119 int o;
120 for(i=ICON_A;i<=ICON_9;i++){
121 #ifdef ICON_DEBUG
122 printf("generating icon overlay for %d(%s)\n",i,icon_details[i].fname);
123 #endif
124 if(actions[i].mvini==MVI_GRAVITY){
125 icons_with_indicators[i]=icon_duplicate(icons[i],TRUE,0,0,0);
126 switch(actions[i].mvi_dir){
127 case MV_LEFT: o=DIRIND_GRAV_L; break;
128 case MV_RIGHT: o=DIRIND_GRAV_R; break;
129 case MV_UP: o=DIRIND_GRAV_U; break;
130 case MV_DOWN: o=DIRIND_GRAV_D; break;
131 }
132 overlay_image(icons_with_indicators[i],indicators[o],0,0);
133 }
134 if(actions[i].cont&CT_PUSH){
135 if(!icons_with_indicators[i])
136 icons_with_indicators[i]=icon_duplicate(icons[i],TRUE,0,0,0);
137 if(actions[i].cont_dir&MV_LEFT)
138 overlay_image(icons_with_indicators[i],indicators[DIRIND_PUSH_L],0,0);
139 if(actions[i].cont_dir&MV_RIGHT)
140 overlay_image(icons_with_indicators[i],indicators[DIRIND_PUSH_R],0,0);
141 if(actions[i].cont_dir&MV_UP)
142 overlay_image(icons_with_indicators[i],indicators[DIRIND_PUSH_U],0,0);
143 if(actions[i].cont_dir&MV_DOWN)
144 overlay_image(icons_with_indicators[i],indicators[DIRIND_PUSH_D],0,0);
145 }
146 if(actions[i].cont&CT_HARDPUSH){
147 if(!icons_with_indicators[i])
148 icons_with_indicators[i]=icon_duplicate(icons[i],TRUE,0,0,0);
149 if(actions[i].cont_dir&MV_LEFT)
150 overlay_image(icons_with_indicators[i],indicators[DIRIND_HARDPUSH_L],0,0);
151 if(actions[i].cont_dir&MV_RIGHT)
152 overlay_image(icons_with_indicators[i],indicators[DIRIND_HARDPUSH_R],0,0);
153 if(actions[i].cont_dir&MV_UP)
154 overlay_image(icons_with_indicators[i],indicators[DIRIND_HARDPUSH_U],0,0);
155 if(actions[i].cont_dir&MV_DOWN)
156 overlay_image(icons_with_indicators[i],indicators[DIRIND_HARDPUSH_D],0,0);
157 }
158 if(actions[i].cont&CT_EXPLODE){
159 if(!icons_with_indicators[i])
160 icons_with_indicators[i]=icon_duplicate(icons[i],TRUE,0,0,0);
161 if(actions[i].cont_dir&MV_HORIZ)
162 overlay_image(icons_with_indicators[i],indicators[DIRIND_EXPLODE_H],0,0);
163 if(actions[i].cont_dir&MV_VERT)
164 overlay_image(icons_with_indicators[i],indicators[DIRIND_EXPLODE_V],0,0);
165 }
166 }
167 }
168
create_xor_move(xy_t x,xy_t y,su_t move)169 struct xor_move* create_xor_move(xy_t x, xy_t y, su_t move)
170 {
171 struct xor_move* xmv;
172 if(!(xmv=malloc(sizeof(struct xor_move))))
173 return 0;
174 xmv->from_obj=map->data[y][x];
175 xmv->from_x=x;
176 xmv->from_y=y;
177 xmv->dir=move;
178 xmv->to_x=xmv->to_y=0;
179 xmv->up=xmv->down=xmv->right=xmv->left=0;
180 xmv->moves_count=0;
181 return xmv;
182 }
183
184 /*
185 the following two functions are a bit cyclical in their
186 operation so think twice if you spot something seeming
187 at first glance nonsensical. (ie james morris, you/me,
188 we know we have a habbit of scanning our code and
189 thinking wtf!?!? and then editing without realising...
190 and we hate these comments which now seem obvious and
191 so untidy...
192 */
193 #include "player.h"
194
create_gravity_chain_xydir(xy_t x,xy_t y,su_t dir)195 struct xor_move* create_gravity_chain_xydir(xy_t x, xy_t y, su_t dir)
196 {
197 struct xor_move* head=0;
198 struct xor_move* xmv=0;
199 struct xor_move* tmp=0;
200 int icon;
201 do{
202 icon=map->data[y][x];
203 if(actions[icon].mvini!=MVI_GRAVITY)
204 return head;
205 if(actions[icon].mvi_dir!=dir)
206 return head;
207 if(!(xmv=malloc(sizeof(struct xor_move))))
208 return head;
209 if(!head)
210 head=xmv;
211 if(tmp){
212 switch(dir){
213 case MV_UP: tmp->down=xmv; break;
214 case MV_DOWN: tmp->up=xmv; break;
215 case MV_LEFT: tmp->right=xmv; break;
216 case MV_RIGHT: tmp->left=xmv; break;
217 }
218 }
219 xmv->from_obj=icon;
220 xmv->from_x=x;
221 xmv->from_y=y;
222 xmv->dir=dir;
223 xmv->to_x=xmv->to_y=0;
224 xmv->up=xmv->down=xmv->right=xmv->left=0;
225 xmv->moves_count=0;
226 tmp=xmv;
227 switch(dir){
228 case MV_UP: y++; break;
229 case MV_DOWN: y--; break;
230 case MV_LEFT: x++; break;
231 case MV_RIGHT: x--; break;
232 }
233 }while(TRUE);
234 return head;
235 }
236
create_gravity_chain(struct xor_move * xmv)237 struct xor_move* create_gravity_chain(struct xor_move* xmv)
238 {
239 struct xor_move* head=0;
240 struct xor_move* tmp=0;
241 struct xor_move* oxmv=xmv;
242 su_t icon;
243 xy_t x, y;
244 su_t dir;
245 x=xmv->from_x;
246 y=xmv->from_y;
247 dir=xmv->dir;
248 do{
249 icon=map->data[y][x];
250 if(actions[icon].mvini!=MVI_GRAVITY){
251 if(xmv!=oxmv)
252 free(xmv);
253 return head;
254 }
255 if(actions[icon].mvi_dir!=dir){
256 if(xmv!=oxmv)
257 free(xmv);
258 return head;
259 }
260 if(!head)
261 head=xmv;
262 if(tmp){
263 switch(dir){
264 case MV_UP: tmp->down=xmv; break;
265 case MV_DOWN: tmp->up=xmv; break;
266 case MV_LEFT: tmp->right=xmv; break;
267 case MV_RIGHT: tmp->left=xmv; break;
268 }
269 }
270 xmv->from_obj=icon; /* these are redundant */
271 xmv->from_x=x; /* on the first pass */
272 xmv->from_y=y; /* oh well... */
273 xmv->dir=dir;
274 xmv->to_x=xmv->to_y=0;
275 xmv->up=xmv->down=xmv->right=xmv->left=0;
276 xmv->moves_count=0;
277 tmp=xmv;
278 switch(dir){
279 case MV_UP: y++; break;
280 case MV_DOWN: y--; break;
281 case MV_LEFT: x++; break;
282 case MV_RIGHT: x--; break;
283 }
284 if(!(xmv=malloc(sizeof(struct xor_move))))
285 return head;
286 }while(TRUE);
287 return head;
288 }
289
destroy_gravity_chain(struct xor_move * xmv)290 void destroy_gravity_chain(struct xor_move* xmv)
291 {
292 struct xor_move* tmp;
293 while(xmv){
294 tmp=xmv;
295 switch(xmv->dir){
296 case MV_UP: xmv=xmv->down; break;
297 case MV_DOWN: xmv=xmv->up; break;
298 case MV_LEFT: xmv=xmv->right; break;
299 case MV_RIGHT: xmv=xmv->left; break;
300 }
301 free(tmp);
302 }
303 }
304
bomb_type(su_t icon)305 su_t bomb_type(su_t icon)
306 {
307 if(actions[icon].cont&CT_EXPLODE)
308 return actions[icon].cont_dir;
309 return MV_NONE;
310 }
311