Back to index

gcompris  8.2.2
Defines | Functions | Variables
railroad.c File Reference
#include "gcompris/gcompris.h"

Go to the source code of this file.

Defines

#define SOUNDLISTFILE   PACKAGE
#define ENGINES   9
#define WAGONS   13
#define NUMBER_OF_SUBLEVELS   3
#define NUMBER_OF_LEVELS   3
#define MODEL_MAX_SIZE   NUMBER_OF_LEVELS+1
#define MODEL_PAUSE   30

Functions

static void start_board (GcomprisBoard *agcomprisBoard)
static void pause_board (gboolean pause)
static void end_board (void)
static gboolean is_our_board (GcomprisBoard *gcomprisBoard)
static void set_level (guint level)
static void process_ok (void)
static void game_won (void)
static void repeat (void)
static void animate_model (void)
static gboolean animate_step (void)
static GnomeCanvasItem * railroad_create_item (GnomeCanvasGroup *parent)
static void railroad_destroy_all_items (void)
static void railroad_next_level (void)
static gint item_event (GnomeCanvasItem *item, GdkEvent *event, gpointer data)
static gint answer_event (GnomeCanvasItem *item, GdkEvent *event, gpointer data)
static void reposition_model (void)
static void reposition_answer (void)
static GList * reset_list (GList *list)
static void reset_all_lists (void)

Variables

static GcomprisBoard * gcomprisBoard = NULL
static gboolean board_paused = TRUE
static int gamewon
static const int line [] = { 100,180,260,340, 420, 500}
static gboolean animation_pending
static gint animation_count = 0
static GnomeCanvasGroup * boardRootItem = NULL
static GnomeCanvasGroup * allwagonsRootItem = NULL
static GnomeCanvasGroup * modelRootItem = NULL
static GnomeCanvasGroup * answerRootItem = NULL
static GList * listPixmapEngines = NULL
static GList * listPixmapWagons = NULL
static GnomeCanvasItem * item_model [MODEL_MAX_SIZE]
static GList * item_answer_list = NULL
static GList * int_answer_list = NULL
static GList * int_model_list = NULL
static int model_size = 0
static gint timer_id
static BoardPlugin menu_bp

Define Documentation

#define ENGINES   9

Definition at line 39 of file railroad.c.

Definition at line 43 of file railroad.c.

#define MODEL_PAUSE   30
#define NUMBER_OF_LEVELS   3

Definition at line 42 of file railroad.c.

#define NUMBER_OF_SUBLEVELS   3

Definition at line 41 of file railroad.c.

#define SOUNDLISTFILE   PACKAGE

Definition at line 22 of file railroad.c.

#define WAGONS   13

Definition at line 40 of file railroad.c.


Function Documentation

static void animate_model ( void  ) [static]

