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