Logo Search packages:      
Sourcecode: xarchon version File versions  Download package

main.c

/*--------------------------------------------------------------------------*/
/* main                                                                     */
/*--------------------------------------------------------------------------*/

#include <config.h>

#include <limits.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/time.h>
#include <X11/keysym.h>
#include <X11/Xlib.h>
#include <X11/xpm.h>

#include <gdk/gdkx.h>
#include <gtk/gtk.h>
#include "gtk-callbacks.h"
#include "gtk-interface.h"
#include "gtk-support.h"

#include "main.h"
#include "canvas.h"
#include "theme.h"
#include "board.h"
#include "iface.h"
#include "audio.h"
#include "field.h"

#include "main-random.h"

/*--------------------------------------------------------------------------*/
/* defines                                                                  */
/*--------------------------------------------------------------------------*/

#define APP_NAME        "xarchon"

#define UPF             (1000000 / FPS)         /* usecs per frame */
#define TIMER_RES       10000                   /* OS timer resolution */
#define UPF_MIN         (UPF - UPF % TIMER_RES)
#define UPF_MAX         (UPF + UPF % TIMER_RES)

/*--------------------------------------------------------------------------*/
/* functions                                                                */
/*--------------------------------------------------------------------------*/

static void set_sensitive_options(int game_active);
static void set_visible_gui(int visible);
static void progress_func(char *msg, float progress);
static void init_gui(int *argc, char *argv[]);
static void init(int *argc, char *argv[]);
static void play(int n);
static void loop(void);

/*--------------------------------------------------------------------------*/
/* variables                                                                */
/*--------------------------------------------------------------------------*/

int random_index;

static GtkWidget *window, *menubar, *progressbar;

static Atom wm_protocols, wm_delete_window;

static int initializing = 1;
static int quitting = 0;

/*--------------------------------------------------------------------------*/
/* main_random                                                              */
/*--------------------------------------------------------------------------*/

int main_random(void)
{
   int v;

   v = random_numbers[random_index % RANDOM_COUNT];
   random_index++;
   return v;
}

/*--------------------------------------------------------------------------*/
/* main_msgbox                                                              */
/*--------------------------------------------------------------------------*/

void main_msgbox(char *msg)
{
   GtkWidget *dialog, *label, *okay_button;

   dialog = gtk_dialog_new();
   label = gtk_label_new(msg);
   okay_button = gtk_button_new_with_label("OK");
   gtk_signal_connect_object(GTK_OBJECT(okay_button), "clicked",
                             GTK_SIGNAL_FUNC(gtk_widget_destroy),
                             GTK_OBJECT(dialog));
   gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
                     okay_button);
   gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
   gtk_window_set_modal(GTK_WINDOW(dialog), 1);
   gtk_widget_show_all(dialog);
}

/*--------------------------------------------------------------------------*/
/* set_sensitive_options                                                    */
/*--------------------------------------------------------------------------*/

static void set_sensitive_options(int game_active)
{
   gtk_widget_set_sensitive(lookup_widget(window, "mnu_game_new"),
                            !game_active);
   gtk_widget_set_sensitive(lookup_widget(window, "mnu_game_stop"),
                            game_active);
   gtk_widget_set_sensitive(lookup_widget(window, "mnu_settings_define"),
                            !game_active);
   gtk_widget_set_sensitive(lookup_widget(window, "mnu_settings_select"),
                            !game_active);
   gtk_widget_set_sensitive(lookup_widget(window, "mnu_settings_theme"),
                            !game_active);
}

/*--------------------------------------------------------------------------*/
/* set_visible_gui                                                          */
/*--------------------------------------------------------------------------*/

static void set_visible_gui(int visible)
{
   if (visible) {
      gtk_widget_show(menubar);
      gtk_widget_show(lookup_widget(window, "logo"));
      gtk_widget_show(progressbar);
   } else {
      gtk_widget_hide(menubar);
      gtk_widget_hide(lookup_widget(window, "logo"));
      gtk_widget_hide(progressbar);
   }
   gdk_flush();
}

/*--------------------------------------------------------------------------*/
/* main_game_new                                                            */
/*--------------------------------------------------------------------------*/