Definition at line 614 of file railroad.c.

                            {
  animation_pending = TRUE;
  animation_count = 0;

  gc_sound_play_ogg( "sounds/train.ogg", NULL );

  // warning : if timeout is too low, the model will not be displayed
  timer_id = gtk_timeout_add (100, (GtkFunction) animate_step, NULL);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static gboolean animate_step ( void  ) [static]

Definition at line 571 of file railroad.c.

                               {
  double step = 0;

  // this defines how the train waits before start
#define MODEL_PAUSE 30
  //   printf("+++animate_step %d \n",animation_count);

  if(board_paused)
    return TRUE;

  if(!gcomprisBoard)
    return FALSE;

  animation_count++;

  if (animation_count < MODEL_PAUSE)
    return TRUE;

  if (animation_count >= 160+MODEL_PAUSE) {
    if (timer_id) {
      gtk_timeout_remove (timer_id);
      timer_id = 0;
    }
    animation_pending = FALSE;
    gnome_canvas_item_hide(GNOME_CANVAS_ITEM(modelRootItem));
    /* Move back the model to its 0 position */
    gnome_canvas_item_set(GNOME_CANVAS_ITEM(modelRootItem),
                       "x", 0.0,
                       NULL);

    gnome_canvas_item_show(GNOME_CANVAS_ITEM(allwagonsRootItem));
    gnome_canvas_item_show(GNOME_CANVAS_ITEM(answerRootItem));
    return FALSE;
  }

  step = (double) (animation_count-MODEL_PAUSE) / 50.0;
  step *= step;

  gnome_canvas_item_move(GNOME_CANVAS_ITEM(modelRootItem), step, 0.0);

  return TRUE;
}

Here is the caller graph for this function:

static gint answer_event ( GnomeCanvasItem *  item,
GdkEvent *  event,
gpointer  data 
) [static]

Definition at line 493 of file railroad.c.

                                                                                {
  double item_x, item_y;
  int item_number, i;
  GnomeCanvasItem *local_item;
  item_number = GPOINTER_TO_INT(data);
  // we don't allow any input until train is gone
  if (animation_pending)
    return FALSE;

  item_x = event->button.x;
  item_y = event->button.y;
  gnome_canvas_item_w2i(item->parent, &item_x, &item_y);

  if(board_paused)
    return FALSE;

  switch (event->type)
    {
    case GDK_BUTTON_PRESS:
      g_warning("Deleting %d\n",item_number);
      local_item = g_list_nth_data(item_answer_list,item_number);
      item_answer_list = g_list_remove( item_answer_list, local_item );
      //      gtk_signal_disconnect(GTK_OBJECT(local_item), (GtkSignalFunc) answer_event, NULL);
      gtk_object_destroy (GTK_OBJECT(local_item));
      int_answer_list = g_list_remove(int_answer_list, g_list_nth_data(int_answer_list, item_number) );
      reposition_answer();
      // setup the signals for the cars at the right side of the deleted object
      for (i=item_number; i<g_list_length(item_answer_list); i++) {
       local_item = g_list_nth_data(item_answer_list, i);
       gtk_signal_disconnect_by_func(GTK_OBJECT(local_item), (GtkSignalFunc) answer_event, GINT_TO_POINTER( i+1 ));
        gtk_signal_connect(GTK_OBJECT(local_item),"event", (GtkSignalFunc) answer_event, GINT_TO_POINTER( i ));
      }
      break;

    default:
      break;
    }
  return FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void end_board ( void  ) [static]

Definition at line 192 of file railroad.c.

{
  GdkPixbuf * pixmap = NULL;
  // If we don't end animation, there may be a segfault if leaving while the animation is pending
  if (timer_id) {
    gtk_timeout_remove (timer_id);
    timer_id = 0;
  }

  if(gcomprisBoard!=NULL)
    {
      pause_board(TRUE);
      gc_score_end();
      railroad_destroy_all_items();

      while(g_list_length(listPixmapEngines)>0) {
       pixmap = g_list_nth_data(listPixmapEngines, 0);
       listPixmapEngines = g_list_remove (listPixmapEngines, pixmap);
       gdk_pixbuf_unref(pixmap);
      }

      while(g_list_length(listPixmapWagons)>0) {
       pixmap = g_list_nth_data(listPixmapWagons, 0);
       listPixmapWagons = g_list_remove (listPixmapWagons, pixmap);
       gdk_pixbuf_unref(pixmap);
      }

    }
  gcomprisBoard = NULL;
}

Here is the call graph for this function:

static void game_won ( void  ) [static]

Definition at line 393 of file railroad.c.

{
  gcomprisBoard->sublevel++;

  if(gcomprisBoard->sublevel>gcomprisBoard->number_of_sublevel) {
    /* Try the next level */
    gcomprisBoard->sublevel=1;
    gcomprisBoard->level++;
    if(gcomprisBoard->level>gcomprisBoard->maxlevel) { // the current board is finished : bail out
      gc_bonus_end_display(BOARD_FINISHED_RANDOM);
      return;
    }
    gc_sound_play_ogg ("sounds/bonus.ogg", NULL);
  }
  railroad_next_level();
}

Here is the call graph for this function:

Here is the caller graph for this function:

gboolean is_our_board ( GcomprisBoard *  gcomprisBoard) [static]

Definition at line 235 of file railroad.c.

{
  if (gcomprisBoard)
    {
      if(g_strcasecmp(gcomprisBoard->type, "railroad")==0)
       {
         /* Set the plugin entry */
         gcomprisBoard->plugin=&menu_bp;

         return TRUE;
       }
    }
  return FALSE;
}
static gint item_event ( GnomeCanvasItem *  item,
GdkEvent *  event,
gpointer  data 
) [static]

Definition at line 440 of file railroad.c.

                                                                              {
  double item_x, item_y;
  int item_number;
  GdkPixbuf * pixmap = NULL;
  int i, xOffset = 0;
  GnomeCanvasItem * local_item;
  double dx1, dy1, dx2, dy2;
  item_number = GPOINTER_TO_INT(data);

  // we don't allow any input until train is gone
  if (animation_pending)
    return FALSE;

  item_x = event->button.x;
  item_y = event->button.y;
  gnome_canvas_item_w2i(item->parent, &item_x, &item_y);

  if(board_paused)
    return FALSE;

  switch (event->type)
    {
    case GDK_BUTTON_PRESS:
      g_warning("GDK_BUTTON_PRESS item %d\tlength answer = %d\n",item_number,g_list_length(item_answer_list));
      xOffset = 0;
      for (i=0; i<g_list_length(item_answer_list); i++) {
       gnome_canvas_item_get_bounds(g_list_nth_data(item_answer_list,i), &dx1, &dy1, &dx2, &dy2);
       xOffset += dx2-dx1;
      }
      if (item_number < ENGINES)
       pixmap = g_list_nth_data(listPixmapEngines, item_number);
      else
       pixmap = g_list_nth_data(listPixmapWagons, item_number-ENGINES);

      local_item =gnome_canvas_item_new (answerRootItem,
                                    gnome_canvas_pixbuf_get_type (),
                                    "pixbuf",  pixmap,
                                    "x",  (double) xOffset,
                                    "y",  (double) line[0] - gdk_pixbuf_get_height(pixmap),
                                    NULL);
      item_answer_list = g_list_append(item_answer_list, local_item);
      int_answer_list = g_list_append(int_answer_list,GINT_TO_POINTER(item_number));
      //      printf("added %d to int_answer_list\n", item_number);
      gtk_signal_connect(GTK_OBJECT(local_item), "event", (GtkSignalFunc) answer_event, GINT_TO_POINTER( g_list_length(item_answer_list)-1 ));
      break;

    default:
      break;
    }
  return FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void pause_board ( gboolean  pause) [static]

Definition at line 123 of file railroad.c.

{
  if(gcomprisBoard==NULL)
    return;

  if(gamewon == TRUE && pause == FALSE) /* the game is won */
    {
      game_won();
    }

  board_paused = pause;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void process_ok ( void  ) [static]

Definition at line 411 of file railroad.c.

{
  int i;

  gamewon = TRUE;

  // DEBUG
  g_warning("l answer = %d\tl model = %d\n", g_list_length(int_answer_list), g_list_length(int_model_list));
  if (g_list_length(int_answer_list) != g_list_length(int_model_list))
    gamewon = FALSE;
  else
    for (i=0; i<g_list_length(int_answer_list); i++) {
      if ( GPOINTER_TO_INT(g_list_nth_data(int_answer_list,i)) != GPOINTER_TO_INT(g_list_nth_data(int_model_list,i))) {
       printf("pour i= %d --> différent\n", i);
       gamewon = FALSE;
       break;
      }
    }
  // DUMP lists
  g_warning("answer:\n");
  for (i=0; i<g_list_length(int_answer_list); i++)
    g_warning(" i = \t%d val = \t%d\n", i, GPOINTER_TO_INT(g_list_nth_data(int_answer_list,i)) );
  g_warning("model:\n");
  for (i=0; i<g_list_length(int_model_list); i++)
    g_warning(" i = \t%d val = \t%d\n", i, GPOINTER_TO_INT(g_list_nth_data(int_model_list,i)) );

  gc_bonus_display(gamewon, BONUS_FLOWER);
}

Here is the call graph for this function:

static GnomeCanvasItem * railroad_create_item ( GnomeCanvasGroup *  parent) [static]

Definition at line 291 of file railroad.c.

{
  int xOffset = 0, yOffset = 0;
  int i, r, l = 1;
  GdkPixbuf * pixmap = NULL;
  GnomeCanvasItem *item;

  boardRootItem = GNOME_CANVAS_GROUP(
                                 gnome_canvas_item_new (parent,
                                                     gnome_canvas_group_get_type (),
                                                     "x", (double) 0,
                                                     "y", (double) 0,
                                                     NULL));
  /* Create a root group for the answer */
  answerRootItem = GNOME_CANVAS_GROUP(
                                  gnome_canvas_item_new (boardRootItem,
                                                      gnome_canvas_group_get_type (),
                                                      "x", (double) 0,
                                                      "y", (double) 0,
                                                      NULL));

  // Create the vehicules
  allwagonsRootItem = GNOME_CANVAS_GROUP(
                                    gnome_canvas_item_new (boardRootItem,
                                                        gnome_canvas_group_get_type (),
                                                        "x", (double) 0,
                                                        "y", (double) 0,
                                                        NULL));

  for (i=0; i<ENGINES+WAGONS; i++) {
    if (i<ENGINES)
      pixmap = g_list_nth_data(listPixmapEngines, i);
    else
      pixmap = g_list_nth_data(listPixmapWagons, i-ENGINES);

    if ( (xOffset + gdk_pixbuf_get_width(pixmap)) >= gcomprisBoard->width) {
      xOffset = 0;
      l++;
    }
    yOffset = line[l] - gdk_pixbuf_get_height(pixmap);

    item = gnome_canvas_item_new (allwagonsRootItem,
                              gnome_canvas_pixbuf_get_type (),
                              "pixbuf",  pixmap,
                              "x",  (double) xOffset,
                              "y",  (double) yOffset,
                              NULL);
    xOffset += gdk_pixbuf_get_width(pixmap);

    gtk_signal_connect(GTK_OBJECT(item), "event", (GtkSignalFunc) item_event,
                     GINT_TO_POINTER(i));

  }
  // hide them
  gnome_canvas_item_hide(GNOME_CANVAS_ITEM(allwagonsRootItem));

  // construct the model to be recognized
  modelRootItem = GNOME_CANVAS_GROUP(
                                 gnome_canvas_item_new (boardRootItem,
                                                     gnome_canvas_group_get_type (),
                                                     "x", (double) 0,
                                                     "y", (double) 0,
                                                     NULL));

  yOffset = line[0];
  xOffset = 0;
  model_size = gcomprisBoard->level +1; // engine + cars
  // First the cars, depending of the level
  for (i=0; i<model_size-1; i++) {
    r = (int)(((float) WAGONS)*rand()/(RAND_MAX+1.0));
    g_assert( r >=0 && r < WAGONS);
    // keep track of the answer
    int_model_list = g_list_append(int_model_list, GINT_TO_POINTER(r+ENGINES));
    pixmap = g_list_nth_data(listPixmapWagons, r);
    g_assert(i >= 0 && i<MODEL_MAX_SIZE);
    item_model[i] =gnome_canvas_item_new (modelRootItem,
                                     gnome_canvas_pixbuf_get_type (),
                                     "pixbuf",  pixmap,
                                     "x",  (double) xOffset,
                                     "y",  (double) yOffset - gdk_pixbuf_get_height(pixmap),
                                     NULL);
    xOffset  += gdk_pixbuf_get_width(pixmap);
  }

  // Then the engine
  r = (int)(((float) ENGINES)*rand()/(RAND_MAX+1.0));
  g_assert( r >=0 && r < ENGINES);
  // keep track of the answer
  int_model_list = g_list_append(int_model_list, GINT_TO_POINTER(r));
  pixmap = g_list_nth_data(listPixmapEngines, r);
  item_model[model_size-1] =gnome_canvas_item_new (modelRootItem,
                                             gnome_canvas_pixbuf_get_type (),
                                             "pixbuf",  pixmap,
                                             "x",  (double) xOffset,
                                             "y",  (double) yOffset  - gdk_pixbuf_get_height(pixmap),
                                             NULL);

  animate_model();

  return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void railroad_destroy_all_items ( void  ) [static]

Definition at line 283 of file railroad.c.

{
  if(boardRootItem!=NULL)
    gtk_object_destroy (GTK_OBJECT(boardRootItem));

  boardRootItem = NULL;
}

Here is the caller graph for this function:

static void railroad_next_level ( void  ) [static]

Definition at line 264 of file railroad.c.

{
  gc_bar_set_level(gcomprisBoard);

  reset_all_lists();
  // I have big troubles with the GList API : the worst I have ever seen !
  g_assert(g_list_length(item_answer_list) == 0 && g_list_length(int_answer_list) == 0 && g_list_length(int_model_list) == 0);

  model_size = 0;

  railroad_destroy_all_items();
  gamewon = FALSE;
  gc_score_set(gcomprisBoard->sublevel);

  /* Try the next level */
  railroad_create_item(gnome_canvas_root(gcomprisBoard->canvas));
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void repeat ( void  ) [static]

Definition at line 251 of file railroad.c.

{
  if(gcomprisBoard!=NULL && !animation_pending) {
    gnome_canvas_item_hide(GNOME_CANVAS_ITEM(answerRootItem));
    gnome_canvas_item_show(GNOME_CANVAS_ITEM(modelRootItem));
    gnome_canvas_item_hide(GNOME_CANVAS_ITEM(allwagonsRootItem));
    reposition_model();
    animate_model();
  }
}

Here is the call graph for this function:

static void reposition_answer ( void  ) [static]

Definition at line 533 of file railroad.c.

                                {
  double dx1, dy1, dx2, dy2;
  int i;
  int xOffset = 0;
  GnomeCanvasItem * item = NULL;

  if(!gcomprisBoard)
    return;

  g_warning("+++ reposition_answer\n");
  for (i=0; i<g_list_length(item_answer_list); i++) {
    item = g_list_nth_data(item_answer_list,i);
    gnome_canvas_item_get_bounds(item, &dx1, &dy1, &dx2, &dy2);
    gnome_canvas_item_move(item, xOffset-dx1, line[0]-dy2);
    xOffset += dx2-dx1;
  }
}

Here is the caller graph for this function:

static void reposition_model ( void  ) [static]

Definition at line 551 of file railroad.c.

                               {
  double dx1, dy1, dx2, dy2;
  int i;
  int xOffset = 0;
  GnomeCanvasItem * item = NULL;

  if(!gcomprisBoard)
    return;

  g_warning("+++ reposition_model\n");
  gnome_canvas_item_move(GNOME_CANVAS_ITEM(modelRootItem), 0, 0);
  for (i=0; i<model_size; i++) {
    item = item_model[i];
    gnome_canvas_item_get_bounds(item, &dx1, &dy1, &dx2, &dy2);
    gnome_canvas_item_move(item, xOffset-dx1, line[0]-dy2);
    xOffset += dx2-dx1;
  }
}

Here is the caller graph for this function:

static void reset_all_lists ( void  ) [static]

Definition at line 624 of file railroad.c.

                                  {
  GnomeCanvasItem *item;

  int_model_list = reset_list(int_model_list);
  int_answer_list = reset_list(int_answer_list);

  while(g_list_length(item_answer_list)>0) {
    item = g_list_nth_data(item_answer_list, 0);
    item_answer_list = g_list_remove (item_answer_list, item);
    // causes segfaults
    //        gtk_object_destroy (GTK_OBJECT(item));
  }

}

Here is the call graph for this function:

Here is the caller graph for this function:

static GList * reset_list ( GList *  list) [static]

Definition at line 639 of file railroad.c.

                                        {
  while (g_list_length(list) > 0)
    list = g_list_remove(list, g_list_nth_data(list,0));

  return list;
}

Here is the caller graph for this function:

static void set_level ( guint  level) [static]

Definition at line 224 of file railroad.c.

{

  if(gcomprisBoard!=NULL)
    {
      gcomprisBoard->level=level;
      gcomprisBoard->sublevel=1;
      railroad_next_level();
    }
}

Here is the call graph for this function:

static void start_board ( GcomprisBoard *  agcomprisBoard) [static]

Definition at line 137 of file railroad.c.

{
  int i;
  char *str;
  GdkPixbuf *pixmap = NULL;

  if(agcomprisBoard!=NULL)
    {
      gcomprisBoard=agcomprisBoard;
      gc_set_background(gnome_canvas_root(gcomprisBoard->canvas),
                           "railroad/railroad-bg.png");

      for (i=0; i<ENGINES; i++) {
       str = g_strdup_printf("railroad/loco%d.png", i+1);
       pixmap = gc_pixmap_load(str);
       listPixmapEngines = g_list_append(listPixmapEngines, pixmap);
       g_free(str);
      }

      for (i=0; i<WAGONS; i++) {
       str = g_strdup_printf("railroad/wagon%d.png", i+1);
       pixmap = gc_pixmap_load(str);
       listPixmapWagons = g_list_append(listPixmapWagons, pixmap);
       g_free(str);
      }

      animation_pending = FALSE;
      gcomprisBoard->level=1;
      gcomprisBoard->maxlevel=NUMBER_OF_LEVELS;
      gcomprisBoard->sublevel=1;
      gcomprisBoard->number_of_sublevel=NUMBER_OF_SUBLEVELS; /* Go to next level after this number of 'play' */
      gc_score_start(SCORESTYLE_NOTE,
                        gcomprisBoard->width - 220,
                        gcomprisBoard->height - 50,
                        gcomprisBoard->number_of_sublevel);


      str = gc_skin_image_get("button_reload.png");
      pixmap = gc_pixmap_load(str);
      g_free(str);
      if(pixmap) {
       gc_bar_set_repeat_icon(pixmap);
       gdk_pixbuf_unref(pixmap);
       gc_bar_set(GC_BAR_LEVEL|GC_BAR_OK|GC_BAR_REPEAT_ICON);
      } else {
       gc_bar_set(GC_BAR_LEVEL|GC_BAR_OK|GC_BAR_REPEAT);
      }

      railroad_next_level();

      gamewon = FALSE;
      pause_board(FALSE);
    }
}

Here is the call graph for this function:


Variable Documentation

GnomeCanvasGroup* allwagonsRootItem = NULL [static]

Definition at line 51 of file railroad.c.

gint animation_count = 0 [static]

Definition at line 47 of file railroad.c.

gboolean animation_pending [static]

Definition at line 46 of file railroad.c.

GnomeCanvasGroup* answerRootItem = NULL [static]

Definition at line 53 of file railroad.c.

gboolean board_paused = TRUE [static]

Definition at line 25 of file railroad.c.

GnomeCanvasGroup* boardRootItem = NULL [static]

Definition at line 49 of file railroad.c.

int gamewon [static]

Definition at line 32 of file railroad.c.

GcomprisBoard* gcomprisBoard = NULL [static]

Definition at line 24 of file railroad.c.

GList* int_answer_list = NULL [static]

Definition at line 66 of file railroad.c.

GList* int_model_list = NULL [static]

Definition at line 68 of file railroad.c.

GList* item_answer_list = NULL [static]

Definition at line 64 of file railroad.c.

GnomeCanvasItem* item_model[MODEL_MAX_SIZE] [static]

Definition at line 62 of file railroad.c.

const int line[] = { 100,180,260,340, 420, 500} [static]

Definition at line 45 of file railroad.c.

GList* listPixmapEngines = NULL [static]

Definition at line 55 of file railroad.c.

GList* listPixmapWagons = NULL [static]

Definition at line 56 of file railroad.c.

BoardPlugin menu_bp [static]
Initial value:
  {
    NULL,
    NULL,
    N_("Memory game"),
    N_("Build a train according to the model"),
    "Pascal Georges pascal.georges1@free.fr>",
    NULL,
    NULL,
    NULL,
    NULL,
    start_board,
    pause_board,
    end_board,
    is_our_board,
    NULL,
    process_ok,
    set_level,
    NULL,
    repeat,
    NULL,
    NULL
  }

Definition at line 87 of file railroad.c.

int model_size = 0 [static]

Definition at line 70 of file railroad.c.

GnomeCanvasGroup* modelRootItem = NULL [static]

Definition at line 52 of file railroad.c.

gint timer_id [static]

Definition at line 71 of file railroad.c.