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 #include "moves.h"
20 #include "game_display.h"
21 #include "explode.h"
22 #include "options.h"
23 #include "map.h"
24
25 #include <stdlib.h>
26
init_unsupported()27 void init_unsupported()
28 {
29 xy_t x,y;
30 xy_t nx,ny;
31 su_t i,ni;
32 su_t dir;
33 struct xor_move* xmv;
34 #ifdef MOVE_DEBUG
35 printf("init_unsupported()/*check for unsupported gravitating objects*/\n");
36 #endif
37 xmvlist_create();
38 for(y=1;y<map->height;y++){
39 for(x=1;x<map->width;x++){
40 i=map->data[y][x];
41 if(actions[i].mvini==MVI_GRAVITY){
42 nx=0;ny=0;
43 switch((dir=actions[i].mvi_dir)){
44 case MV_UP:
45 nx=x;ny=y-1;
46 break;
47 case MV_DOWN:
48 nx=x;ny=y+1;
49 break;
50 case MV_LEFT:
51 nx=x-1;ny=y;
52 break;
53 case MV_RIGHT:
54 nx=x+1;ny=y;
55 break;
56 default:
57 break;
58 }
59 if(nx>0&&ny>0&&nx<map->width&&ny<map->height){
60 ni=map->data[ny][nx];
61 xmv=create_xor_move(x,y,dir);
62 if(move_object_init(xmv)==CT_PASS){
63 if((create_gravity_chain(xmv))){
64 xmvlist_append_xor_move(xmv);
65 #ifdef MAP_DEBUG
66 printf("reporting:Unsupported object in map x:%d y:%d char:%c\n",
67 x,y,icon_details[xmv->from_obj].mapchar);
68 #endif
69 }
70 else
71 free(xmv);
72 }
73 else free(xmv);
74 }
75 }
76 }
77 }
78 if(xmvlist_first()){
79 if(!player.replay){
80 gfx_message("Get Ready");
81 game_win_display();
82 }
83 move_gravity_process();
84 }
85 xmvlist_destroy();
86 }
87
move_object_init(struct xor_move * move)88 ct_t move_object_init(struct xor_move* move)
89 {
90 ct_t cont;
91 move->to_x=move->from_x;
92 move->to_y=move->from_y;
93 #ifdef MOVE_DEBUG
94 printf("move_object_init(xor_move* %lx)\n",(unsigned long)move);
95 #endif
96 switch(move->dir){
97 case MV_LEFT: move->to_x--; break;
98 case MV_RIGHT: move->to_x++; break;
99 case MV_UP: move->to_y--; break;
100 case MV_DOWN: move->to_y++; break;
101 default:
102 fprintf(stderr,
103 "Invalid movement direction error! move:%d\n",move->dir);
104 return CT_BLOCK;
105 }
106 move->from_obj=map->data[move->from_y][move->from_x];
107 move->to_obj=map->data[move->to_y][move->to_x];
108 cont=actions[move->to_obj].cont;
109 /* ------------------------------------------ */
110 /* conditions apply both to player and object */
111 if(cont==CT_BLOCK||cont==CT_PASS)
112 return cont;
113 if(actions[move->from_obj].cont&CT_HARDPUSH){
114 if(move->dir&actions[move->from_obj].cont_dir){
115 /*fprintf(stderr,"hardpush causing blockage..\n");*/
116 return CT_BLOCK;
117 }
118 }
119 if(cont==CT_FILTER){
120 if(actions[move->to_obj].cont_dir&move->dir)
121 return CT_PASS;
122 return CT_BLOCK;
123 }
124 /* -------------------------------- */
125 /* conditions which apply to player */
126 if(actions[move->from_obj].mvini&MVI_PLAYER){
127 if(cont&CT_PUSH){
128 if(actions[move->to_obj].cont_dir&move->dir)
129 return CT_PUSH;
130 else
131 return CT_BLOCK;
132 }
133 if(cont&CT_PICKUP||cont&CT_TELEPORT||cont&CT_EXIT)
134 return cont;
135 if(cont&CT_HARDPUSH){
136 if(actions[move->to_obj].cont_dir&move->dir)
137 return CT_HARDPUSH;
138 else
139 return CT_BLOCK;
140 }
141 if(cont&CT_PUSH){
142 if(actions[move->to_obj].cont_dir&move->dir)
143 return CT_PUSH;
144 else
145 return CT_BLOCK;
146 }
147 return CT_ERROR;
148 }
149 /* -------------------------------- */
150 /* conditions which apply to object */
151 if(cont&CT_EXPLODE)
152 return CT_EXPLODE;
153 if(cont&CT_FLIP)
154 return CT_FLIP;
155 return CT_BLOCK;
156 }
157
move_gravity_process()158 void move_gravity_process()
159 {
160 struct xor_move* xmv=0;
161 struct xor_move* tmp=0;
162 struct xor_move* cmv=0;
163 struct xor_move* cmv_next=0;
164 struct xmv_link* tmplnk=0;
165 ct_t cont;
166 xy_t tmpx,tmpy;
167 unsigned int flimit=SDL_GetTicks()+TICK_COUNT;
168 #ifdef MOVE_DEBUG
169 printf("\nmove_gravity_process()\n");
170 #endif
171 /*
172 rpause.tv_sec=0;
173 if(player.replay)
174 rpause.tv_nsec=options_replay_speed(options->replay_speed);
175 else
176 rpause.tv_nsec=20000000L;
177 */
178 xmvlist_first();
179 while(xmvlist->current){
180 xmv=xmvlist->current->xmv;
181 cmv=xmv;
182 #ifdef MOVE_DEBUG
183 printf("xmvlist->current=%lx->xmv=%lx\n",
184 (unsigned long)xmvlist->current,(unsigned long)xmv);
185 #endif
186 while(cmv){
187 delay(flimit);
188 flimit=SDL_GetTicks()+TICK_COUNT;
189 #ifdef MOVE_DEBUG
190 printf("mv_grv_proc:\n\t*(%lx)cmv->from_x:%d,from_y:%d,from_obj:%s\n",
191 (unsigned long)cmv,cmv->from_x,cmv->from_y,
192 icon_details[cmv->from_obj].fname);
193 #endif
194 switch(cmv->dir){
195 case MV_UP: cmv_next=cmv->down; break;
196 case MV_DOWN: cmv_next=cmv->up; break;
197 case MV_LEFT: cmv_next=cmv->right;break;
198 case MV_RIGHT: cmv_next=cmv->left; break;
199 default:
200 break;
201 }
202 cont=move_object_init(cmv);
203 if(actions[cmv->to_obj].mvini==MVI_PLAYER){
204 if(cmv->moves_count>0){
205 player_death(cmv->to_obj);
206 cont=CT_PASS;
207 }
208 }
209 if(cont&CT_FLIP){
210 if(cmv->moves_count>0){
211 #ifdef MOVE_DEBUG
212 printf("grav proc flipping..\n");
213 #endif
214 game_win_icon_display(
215 cmv->to_x,cmv->to_y,
216 ( map->data[cmv->to_y][cmv->to_x]=
217 flip(cmv->to_obj,cmv->dir) ) );
218 cont=CT_BLOCK;
219 }
220 }
221 if(cont&CT_EXPLODE){
222 #ifdef MOVE_DEBUG
223 printf("\nBANG!!!\n");
224 #endif
225 explode_process_detonator(xmvlist->current);
226 cmv=cmv_next;
227 #ifdef MOVE_DEBUG
228 printf("\nreturn to move_gravity_process(xor_move* xmv=%lx)\n",(unsigned long) xmv);
229 printf("\tcmv=cmv_next=%lx\n",(unsigned long)cmv);
230 if(cmv)
231 printf("\t*(%lx)cmv->from_x:%d,from_y:%d,from_obj:%s\n",
232 (unsigned long)cmv,cmv->from_x,cmv->from_y,
233 icon_details[cmv->from_obj].fname);
234 #endif
235 }
236 else if(cont==CT_PASS)
237 {
238 map->data[cmv->from_y][cmv->from_x]=ICON_FLOOR;
239 map->data[cmv->to_y][cmv->to_x]=cmv->from_obj;
240 game_win_move_object(cmv);
241 tmpx=cmv->from_x;
242 tmpy=cmv->from_y;
243 cmv->from_x=cmv->to_x;
244 cmv->from_y=cmv->to_y;
245 cmv->moves_count++;
246 if(cmv_next){
247 cmv=cmv_next;
248 /*rpause.tv_nsec/=1.1;*/
249 }
250 else{
251 if(cmv->dir&MV_HORIZ){
252 if((cmv=create_gravity_chain_xydir(tmpx,tmpy-1,MV_DOWN)))
253 xmvlist_append_xor_move(cmv);
254 if((tmp=create_gravity_chain_xydir(tmpx,tmpy+1,MV_UP))){
255 xmvlist_append_xor_move(tmp);
256 if(!cmv)
257 cmv=tmp;
258 }
259 }
260 else{
261 if((cmv=create_gravity_chain_xydir(tmpx+1,tmpy,MV_LEFT)))
262 xmvlist_append_xor_move(cmv);
263 if((tmp=create_gravity_chain_xydir(tmpx-1,tmpy,MV_RIGHT))){
264 xmvlist_append_xor_move(tmp);
265 if(!cmv)
266 cmv=tmp;
267 }
268 }
269 /*
270 if(cmv){
271 rpause.tv_nsec/=1.1;
272 }
273 */
274 xmvlist_cycle_next();
275 cmv=xmv=xmvlist->current->xmv;
276 }
277 }
278 else if ((cmv=move_unchain_blocked_bomb(xmvlist->current)))
279 xmv=cmv;
280 else { /* chain blocked - remove it */
281 #ifdef MOVE_DEBUG
282 printf("mv_grav_proc() chain blocked removing...\n");
283 #endif
284 tmplnk=xmvlist->current;
285 #ifdef MOVE_DEBUG
286 if(tmplnk->xmv!=xmv)
287 printf("\n***** current->xmv != xmv *******\n");
288 #endif
289 destroy_gravity_chain(xmv);
290 if(xmvlist_cycle_next()==tmplnk)
291 cmv=xmv=0; /* about to remove last chain */
292 else
293 cmv=xmv=xmvlist->current->xmv;
294 xmvlist_unlink_xor_move(tmplnk);
295 }
296 }
297 }
298 #ifdef MOVE_DEBUG
299 printf("\nEXITING move_gravity_process(xor_move* xmv=%lx)\n",(unsigned long) xmv);
300 #endif
301 }
302
move_unchain_blocked_bomb(struct xmv_link * lnk)303 struct xor_move* move_unchain_blocked_bomb(struct xmv_link* lnk)
304 {
305 struct xor_move* xmv=lnk->xmv;
306 struct xor_move* tmp;
307 if(xmv->moves_count==0)
308 return 0;
309 #ifdef MOVE_DEBUG
310 printf("move_unchain_blocked_bomb(xmv_link* lnk=%lx)\n",
311 (unsigned long)lnk);
312 printf("moves count:%d\n",xmv->moves_count);
313 #endif
314 switch(xmv->dir){
315 case MV_DOWN:
316 while(xmv){
317 if(bomb_type(xmv->from_obj)==MV_HORIZ){
318 if((tmp=xmv->up)){
319 xmv->up=0;
320 destroy_gravity_chain(lnk->xmv);
321 return (lnk->xmv=tmp);
322 }
323 return 0;
324 }
325 else{
326 tmp=xmv;
327 xmv=xmv->up;
328 }
329 }
330 return 0;
331 case MV_LEFT:
332 while(xmv){
333 if(bomb_type(xmv->from_obj)==MV_VERT){
334 if((tmp=xmv->right)){
335 xmv->right=0;
336 destroy_gravity_chain(lnk->xmv);
337 return (lnk->xmv=tmp);
338 }
339 return 0;
340 }
341 else{
342 tmp=xmv;
343 xmv=xmv->right;
344 }
345 }
346 return 0;
347 case MV_UP:
348 while(xmv){
349 if(bomb_type(xmv->from_obj)==MV_HORIZ){
350 if((tmp=xmv->down)){
351 xmv->down=0;
352 destroy_gravity_chain(lnk->xmv);
353 return (lnk->xmv=tmp);
354 }
355 return 0;
356 }
357 else{
358 tmp=xmv;
359 xmv=xmv->down;
360 }
361 }
362 return 0;
363 case MV_RIGHT:
364 while(xmv){
365 if(bomb_type(xmv->from_obj)==MV_VERT){
366 if((tmp=xmv->right)){
367 xmv->left=0;
368 destroy_gravity_chain(lnk->xmv);
369 return (lnk->xmv=tmp);
370 }
371 return 0;
372 }
373 else{
374 tmp=xmv;
375 xmv=xmv->left;
376 }
377 }
378 return 0;
379 default:
380 return 0;
381 }
382 }
383
move_hard_push(struct xor_move * xmv)384 void move_hard_push(struct xor_move* xmv)
385 {
386 #ifdef MOVE_DEBUG
387 printf("move_hard_push (xor_move* %lx)\n",(unsigned long)xmv);
388 #endif
389 /*
390 rpause.tv_sec=0;
391 if(player.replay)
392 rpause.tv_nsec=options_replay_speed(options->replay_speed);
393 else
394 rpause.tv_nsec=20000000L;
395 */
396 #ifdef MOVE_DEBUG
397 if(!(actions[xmv->from_obj].cont_dir&xmv->dir))
398 printf("***** hard push direction mismatch! *****\n");
399 #endif
400 unsigned int flimit=SDL_GetTicks()+TICK_COUNT;
401 do{
402 map->data[xmv->from_y][xmv->from_x]=ICON_FLOOR;
403 map->data[xmv->to_y][xmv->to_x]=xmv->from_obj;
404 game_win_move_object(xmv);
405 xmv->from_x=xmv->to_x;
406 xmv->from_y=xmv->to_y;
407 switch(xmv->dir){
408 case MV_LEFT: xmv->to_x--; break;
409 case MV_RIGHT: xmv->to_x++; break;
410 case MV_UP: xmv->to_y--; break;
411 case MV_DOWN: xmv->to_y++; break;
412 default:
413 fprintf(stderr,
414 "***** hardpush object move non-direction *****\n");
415 return;
416 }
417 delay(flimit);
418 flimit=SDL_GetTicks()+TICK_COUNT;
419 /*nanosleep(&rpause,&repause);*/
420 }
421 while(map->data[xmv->to_y][xmv->to_x]==ICON_FLOOR);
422
423 /*
424 while(map->data[xmv->to_y][xmv->to_x]==ICON_FLOOR){
425 map->data[xmv->from_y][xmv->from_x]=ICON_FLOOR;
426 map->data[xmv->to_y][xmv->to_x]=xmv->from_obj;
427 game_win_move_object(xmv);
428 xmv->from_x=xmv->to_x;
429 xmv->from_y=xmv->to_y;
430 switch(xmv->dir){
431 case MV_LEFT: xmv->to_x--; break;
432 case MV_RIGHT: xmv->to_x++; break;
433 case MV_UP: xmv->to_y--; break;
434 case MV_DOWN: xmv->to_y++; break;
435 default:
436 fprintf(stderr,
437 "***** hardpush object move non-direction *****\n");
438 return;
439 }
440 delay(flimit);
441 flimit=SDL_GetTicks()+TICK_COUNT;
442 */
443 /*nanosleep(&rpause,&repause);*/
444 /*
445 }
446 */
447 }
448
flip(su_t obj,su_t dir)449 su_t flip(su_t obj, su_t dir)
450 {
451 switch(obj){
452 case ICON_B: return (dir&MV_VERT?ICON_P:ICON_D);
453 case ICON_D: return (dir&MV_VERT?ICON_Q:ICON_B);
454 case ICON_P: return (dir&MV_VERT?ICON_B:ICON_Q);
455 case ICON_Q: return (dir&MV_VERT?ICON_D:ICON_P);
456 case ICON_S: return ICON_Z;
457 case ICON_Z: return ICON_S;
458 case ICON_L: return ICON_J;
459 case ICON_J: return ICON_L;
460 default:
461 fprintf(stderr,"tried to flip non-flippable\n");
462 return obj;
463 }
464 }
465