void main_game_new(GtkMenuItem *menuitem, gpointer user_data)
{
   char *msg;
   int light_first;

   set_visible_gui(0);
   msg = iface_start(&light_first);
   quitting = 0;                        /* this is important */
   if (msg != NULL) {
      set_visible_gui(1);
      progress_func(msg, 1.0);
      return;
   }
   set_sensitive_options(1);
   board_start_game(light_first);
   if (menuitem != NULL)                /* NULL when called by main() */
      gtk_main_quit();
}

/*--------------------------------------------------------------------------*/
/* main_game_unpause                                                        */
/*--------------------------------------------------------------------------*/

void main_game_unpause(GtkMenuItem *menuitem, gpointer user_data)
{
   if (board_pause_game(0))
      gtk_main_quit();
}

/*--------------------------------------------------------------------------*/
/* main_game_stop                                                           */
/*--------------------------------------------------------------------------*/

void main_game_stop(GtkMenuItem *menuitem, gpointer user_data)
{
   board_end_game();
   set_sensitive_options(0);
   progress_func("Game Ended", 1.0);
}

/*--------------------------------------------------------------------------*/
/* main_toggle_sound                                                        */
/*--------------------------------------------------------------------------*/

void main_toggle_sound(GtkMenuItem *menuitem, gpointer user_data)
{
   if (audio_isenabled())
      audio_disable();
   else
      audio_enable();
}

/*--------------------------------------------------------------------------*/
/* main_game_exit                                                           */
/*--------------------------------------------------------------------------*/

void main_game_exit(GtkMenuItem *menuitem, gpointer user_data)
{
   quitting = 1;
   gtk_main_quit();
}

/*--------------------------------------------------------------------------*/
/* main_help_tips                                                           */
/*--------------------------------------------------------------------------*/

void main_help_tips(GtkMenuItem *menuitem, gpointer user_data)
{
   static GtkWidget *window = NULL;
   static int destroying = 0;

   if (window == NULL) {
      window = create_tips_window();
      gtk_widget_show(window);
   } else if (!destroying) {
      destroying = 1;
      gtk_widget_destroy(window);
      window = NULL;
      destroying = 0;
   }
}

/*--------------------------------------------------------------------------*/
/* main_help_about                                                          */
/*--------------------------------------------------------------------------*/

void main_help_about(GtkMenuItem *menuitem, gpointer user_data)
{
   static GtkWidget *window = NULL;
   static int destroying = 0;

   if (window == NULL) {
      window = create_about_window();
      gtk_widget_show(window);
   } else if (!destroying) {
      destroying = 1;
      gtk_widget_destroy(window);
      window = NULL;
      destroying = 0;
   }
}

/*--------------------------------------------------------------------------*/
/* main_window_expose_event                                                 */
/*--------------------------------------------------------------------------*/

gboolean main_window_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
{
   /* redraw canvas only if a game is in progress */
   if (gtk_main_level() == 0 && board_pause_game(-1))
      canvas_refresh_all();
   return TRUE;
}

/*--------------------------------------------------------------------------*/
/* main_window_destroy_event                                                */
/*--------------------------------------------------------------------------*/

void main_window_destroy_event(GtkObject *object, gpointer data)
{
   if (initializing)
      exit(EXIT_SUCCESS);
   quitting = 1;
   gtk_main_quit();
}

/*--------------------------------------------------------------------------*/
/* progress_func                                                            */
/*--------------------------------------------------------------------------*/

void progress_func(char *msg, float progress)
{
   if (progress == 0.0)
      gtk_widget_set_sensitive(menubar, FALSE);
   if (progress == 1.0)
      gtk_widget_set_sensitive(menubar, TRUE);
   gtk_progress_set_format_string(GTK_PROGRESS(progressbar), msg);
   gtk_progress_bar_update(GTK_PROGRESS_BAR(progressbar), progress);
   if (gtk_main_level() == 0) {
      while (gtk_events_pending())
         gtk_main_iteration();
      gdk_flush();
   }
}

/*--------------------------------------------------------------------------*/
/* init_gui                                                                 */
/*--------------------------------------------------------------------------*/

