e18b64228a93fcd7898c6738160c93a4c44533fe
[mancala] / src / play.c
1 /*
2 *  for Maemo renamed to play.c and some bugfixes (2009, Reto Zingg)
3 *
4 *  Main Mancala Program Module Source -- main.c 
5 *  $Id: main.c,v 1.7.2.25 2004/01/17 06:56:23 sparrow_hawk Exp $
6 *
7 *  Copyright (C) 2003 Kevin Riggle 
8 *  http://cmancala.sourcefoge.net
9 *  Copyright (C) 2009 Reto Zingg
10 *
11 *  This program is free software; you can redistribute it and/or modify it
12 *  under the terms of the GNU General Public License as published by the
13 *  Free Software Foundation; either version 2, or (at your option) any
14 *  later version.
15 *
16 *  This program is distributed in the hope that it will be useful, but
17 *  WITHOUT ANY WARRANTY; without even the implied warranty of
18 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 *  General Public License for more details, a copy of which may be found in
20 *  the file COPYING provided in the main directory of this release.
21 *
22 */
23
24 #include <hildon/hildon.h>
25 #include <hgw/hgw.h>
26 #include <unistd.h>
27
28 #include "SDL_mixer.h"
29 #include "SDL.h"
30 #include "SDL_image.h"
31 #include "SDL_ttf.h"
32 #include "SDL_getenv.h"
33
34 #include "graphics.h"
35 #include "mancala.h"
36 #include "ai.h"
37 #include "sounds.h"
38 #include "play.h"
39
40 #include "callbacks.h"
41
42 // the surfaces
43 SDL_Surface *screen, *board, *title_text, *tile, *stone[STONE_MAX+1], *exit_text;
44 // the fonts
45 TTF_Font *title_font, *home_font, *board_font;
46 // The sound effects that will be used
47 Mix_Chunk *pick = NULL;
48 // the hildon-game-wrapper context
49 HgwContext *hgw_context = NULL;
50
51 // for debugging, example:
52
53 // rmz_debug(g_strdup_printf("play step 2: SDL_AUDIODRIVER: %s",
54 //                            my_sdl_audiodrv)
55 //                          );
56
57 // void rmz_debug (char *msg){
58 //     FILE *pFile;
59 //     
60 //     pFile = fopen ("/home/rzingg/mancala.debug", "a");
61 //     if (pFile) {
62 //         fprintf (pFile, "rmz_debug: %s \n", msg);
63 //         fclose (pFile);
64 //     }
65 // }
66
67 void sdl_clean_up(){
68         
69         int i = 0;
70         
71         SDL_FreeSurface(board);
72         SDL_FreeSurface(tile);
73         SDL_FreeSurface(exit_text);
74         SDL_FreeSurface(title_text);
75         for(i=0; i<=STONE_MAX; i++)
76                 SDL_FreeSurface(stone[i]);
77         SDL_FreeSurface(screen);
78         TTF_CloseFont(title_font);
79         TTF_CloseFont(board_font);
80         TTF_CloseFont(home_font);
81         Mix_FreeChunk(pick);
82         /* Make sure we clean up after ourselves */
83         TTF_Quit();
84         Mix_CloseAudio();
85         SDL_Quit();
86         return;
87 }
88
89 int play() {
90
91         // Scratchbox needs different SDL_AudiDriver env
92         #if __i386__
93         putenv("SDL_AUDIODRIVER=alsa") ;
94         #endif /* __i386__ */
95         
96         SDL_Rect board_rect, title_rect, exit_rect;
97         SDL_Color font_color;
98         SDL_Event event;
99         SDL_Color font_color_exit;
100         
101         char tile_path[STRING_MAX], stone_path[STRING_MAX];
102         char icon_path[STRING_MAX], title_path[STRING_MAX];
103         char home_path[STRING_MAX], board_path[STRING_MAX];
104         char pick_path[STRING_MAX];
105         int aiBoard[BOARD_MAX+1], humanBoard[BOARD_MAX+1];
106         int i, redraw_board, highlight, old_highlight, active;
107         int current_move, ai_last_move, human_last_move, state;
108         
109         /* Set up the game board and game variables. */
110         gameInit(aiBoard, humanBoard);
111         current_move = 0;
112         ai_last_move = human_last_move = -99;
113         
114         /* initialize our libraries */
115         //if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_AUDIO) < 0) {
116        if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {
117                printf("Unable to initialize SDL: %s\n", 
118                         SDL_GetError());
119                         sdl_clean_up();
120                         return 1;
121        }
122        
123        if (TTF_Init() < 0) {
124                printf("Unable to initialize SDL_ttf: %s\n", 
125                         SDL_GetError());
126                         sdl_clean_up();
127                         return 1;
128        }
129        
130        //Initialize SDL_mixer 
131        if( Mix_OpenAudio( 22050, MIX_DEFAULT_FORMAT, 2, 4096 ) == -1 ) 
132        // if( Mix_OpenAudio(22050, (Uint16)AUDIO_U8, 2, 256 ) == -1 )
133        {
134                printf("Unable to initialize Mix_OpenAudio: %s\n",
135                         SDL_GetError());
136                         sdl_clean_up();
137                         return 1;
138        }
139        
140        /* Load our images... PNGs now, maybe XPMs later */
141        sprintf(tile_path, "%s/tile.png", RES_PATH);
142        if ((tile = LoadRes(tile_path)) == NULL) {
143                printf("Unable to load resource: %s\n", 
144                         SDL_GetError());
145                         sdl_clean_up();
146                         return 1;
147        }
148        
149        for (i=0; i<=STONE_MAX; i++) {
150                if (sprintf(stone_path, "%s/stone%02d.png", RES_PATH, i) == 0)
151                        printf("Problems assembling path.\n");
152                if (!(stone[i] = LoadRes(stone_path))) {
153                        printf("Unable to load resource: %s\n",
154                                 SDL_GetError());
155                                 sdl_clean_up();
156                                 return 1;
157                }
158        }
159        
160        /* Load our font(s) */
161        if (sprintf(title_path, "%s/luxisr.ttf", FONT_PATH) == 0)
162                printf("Problems assembling path.\n");
163        if (!(title_font = TTF_OpenFont(title_path, TITLE_SIZE))) {
164                printf("Could not load font: %s\n", TTF_GetError());
165                sdl_clean_up();
166                return 1;
167        }
168        
169        if (sprintf(board_path, "%s/luxisr.ttf", FONT_PATH) == 0)
170                printf("Problems assembling path.\n");
171        if (!(board_font = TTF_OpenFont(board_path, BOARD_SIZE))) {
172                printf("Could not load font: %s\n", TTF_GetError());
173                sdl_clean_up();
174                return 1;
175        }
176        
177        if (sprintf(home_path, "%s/luxisr.ttf", FONT_PATH) == 0)
178                printf("Problems assembling path.\n");
179        if (!(home_font = TTF_OpenFont(home_path, HOME_SIZE))) {
180                printf("Could not load font: %s\n", TTF_GetError());
181                sdl_clean_up();
182                return 1;
183        }
184        
185        /* Load sound effects */ 
186        sprintf(pick_path, "%s/pick.wav", RES_PATH); 
187        if ((pick = Mix_LoadWAV(pick_path)) == NULL) { 
188                printf("Unable to load sound: %s\n", 
189                         SDL_GetError());
190                         sdl_clean_up();
191                         return 1; 
192        }
193        
194        /* store the font's color */
195        font_color.r = 255;
196        font_color.b = 255;
197        font_color.g = 255;
198        
199        /* render the title text 
200        if (!(title_text = TTF_RenderText_Solid(title_font, 
201                "Mancala", font_color))) 
202                fprintf(stderr, "TTF: %s\n", TTF_GetError());
203        */
204        title_text = NULL;
205        
206        
207        /* define the position of the board in the screen */
208        board_rect.x = 0;
209        board_rect.y = Y_OFFSET;
210        board_rect.w = 0;
211        board_rect.h = 0;
212        
213        /* set window properties and create it */
214        SDL_WM_SetCaption("Mancala", "Mancala");
215        if (sprintf(icon_path, "%s/icon.png", RES_PATH) == 0)
216                printf("Problems assembling icon path.\n");
217        SDL_WM_SetIcon(LoadRes(icon_path), NULL);
218        if ((screen = SDL_SetVideoMode(tile->w*8, (tile->h*2) + Y_OFFSET, 16, SDL_FULLSCREEN))
219                == NULL) {
220                printf("Unable to set %dx%d video: %s", tile->w*8,
221                         tile->h*2, SDL_GetError());
222                         sdl_clean_up();
223                         return 1;
224        }
225        SDL_ShowCursor(SDL_DISABLE);
226        
227        /* define the font color fot the exit text */
228        font_color_exit.r = 255;
229        font_color_exit.r = 255;
230        font_color_exit.r = 255;
231        
232        if (!(exit_text = TTF_RenderText_Blended(home_font, "EXIT", 
233              font_color_exit))) {
234                      printf("SDL_ttf: %s\n", TTF_GetError());
235                      return 1;
236         }
237        
238         exit_rect.x = 400;
239         exit_rect.y = 0;
240         exit_rect.w = 0;
241         exit_rect.h = 0;
242         
243         SDL_BlitSurface(exit_text, NULL, screen, &exit_rect);
244         
245        state = HMN_WAIT;
246        redraw_board = 1;
247        old_highlight = 0;      
248        highlight = 0;
249        active = 0;
250        
251        /* GAME LOOP */
252        while (state != GAME_WON) {
253                
254                /* check for GTK events... */
255                /* otherwise hildon thinks the app hangs... */
256                while (gtk_events_pending ())
257                        gtk_main_iteration ();
258                
259                /* figure out if anything important happened */
260                old_highlight = highlight;
261                while (SDL_PollEvent(&event)) {
262                        /* BAIL OUT! BAIL OUT! */
263                        if (event.type == SDL_KEYDOWN){
264                                printf("event SDL_KEYDOWN found....\n");
265                                if ( event.key.keysym.sym == SDLK_q )
266                                {
267                                        printf("event SDLK_q found....\n");
268                                        SDL_Event quit_event;
269                                        quit_event.type = SDL_QUIT;
270                                        SDL_PushEvent(&quit_event);
271                                }
272                        }
273                        
274                        if (event.type == SDL_MOUSEBUTTONDOWN) {
275                                if ((event.button.button = 1) &&
276                                    (event.button.y < Y_OFFSET)) {
277                                        printf("clicked out side the board in exit area...\n");
278                                        SDL_Event quit_event;
279                                        quit_event.type = SDL_QUIT;
280                                        SDL_PushEvent(&quit_event);
281                                }
282                        }
283                        
284                        if (event.type == SDL_QUIT) {
285                                printf("event SDL_QUIT found....\n");
286                                sdl_clean_up();
287                                return 0;
288                        }
289                        
290                        /* get events */
291                        if (state == HMN_WAIT) {
292                                switch (event.type) {
293                                        case SDL_MOUSEBUTTONDOWN:
294                                                if ((event.button.button = 1) &&
295                                                    (event.button.y < tile->h) &&
296                                                    (event.button.y > Y_OFFSET)) {
297
298                                                        int pitch=0;
299                                                        pitch = event.button.x / tile->w;
300
301                                                         // pitch 0 and 7 are the homebases which you can't play
302                                                         if ( pitch == 0 || pitch == 7 ){
303                                                                  printf("clicked out side the board...\n");
304                                                         }
305                                                         else{
306                                                                 current_move = pitch;
307                                                                 state = HMN_MOVE;
308                                                         }
309                                                }
310                                                break;
311                                        case SDL_MOUSEMOTION:
312                                                if (event.motion.y < tile->h) {
313                                                        highlight = event.motion.x / tile->w;
314                                                }
315                                                else
316                                                        highlight = 0;
317                                                break;
318                                        case SDL_ACTIVEEVENT:
319                                                if (event.active.gain == 0)
320                                                        highlight = 0;
321                                                break;
322                                }
323                        }
324                }
325                SDL_Delay(DELAY_MAX);
326                
327                /* GAME LOGIC */
328                if (gameWon(aiBoard, humanBoard) == 1)
329                        state = GAME_WON;
330                
331                /* happy happy state machine */
332                switch(state) {
333                        case HMN_WAIT:
334                                active = 0;
335                                if (highlight != old_highlight)
336                                        redraw_board = 1;
337                                break;
338                        case HMN_MOVE:
339                                human_last_move = move(humanBoard,aiBoard,current_move);
340                                play_sound(pick);
341                                redraw_board = 1;
342                                if (human_last_move == 0)
343                                        state = HMN_WAIT;
344                                else 
345                                        state = CMP_WAIT;
346                                printf("Human moving from %d to %d, now %d\n", current_move, human_last_move, state);
347                                break;
348                        case CMP_WAIT:
349                                SDL_Delay(DELAY_AI);
350                                active = 1;
351                                current_move = aiMove(aiBoard, humanBoard);
352                                state = CMP_MOVE;
353                                break;
354                        case CMP_MOVE:
355                                printf("Computer moving\n");
356                                ai_last_move = move(aiBoard,humanBoard,current_move);
357                                play_sound(pick);
358                                redraw_board = 1;
359                                if (ai_last_move == 0)
360                                        state = CMP_WAIT;
361                                else
362                                        state = HMN_WAIT;
363                                break;
364                        case GAME_WON:
365                                if (aiBoard[0] > humanBoard[0]) {
366                                        if (!(title_text = TTF_RenderText_Blended(title_font, 
367                                                "Computer Wins!", font_color)))
368                                                printf("TTF: %s\n", TTF_GetError());
369                                }
370                                else {
371                                        if (!(title_text = TTF_RenderText_Blended(title_font, 
372                                                "Human Wins!", font_color))) 
373                                                printf("TTF: %s\n", TTF_GetError());
374                                }
375                                redraw_board = 1;
376                                break;
377                }
378                
379                /* redraw the board if needed */
380                if (redraw_board == 1) {
381                        /*printf("redrawing board\n");*/
382                        
383                        /* draw and blit the board */
384                        board = DrawBoard(aiBoard, humanBoard, board_font, 
385                                           home_font, tile, stone, active, 
386                                           highlight);
387                                           if (!board) {
388                                                   printf("Could not draw the board.\n");
389                                           }
390                                           else {
391                                                   // board_rect = SurfaceToRect(board);
392                                                   SDL_BlitSurface(board, NULL, screen, 
393                                                                    &board_rect);
394                                           }
395                                           
396                                           /* draw, center, and blit the title */
397                                           if (title_text) {
398                                                   title_rect = SurfaceToRect(title_text);
399                                                   title_rect.x = ((screen->w - title_rect.w)/2);
400                                                   title_rect.y = ((screen->h - title_rect.h)/2);
401                                                   SDL_BlitSurface(title_text, NULL, screen, 
402                                                                    &title_rect);
403                                           }
404                                           
405                                           SDL_UpdateRect(screen, 0,0,0,0);
406                                           
407                                           redraw_board = 0;
408                }
409                
410                hgw_msg_compat_receive(hgw_context, 0);
411                
412        }
413        
414        SDL_Delay(DELAY_AI);
415        
416        
417        sdl_clean_up();
418        return 0;
419        
420 }
421
422
423 int main(int argc, char **argv) {
424
425     hgw_context = hgw_context_compat_init(argc, argv);
426     if (!hgw_context) {
427         printf("Cannot init hildon-games-startup!\n");
428         return 0;
429     }
430
431     hgw_compat_set_cb_exit(hgw_context, exit_callback);
432     hgw_compat_set_cb_quit(hgw_context, quit_callback);
433     hgw_compat_set_cb_flush(hgw_context, flush_callback);    
434     if(!hgw_context_compat_check(hgw_context)) return 0;
435
436     /* hildon-games-wrapper part */
437     hgw_msg_compat_receive(hgw_context, 0);
438     usleep(100);
439
440     // Main game
441     play();
442
443     // hgw_context_compat_destroy_deinit(hgw_context);
444     // hgw_context_compat_destroy_quit(hgw_context);
445     // hgw_context_destroy(hgw_context);
446     hgw_context_destroy(hgw_context, HGW_BYE_INACTIVE);
447
448     return 0;
449 }
450