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 "play_xor.h"
20 #include <stdlib.h>
21 #include <time.h>
22 
23 #include "moves.h"
24 #include "options.h"
25 #include "scores.h"
26 #include "map.h"
27 #include "icons.h"
28 #include "mapdisplay.h"
29 
30 struct xg_key** play_keys=0;
31 struct xg_key** replay_keys=0;
32 
play_create_keys()33 bool play_create_keys()
34 {
35     if(!(play_keys=create_key_list_array(PLAY_KEYS_XXX)))
36         return FALSE;
37     play_keys[PLAY_KEY_UP]->key=SDLK_UP;
38     play_keys[PLAY_KEY_DOWN]->key=SDLK_DOWN;
39     play_keys[PLAY_KEY_LEFT]->key=SDLK_LEFT;
40     play_keys[PLAY_KEY_RIGHT]->key=SDLK_RIGHT;
41     play_keys[PLAY_KEY_SWAP]->key=SDLK_RETURN;
42     play_keys[PLAY_KEY_MAP]->key=SDLK_m;
43     play_keys[PLAY_KEY_SCR_THRESH_1]->key=SDLK_1;
44     play_keys[PLAY_KEY_SCR_THRESH_2]->key=SDLK_2;
45     play_keys[PLAY_KEY_SCR_THRESH_3]->key=SDLK_3;
46     play_keys[PLAY_KEY_TOG_INDICATORS]->key=SDLK_F1;
47     #ifdef MAPDEVMODE
48     play_keys[PLAY_KEY_MAPDEV]->key=SDLK_F9;
49     #endif
50     if(!(replay_keys=create_key_list_array(REPLAY_KEYS_XXX)))
51         return FALSE;
52     replay_keys[REPLAY_KEY_YES]->key=SDLK_y;
53     replay_keys[REPLAY_KEY_NO]->key=SDLK_n;
54     replay_keys[REPLAY_KEY_SAVE]->key=SDLK_s;
55     replay_keys[REPLAY_KEY_CONTINUE]->key=SDLK_c;
56     replay_keys[REPLAY_KEY_SPEED_1]->key=SDLK_1;
57     replay_keys[REPLAY_KEY_SPEED_2]->key=SDLK_2;
58     replay_keys[REPLAY_KEY_SPEED_3]->key=SDLK_3;
59     replay_keys[REPLAY_KEY_SPEED_4]->key=SDLK_4;
60     replay_keys[REPLAY_KEY_SPEED_5]->key=SDLK_5;
61     replay_keys[REPLAY_KEY_SPEED_6]->key=SDLK_6;
62     replay_keys[REPLAY_KEY_SPEED_7]->key=SDLK_7;
63     replay_keys[REPLAY_KEY_SPEED_8]->key=SDLK_8;
64     replay_keys[REPLAY_KEY_SPEED_9]->key=SDLK_9;
65     return TRUE;
66 }
67 
play_destroy_keys()68 void play_destroy_keys()
69 {
70     #ifdef INPUT_DEBUG
71     printf("about to destroy play_keys\n");
72     #endif
73     destroy_key_list_array(play_keys);
74     destroy_key_list_array(replay_keys);
75 }
76 
play_xor(lvl_t level,bool from_start)77 bool play_xor(lvl_t level, bool from_start)
78 {
79     ctr_t mv;
80     su_t move;
81     su_t state=PLAY_CONTINUE;
82     bool map_solved;
83     unsigned int flimit=SDL_GetTicks()+TICK_COUNT;
84     player.replay=0;
85     if(from_start){
86         replay.level=level;
87         init_wall(level,TRUE);
88         xg_map_load(level);
89         if(!map)
90             return FALSE;
91         xg_map_apply_edging();
92         map_display_init();
93         if((replay.moves=malloc(sizeof(su_t)*map->max_moves+1))){
94             for(mv=map->max_moves;mv>0;mv--)
95                 replay.moves[mv]=0;
96         }
97         else
98             return FALSE;
99         xg_map_init_views(game_win->blk_count_x,game_win->blk_count_y);
100         player_init();
101     }
102     else
103         level=replay.level;
104     gfx_set_win(scr_win);
105     gfx_win_half_size();
106     set_space_icon(SPC_TRAN);
107     gfx_mv_cur(2,0);
108     gfx_printf("%s",map->title);
109     gfx_set_win(game_win);
110     gfx_win_full_size();
111     game_win_display();
112     set_keys(play_keys);
113     if(from_start)
114         init_unsupported();
115     game_win_update_player_info();
116     map_solved=map_check_solved();
117     while(state==PLAY_CONTINUE||state==PLAY_PROCESS_MOVE){
118         move=MV_NONE;
119         if(simple_poll_event()){
120             if(xginput.exit)
121                 return FALSE;
122             else if(xginput.quit){
123                 dump_replay_data();
124                 move=MV_PLAYER_QUIT;
125             }
126             else if(play_keys[PLAY_KEY_LEFT]->pressed)  move=MV_LEFT;
127             else if(play_keys[PLAY_KEY_RIGHT]->pressed) move=MV_RIGHT;
128             else if(play_keys[PLAY_KEY_UP]->pressed)    move=MV_UP;
129             else if(play_keys[PLAY_KEY_DOWN]->pressed)  move=MV_DOWN;
130             else if(play_keys[PLAY_KEY_SWAP]->pressed)  move=MV_PLAYER_SWAP;
131             else if(play_keys[PLAY_KEY_MAP]->pressed)   map_display_show();
132             else if(play_keys[PLAY_KEY_SCR_THRESH_1]->pressed)
133                 options->scroll_thresh=1;
134             else if(play_keys[PLAY_KEY_SCR_THRESH_2]->pressed)
135                 options->scroll_thresh=2;
136             else if(play_keys[PLAY_KEY_SCR_THRESH_3]->pressed)
137                 options->scroll_thresh=3;
138             else if(play_keys[PLAY_KEY_TOG_INDICATORS]->pressed){
139                 options->show_indicators^=1;
140                 game_win_display();
141             }
142             #ifdef MAPDEVMODE
143             else if(play_keys[PLAY_KEY_MAPDEV]->pressed){
144                 map_dump_solve_state();
145             }
146             #endif
147             if(move){
148                 if((state=player_move(move))&PLAY_RECORD){
149                     replay.moves[player.move_no++]=move;
150                     state^=PLAY_RECORD;
151                     if(state==PLAY_ZERO_MOVES)
152                         gfx_message("out of moves");
153                     if(map_check_solved()!=map_solved){
154                         map_solved^=1;
155                         game_win_icon_display(
156                             map->exit.x,
157                             map->exit.y,
158                             map->data[map->exit.y][map->exit.x]);
159                     }
160                     #ifdef MOVE_DEBUG
161                     printf("player x:%d y:%d\n",
162                         map->player[player.player].x,
163                         map->player[player.player].y);
164                     #endif
165                     if((!player.p0_alive)&&(!player.p1_alive))
166                         state=PLAY_GOTCHA;
167                     game_win_update_player_info();
168                 }
169             }
170         }
171         delay(flimit);
172         flimit=SDL_GetTicks()+TICK_COUNT;
173     }
174     if(state==PLAY_COMPLETE){
175         save_score(map->level,player.move_no);
176         gfx_message("well done");
177     }
178     dump_replay_data();
179     if(player.move_no<map->max_moves)
180         return replay_xor(TRUE);
181     return FALSE;
182 }
183 
dump_replay_data()184 void dump_replay_data()
185 {
186     int n;
187     char c;
188     return;
189     if(!replay.moves){
190         printf("no replay data!\n");
191         return;
192     }
193     printf("moves remaining:%d\n", map->max_moves-player.move_no);
194     for(n=0;replay.moves[n]!=MV_NONE;n++){
195         switch(replay.moves[n]){
196             case MV_UP:             c='u';break;
197             case MV_DOWN:           c='d';break;
198             case MV_LEFT:           c='l';break;
199             case MV_RIGHT:          c='r';break;
200             case MV_HORIZ:          c='h';break;
201             case MV_VERT:           c='v';break;
202             case MV_ANY:            c='a';break;
203             case MV_PLAYER_SWAP:    c='s';break;
204             case MV_PLAYER_QUIT:    c='q';break;
205         }
206         printf("%d:%c ",n,c);
207     }
208     printf("\n");
209 }
210 
dump_play_state(int mv,int state)211 void dump_play_state(int mv, int state)
212 {
213     printf("%d:state( ",mv);
214     if(state&PLAY_RECORD){
215         printf("record ");
216         state^=PLAY_RECORD;
217     }
218     switch(state){
219         case PLAY_CONTINUE:
220             printf("continue ");
221             break;
222         case PLAY_PROCESS_MOVE:
223             printf("process ");
224             break;
225         case PLAY_SWAP:
226             printf("swap ");
227             break;
228         case PLAY_QUIT:
229             printf("quit ");
230             break;
231         case PLAY_ZERO_MOVES:
232             printf("zero moves");
233             break;
234         case PLAY_GOTCHA:
235             printf("gotcha ");
236             break;
237         case PLAY_COMPLETE:
238             printf("complete ");
239             break;
240         default:
241             printf("*** UNKNOWN **** ");
242             break;
243     }
244     printf(") ");
245 }
246 
replay_xor(bool ask)247 bool replay_xor(bool ask)
248 {
249     unsigned int flimit=SDL_GetTicks()+TICK_COUNT;
250     su_t state;
251     int p;
252     bool continue_play=FALSE;
253     bool ask_continue=player.p0_alive|player.p1_alive;
254     if(!replay.moves)
255         return FALSE;
256     dump_replay_data();
257     set_keys(replay_keys);
258     player.replay=TRUE;
259     do{
260         if(ask==TRUE){
261             if(ask_continue)
262                 gfx_message("Replay (Y/N/C/S)?");
263             else
264                 gfx_message("Replay (Y/N/S)?");
265             if(xginput.exit||replay_keys[REPLAY_KEY_NO]->pressed)
266             {
267                 free(replay.moves);
268                 replay.moves=0;
269                 xg_map_destroy();
270                 return FALSE;
271             }
272             else if(replay_keys[REPLAY_KEY_SAVE]->pressed){
273                 replay_save();
274                 free(replay.moves);
275                 replay.moves=0;
276                 xg_map_destroy();
277                 return FALSE;
278             }
279             else if(replay_keys[REPLAY_KEY_CONTINUE]->pressed){
280                 if(ask_continue)
281                     if(player.p0_alive||player.p1_alive)
282                         continue_play=TRUE;
283             }
284         }
285         else{
286             ask=TRUE;
287             replay_keys[REPLAY_KEY_YES]->pressed=TRUE;
288             /*SDL_PushEvent(&fake_confirm);*/
289         }
290         if(replay_keys[REPLAY_KEY_YES]->pressed){
291             dump_replay_data();
292             xg_map_load(replay.level);
293             xg_map_apply_edging();
294             xg_map_init_views(game_win->blk_count_x,game_win->blk_count_y);
295             player_init();
296             init_wall(replay.level,TRUE);
297             game_win_display();
298             state=PLAY_CONTINUE;
299             init_unsupported();
300             dump_replay_data();
301             while(state==PLAY_CONTINUE||state==PLAY_PROCESS_MOVE)
302             {
303                 if(simple_poll_event()){
304                     if(xginput.exit||xginput.quit)
305                         state=player_move(MV_PLAYER_QUIT);
306                     else if(replay_keys[REPLAY_KEY_SPEED_1]->pressed)
307                         options->replay_speed=1;
308                     else if(replay_keys[REPLAY_KEY_SPEED_2]->pressed)
309                         options->replay_speed=2;
310                     else if(replay_keys[REPLAY_KEY_SPEED_3]->pressed)
311                         options->replay_speed=3;
312                     else if(replay_keys[REPLAY_KEY_SPEED_4]->pressed)
313                         options->replay_speed=4;
314                     else if(replay_keys[REPLAY_KEY_SPEED_5]->pressed)
315                         options->replay_speed=5;
316                     else if(replay_keys[REPLAY_KEY_SPEED_6]->pressed)
317                         options->replay_speed=6;
318                     else if(replay_keys[REPLAY_KEY_SPEED_7]->pressed)
319                         options->replay_speed=7;
320                     else if(replay_keys[REPLAY_KEY_SPEED_8]->pressed)
321                         options->replay_speed=8;
322                     else if(replay_keys[REPLAY_KEY_SPEED_9]->pressed)
323                         options->replay_speed=9;
324                 }
325                 else {
326                     state=player_move(
327                         replay.moves[player.move_no++])
328                             ^PLAY_RECORD;
329                     map_check_solved();
330                     game_win_update_player_info();
331                     if((!player.p0_alive)&&(!player.p1_alive))
332                         state=PLAY_GOTCHA;
333                     for(p=0;p<options->replay_speed;p++){
334                         delay(flimit);
335                         flimit=SDL_GetTicks()+TICK_COUNT;
336                     }
337                 }
338             }
339             if(state==PLAY_GOTCHA)
340                 ask_continue=FALSE;
341             else
342                 ask_continue=TRUE;
343         }
344     }while(!continue_play);
345     state=PLAY_CONTINUE;
346     if(replay.moves[player.move_no-1]==MV_PLAYER_QUIT)
347         player.move_no--;
348     return TRUE;
349 }
350 
replay_save()351 void replay_save()
352 {
353 /*
354     char buf[32];
355     FILE* fp;
356     int key;
357     echo();
358     wattrset(game_win,COLOR_PAIR(ICON_XXX+1));
359     mvwprintw(game_win,11,0,"                                        ");
360     mvwprintw(game_win,12,0," Filename:                              ");
361     mvwprintw(game_win,13,0,"                                        ");
362     wmove(game_win,12,10);
363     wgetnstr(game_win,buf,30);
364     noecho();
365     if((fp=fopen(buf,"r"))){
366         mvwprintw(game_win,15,0,"                          ");
367         mvwprintw(game_win,16,0," Exists! Overwrite (y/n)? ");
368         mvwprintw(game_win,17,0,"                          ");
369         key=wgetch(game_win);
370         if(key=='n'||key=='N')
371             return;
372         fclose(fp);
373     }
374     if(!(fp=fopen(buf,"w"))){
375         mvwprintw(game_win,18,0,"        ");
376         mvwprintw(game_win,19,0," Error! ");
377         mvwprintw(game_win,20,0,"        ");
378         wgetch(game_win);
379         return;
380     }
381     if(!fwrite(&replay,sizeof(struct xor_replay),1,fp))
382     {
383         fclose(fp);
384         mvwprintw(game_win,18,0,"        ");
385         mvwprintw(game_win,19,0," Error! ");
386         mvwprintw(game_win,20,0,"        ");
387         wgetch(game_win);
388         return;
389     }
390     fclose(fp);
391     mvwprintw(game_win,18,0,"        ");
392     mvwprintw(game_win,19,0," Saved! ");
393     mvwprintw(game_win,20,0,"        ");
394     wgetch(game_win);
395 */
396 }
397 
398 
replay_load()399 lvl_t replay_load()
400 {
401     return 0;
402 /*
403     char buf[32];
404     FILE* fp;
405     echo();
406     wattrset(game_win,COLOR_PAIR(ICON_XXX+1));
407     mvwprintw(game_win,11,0,"                                        ");
408     mvwprintw(game_win,12,0," Filename:                              ");
409     mvwprintw(game_win,13,0,"                                        ");
410     wmove(game_win,12,10);
411     wgetnstr(game_win,buf,30);
412     noecho();
413     if(!(fp=fopen(buf,"r"))){
414         mvwprintw(game_win,18,0,"        ");
415         mvwprintw(game_win,19,0," Error! ");
416         mvwprintw(game_win,20,0,"        ");
417         wgetch(game_win);
418         return -1;
419     }
420     if(!fread(&replay,sizeof(struct xor_replay),1,fp))
421     {
422         fclose(fp);
423         mvwprintw(game_win,18,0,"        ");
424         mvwprintw(game_win,19,0," Error! ");
425         mvwprintw(game_win,20,0,"        ");
426         wgetch(game_win);
427         return -1;
428     }
429     mvwprintw(game_win,18,0,"         ");
430     mvwprintw(game_win,19,0," Loaded! ");
431     mvwprintw(game_win,20,0,"         ");
432     if(replay_xor(FALSE))
433         return 100;
434     return replay.level;
435 */
436 }
437 
inc_max_moves()438 void inc_max_moves()
439 {
440     su_t* tmp=0;
441     if(player.replay){
442         /* really don't want to realloc during replay */
443         map->max_moves+=10;
444         return;
445     }
446     if((tmp=realloc(replay.moves,map->max_moves+10))){
447         map->max_moves+=10;
448         replay.moves=tmp;
449     }
450     else{
451         fprintf(stderr,"*** memory re-allocation for replay data failed! ***\n");
452         fprintf(stderr,"This was needed for the object just collected by player\n");
453         fprintf(stderr,"in order to increase the number of moves allowed in which\n");
454         fprintf(stderr,"to complete this level. This therefor is staying the same.\n");
455     }
456 }
457