void init_gui(int *argc, char *argv[])
{
   GtkPixmap *pixmap;

   gtk_init(argc, &argv);
   wm_protocols = XInternAtom(GDK_DISPLAY(), "WM_PROTOCOLS", False);
   wm_delete_window = XInternAtom(GDK_DISPLAY(), "WM_DELETE_WINDOW", False);
   add_pixmap_directory(DATADIR);       /* a glade thingy */

   window = create_main_window();
   gtk_widget_set_usize(window, CANVAS_WIDTH, CANVAS_HEIGHT);

   gtk_signal_connect(GTK_OBJECT(window), "delete_event",
                     GTK_SIGNAL_FUNC(gtk_false), NULL);

   menubar = lookup_widget(window, "menubar");
   progressbar = lookup_widget(window, "progressbar");
   set_sensitive_options(0);
   gtk_widget_set_sensitive(menubar, FALSE);

   gtk_widget_show(window);
   XSelectInput(GDK_DISPLAY(), GDK_WINDOW_XWINDOW(window->window),
                KeyPressMask | KeyReleaseMask |
                PointerMotionMask | ButtonPressMask | ButtonReleaseMask |
                ExposureMask | FocusChangeMask);

   pixmap = GTK_PIXMAP(create_pixmap(window, "icon.xpm"));
   gdk_window_set_icon(window->window, NULL, pixmap->pixmap, pixmap->mask);
   gtk_widget_destroy(GTK_WIDGET(pixmap));
}

/*--------------------------------------------------------------------------*/
/* init                                                                     */
/*--------------------------------------------------------------------------*/

void init(int *argc, char *argv[])
{
   char str[64];

   iface_config_read();
   init_gui(argc, argv);
   canvas_init(GDK_DISPLAY(), GDK_WINDOW_XWINDOW(window->window),
               CANVAS_WIDTH, CANVAS_HEIGHT);
   canvas_install_colormap(0);
   audio_init();
   theme_init(progress_func);
   srandom(time(NULL));
   random_index = random() % RANDOM_COUNT;
   initializing = 0;
   sprintf(str, "Welcome to X ARCHON, version %s", VERSION);
   progress_func(str, 1.0);
}

/*--------------------------------------------------------------------------*/
/* display_event                                                            */
/*--------------------------------------------------------------------------*/

#if DEBUG
static void display_event(XEvent *ev)
{
   static char *Event_Names[LASTEvent] = {
      NULL, /* 0 */
      NULL,
      "KeyPress",
      "KeyRelease",
      "ButtonPress",
      "ButtonRelease",
      "MotionNotify",
      "EnterNotify",
      "LeaveNotify",
      "FocusIn",
      "FocusOut",
      "KeymapNotify",
      "Expose",
      "GraphicsExpose",
      "NoExpose",
      "VisibilityExpose",
      NULL, /* 16 */
      NULL,
      "UnmapNotify",
      "MapNotify",
      "MapRequest",
      NULL, /* 21 */
      NULL,
      NULL,
      NULL,
      NULL,
      NULL,
      NULL,
      NULL,
      NULL,
      NULL,
      NULL,
      NULL,
      "ClientMessage",
      "MappingNotify"
   };
   printf("Event %s (%d) Received\n", Event_Names[ev->type], ev->type);
}
#endif

/*--------------------------------------------------------------------------*/
/* main_handle_events                                                       */
/*--------------------------------------------------------------------------*/

int main_handle_events(int in_board_game)
{
   XEvent ev;
   int key;

   while (XEventsQueued(GDK_DISPLAY(), QueuedAfterReading) > 0) {
      XNextEvent(GDK_DISPLAY(), &ev);
#ifdef DEBUG
      display_event(&ev);
#endif
      switch (ev.type) {
         case KeyPress:
            if (in_board_game) {
               key = XLookupKeysym((XKeyEvent *)&ev, 0);
               /* if Escape on game that has ended, or if F12 */
               if ((key == XK_Escape && !board_pause_game(-1)) ||
                   key == XK_F12) {
                  main_game_stop(NULL, NULL);
                  return 0;
               }
               /* if Escape on a non-network game */
               if (key == XK_Escape && iface_is_pausable()) {
                  board_pause_game(1);
                  progress_func("Game Paused", 1.0);
                  return 0;
               }
               /* if F11 */
               if (key == XK_F11)
                  main_toggle_sound(NULL, NULL);
            }
            /* fallthrough */
         case KeyRelease:
            canvas_key_event((XKeyEvent *)&ev);
            break;
         case MotionNotify:
         case ButtonPress:
         case ButtonRelease:
            canvas_mouse_event(&ev);
            break;
         case Expose:
            if (ev.xexpose.count == 0)
               canvas_refresh_all();
            break;
         case MappingNotify:
            XRefreshKeyboardMapping(&ev.xmapping);
            break;
         case FocusIn:
         case FocusOut:
            if (in_board_game && iface_is_pausable())
               board_pause_game(ev.type == FocusOut);
            break;
         case ClientMessage:
            if (ev.xclient.message_type == wm_protocols &&
                ev.xclient.data.l[0] == wm_delete_window) {
               quitting = 1;
               return 0;
            }
      }
   }
   return 1;
}

/*--------------------------------------------------------------------------*/
/* play                                                                     */
/*--------------------------------------------------------------------------*/

void play(int n)
{
   struct itimerval itv;

   signal(SIGALRM, play);               /* always re-install signal handler */
   if (n != 0)                          /* if acting as signal handler */
      return;
   itv.it_interval.tv_sec = itv.it_value.tv_sec = 0;
   while (1) {
      /* timing logic:  at 40 fps, we need to get control every 25000us, */
      /* but the Linux timer ticks at 10ms == 10000us.  Control would be */
      /* returned only after 30000us, which is like working at 33 fps.   */
      /* Workaround:  alternate the pause between 20000 and 30000 usec,  */
      /* keeping an average of 25000us per frame, which is 40 fps.       */
      if (itv.it_interval.tv_usec == UPF_MIN)
         itv.it_interval.tv_usec = itv.it_value.tv_usec = UPF_MAX;
      else
         itv.it_interval.tv_usec = itv.it_value.tv_usec = UPF_MIN;
      setitimer(ITIMER_REAL, &itv, NULL);
      pause();
      signal(SIGALRM, play);            /* re-install signal handler */
      if (!main_handle_events(1))
         return;
      board_frame();
   }
}

/*--------------------------------------------------------------------------*/
/* loop                                                                     */
/*--------------------------------------------------------------------------*/

void loop(void)
{
   while (1) {
      gtk_main();
      if (quitting)
         return;
      set_visible_gui(0);
      canvas_install_colormap(1);
      canvas_refresh_all();
      canvas_mouse_cursor(1);
      play(0);
      canvas_mouse_cursor(0);
      if (quitting)
         return;
      canvas_install_colormap(0);
      set_visible_gui(1);
   }
}

/*--------------------------------------------------------------------------*/
/* main                                                                     */
/*--------------------------------------------------------------------------*/

#ifndef GENETICS_MAIN

int main(int argc, char *argv[])
{
   init(&argc, argv);

#ifndef AUTOPILOT
   loop();

#else
   {
   int game_num = 1, i;
   int lgt, drk;
   int lgt_x, lgt_y;
   int drk_x, drk_y;
   CELL *cell;
   ACTOR *winner;

   if (0) loop();
   printf("main:   running an autopilot game.\n");
   canvas_enable(0);
   audio_enable(0);
   iface_start(&lgt);

   for (i = 0; i < 20; i++)
   for (lgt = ACTOR_LIGHT_FIRST; lgt <= ACTOR_LIGHT_LAST; lgt++)
      for (drk = ACTOR_DARK_FIRST; drk <= ACTOR_DARK_LAST; drk++) {
         board_start_game(lgt);
         printf("* * * * * actor %d battles %d * * * * * (%d)\n", lgt, drk, i);
         fprintf(stderr, "* * * * * actor %d battles %d * * * * * (%d)\n", lgt, drk, i);
         board_find_actor(lgt, &lgt_x, &lgt_y);
         board_find_actor(drk, &drk_x, &drk_y);
         cell = &board_cells[drk_y][drk_x];
         cell->flags &= ~CELL_LUMI_MASK;
         cell->flags |= CELL_LIGHT;
         field_start_game(board_cells[lgt_y][lgt_x].actor,
                          board_cells[drk_y][drk_x].actor,
                          cell, 0, 0);
         do
            winner = field_frame();
         while (winner == NULL);
         /*
         board_end_game();
         */
      }
   iface_config_write();
   printf("All Done\n");
   }
#endif

   return 0;
}

#endif /* GENETICS_MAIN */

Generated by  Doxygen 1.6.0   Back to index