Back to index

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

Go to the source code of this file.

Classes

struct  PieceItem

Defines

#define SOUNDLISTFILE   PACKAGE
#define MAX_NUMBER_X   3
#define MAX_NUMBER_Y   10

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 game_won (void)
static GnomeCanvasItem * hanoi_create_item (GnomeCanvasGroup *parent)
static void hanoi_destroy_all_items (void)
static void hanoi_next_level (void)
static gint item_event (GnomeCanvasItem *item, GdkEvent *event, PieceItem *data)
static gboolean is_completed ()

Variables

static GcomprisBoard * gcomprisBoard = NULL
static gboolean board_paused = TRUE
static int gamewon
static GnomeCanvasGroup * boardRootItem = NULL
static PieceItemposition [MAX_NUMBER_X][MAX_NUMBER_Y]
static int number_of_item = 0
static int number_of_item_x = MAX_NUMBER_X
static int number_of_item_y = 0
static int item_width
static int item_height
static BoardPlugin menu_bp

Class Documentation

struct PieceItem

Definition at line 44 of file hanoi.c.

Class Members
gint color
gint i
GnomeCanvasItem * item
GnomeCanvasItem * item_text
gint j
gboolean on_top
gint width
double x
double xt
double y
double yt

Define Documentation

#define MAX_NUMBER_X   3

Definition at line 57 of file hanoi_real.c.

#define MAX_NUMBER_Y   10

Definition at line 58 of file hanoi_real.c.

#define SOUNDLISTFILE   PACKAGE

Definition at line 22 of file hanoi_real.c.


Function Documentation

static void end_board ( void  ) [static]

Definition at line 143 of file hanoi_real.c.

{
  if(gcomprisBoard!=NULL)
    {
      pause_board(TRUE);
      hanoi_destroy_all_items();
    }
  gcomprisBoard = NULL;
}

Here is the call graph for this function:

static void game_won ( void  ) [static]

Definition at line 395 of file hanoi_real.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);
  }
  hanoi_next_level();
}

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 241 of file hanoi_real.c.

{
  int i,j;
  double gap_x, gap_y;
  double baseline;
  GnomeCanvasItem *item = NULL;
  GdkPixbuf *pixmap = NULL;
  gchar *filename;

  boardRootItem = GNOME_CANVAS_GROUP(
                                 gnome_canvas_item_new (gnome_canvas_root(gcomprisBoard->canvas),
                                                     gnome_canvas_group_get_type (),
                                                     "x", (double) 0,
                                                     "y", (double) 0,
                                                     NULL));

  pixmap = gc_skin_pixmap_load("gcompris-shapelabel.png");
  if(pixmap) {
    gnome_canvas_item_new (boardRootItem,
                        gnome_canvas_pixbuf_get_type (),
                        "pixbuf", pixmap,
                        "x",       (double)BOARDWIDTH/2,
                        "y",       (double)BOARDHEIGHT - 35,
                        "width", (double) BOARDWIDTH - 20,
                        "width_set", TRUE,
                        "anchor", GTK_ANCHOR_CENTER,
                        NULL);
    gdk_pixbuf_unref(pixmap);
  }

  gnome_canvas_item_new (boardRootItem,
                      gnome_canvas_text_get_type (),
                      "text", _("Move the entire stack to the right peg, one disc at a time"),
                      "font", gc_skin_font_board_medium,
                      "x", (double) BOARDWIDTH/2 +1,
                      "y", (double) BOARDHEIGHT - 50 +1,
                      "anchor", GTK_ANCHOR_NORTH,
                      "fill_color_rgba", gc_skin_color_shadow,
                      "justification", GTK_JUSTIFY_CENTER,
                      NULL);

  gnome_canvas_item_new (boardRootItem,
                      gnome_canvas_text_get_type (),
                      "text", _("Move the entire stack to the right peg, one disc at a time"),
                      "font", gc_skin_font_board_medium,
                      "x", (double) BOARDWIDTH/2,
                      "y", (double) BOARDHEIGHT - 50,
                      "anchor", GTK_ANCHOR_NORTH,
                      "fill_color_rgba", gc_skin_color_text_button,
                      "justification", GTK_JUSTIFY_CENTER,
                      NULL);


  /*----------------------------------------*/
  /* Empty the solution */
  for(i=0; i<number_of_item_x; i++)
    {
      for(j=0; j<number_of_item_y; j++)
       {
         position[i][j] = g_malloc(sizeof(PieceItem));
         position[i][j]->width  = -1;
         position[i][j]->i      = i;
         position[i][j]->j      = j;
         position[i][j]->on_top = FALSE;
       }
    }

  /* Initialize the left positions */
  for(j=0; j<number_of_item_y; j++)
    {
      position[0][j]->width = number_of_item_y - j;
    }

  /* Mark the top piece */
  position[0][number_of_item_y-1]->on_top = TRUE;

  /*dump_solution();*/

  /*----------------------------------------*/
  /* Display it now */

  item_width  = BOARDWIDTH / (number_of_item_x);
  item_height = 30;

  gap_x = item_width  * 0.1;
  gap_y = item_height * 0.25;

  baseline = BOARDHEIGHT/2 + item_height * number_of_item_y/2;

  number_of_item = 0;

  for(i=0; i<number_of_item_x; i++)
    {
      if(i==number_of_item_x-1)
       {
         /* Create the backgound for the target */
         gnome_canvas_item_new (boardRootItem,
                             gnome_canvas_rect_get_type (),
                             "x1", (double) item_width * i + gap_x/2,
                             "y1", (double) baseline - item_height * number_of_item_y - gap_y - 50,
                             "x2", (double) item_width * (i+1) - gap_x/2,
                             "y2", (double) baseline + 50,
                             "fill_color_rgba", 0x036ED8FF,
                             "outline_color", "black",
                             "width_units", (double)1,
                             NULL);
       }

      /* The disc support */
      pixmap = gc_pixmap_load ("images/disc_support.png");

      item = gnome_canvas_item_new (boardRootItem,
                                gnome_canvas_pixbuf_get_type (),
                                "x", (double) item_width * i + item_width/2,
                                "y", (double) baseline - gdk_pixbuf_get_height(pixmap)/2 + item_height/2,
                                "pixbuf", pixmap,
                                "anchor", GTK_ANCHOR_CENTER,
                                NULL);

      gdk_pixbuf_unref(pixmap);


      for(j=0; j<number_of_item_y; j++)
       {

         position[i][j]->x = item_width * i + item_width/2;
         position[i][j]->y = baseline - item_height * j - item_height + gap_y;

         if(position[i][j]->width != -1)
           {
             filename = g_strdup_printf("%s%d.png", "images/disc", j+1);
             pixmap = gc_pixmap_load (filename);

             item = gnome_canvas_item_new (boardRootItem,
                                       gnome_canvas_pixbuf_get_type (),
                                       "pixbuf", pixmap,
                                       "x", position[i][j]->x,
                                       "y", position[i][j]->y,
                                       "anchor", GTK_ANCHOR_CENTER,
                                       NULL);
             g_free(filename);
             gdk_pixbuf_unref(pixmap);

             position[i][j]->item = item;

             gtk_signal_connect(GTK_OBJECT(item), "event", (GtkSignalFunc) item_event,  position[i][j]);

           }
       }
    }

  return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void hanoi_destroy_all_items ( void  ) [static]

Definition at line 199 of file hanoi_real.c.

{
  guint i,j;

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

      /* Cleanup our memory structure */
      for(i=0; i<number_of_item_x; i++)
       {
         for(j=0; j<number_of_item_y; j++)
           {
             g_free(position[i][j]);
           }
       }
    }
  boardRootItem = NULL;

}

Here is the caller graph for this function:

static void hanoi_next_level ( void  ) [static]

Definition at line 183 of file hanoi_real.c.

{

  gc_bar_set_level(gcomprisBoard);

  hanoi_destroy_all_items();
  gamewon = FALSE;

  /* Select level difficulty */
  number_of_item_y = gcomprisBoard->level + 2;

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

Here is the call graph for this function:

Here is the caller graph for this function:

static gboolean is_completed ( ) [static]

Definition at line 415 of file hanoi_real.c.

{
  gint j;
  gboolean done = TRUE;

  for(j=0; j<number_of_item_y; j++)
    {
      if(position[number_of_item_x-1][j]->width != number_of_item_y - j)
       done = FALSE;
    }

  return done;
}

Here is the caller graph for this function:

static gboolean is_our_board ( GcomprisBoard *  gcomprisBoard) [static]

Definition at line 165 of file hanoi_real.c.

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

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

Definition at line 431 of file hanoi_real.c.

{
   static double x, y;
   double new_x, new_y;
   GdkCursor *fleur;
   static int dragging;
   double item_x, item_y;

   if(!gcomprisBoard)
     return FALSE;

  if(board_paused)
    return FALSE;

  if(!data->on_top)
    return FALSE;

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

  switch (event->type)
    {
    case GDK_ENTER_NOTIFY:
      gc_item_focus_set(item, TRUE);
      break;
    case GDK_LEAVE_NOTIFY:
      gc_item_focus_set(item, FALSE);
      break;
    case GDK_BUTTON_PRESS:
      switch(event->button.button)
       {
       case 1:

         x = item_x;
         y = item_y;

         gnome_canvas_item_raise_to_top(data->item);

         fleur = gdk_cursor_new(GDK_FLEUR);
         gc_canvas_item_grab(data->item,
                             GDK_POINTER_MOTION_MASK |
                             GDK_BUTTON_RELEASE_MASK,
                             fleur,
                             event->button.time);
         gdk_cursor_destroy(fleur);
         dragging = TRUE;
         break;
       }
      break;

    case GDK_MOTION_NOTIFY:
      if (dragging && (event->motion.state & GDK_BUTTON1_MASK))
       {
         new_x = item_x;
         new_y = item_y;

         gnome_canvas_item_move(data->item, new_x - x, new_y - y);
         x = new_x;
         y = new_y;
       }
      break;

    case GDK_BUTTON_RELEASE:
      if(dragging)
       {
         gint i;
         gint tmpi, tmpj;
         double tmpx, tmpy;
         PieceItem *piece_src;
         PieceItem *piece_dst;
         gint line;
         gint col=-1;
         double disc_w, disc_h;
         GdkPixbuf *pixmap;

         g_object_get(G_OBJECT(data->item), "pixbuf", &pixmap, NULL);
         disc_w = gdk_pixbuf_get_width(pixmap)/2;
         disc_h = gdk_pixbuf_get_height(pixmap)/2;
         gdk_pixbuf_unref(pixmap);

         gc_canvas_item_ungrab(data->item, event->button.time);
         dragging = FALSE;

         /* Search the column (x) where this item is ungrabbed */
         if(item_x > (position[number_of_item_x-1][0]->x
                     - (position[number_of_item_x-1][0]->x - position[number_of_item_x-2][0]->x) / 2))
            col = number_of_item_x-1;
         else if(item_x < position[0][0]->x)
           col = 0;
         else {
           for(i=0; i<number_of_item_x-1; i++) {
             int distance = (position[i+1][0]->x - position[i][0]->x) / 2;
             if(position[i][0]->x -  distance < item_x &&
               position[i+1][0]->x - distance > item_x)
              col = i;
           }
         }

         /* Bad drop / Outside of column area */
         /* Bad drop / On the same column */
         if(col<0 || col > number_of_item_x || col == data->i)
           {
             /* Return to the original position */
             gc_item_absolute_move (data->item , data->x - disc_w, data->y - disc_h);

             /* FIXME : Workaround for bugged canvas */
             gnome_canvas_update_now(gcomprisBoard->canvas);

             return FALSE;
           }


         /* Now search the free line (y) */
         line = number_of_item_y;
         for(i=number_of_item_y-1; i>=0; i--)
           if(position[col][i]->width == -1)
             line = i;

         /* Bad drop / Too many pieces here or larger disc is above */
         if(line > number_of_item_y ||
            (line > 0 && position[col][line-1]->width != -1 && position[col][line-1]->width < data->width))
           {
             /* Return to the original position */
             gc_item_absolute_move (data->item , data->x - disc_w, data->y - disc_h);

             /* FIXME : Workaround for bugged canvas */
             gnome_canvas_update_now(gcomprisBoard->canvas);

             return FALSE;
           }

         /* Update ontop values for the piece under the grabbed one */
         if(data->j>0)
           position[data->i][data->j-1]->on_top = TRUE;

         /* Update ontop values for the piece under the ungrabbed one */
         if(line>0)
           position[col][line-1]->on_top = FALSE;

         /* Move the piece */
         piece_dst = position[col][line];
         piece_src = data;

         gc_item_absolute_move (data->item,
                           piece_dst->x - disc_w,
                           piece_dst->y - disc_h);

         /* FIXME : Workaround for bugged canvas */
         gnome_canvas_update_now(gcomprisBoard->canvas);

         /* Swap values in the pieces */
         tmpx    = data->x;
         tmpy    = data->y;
         piece_src->x = piece_dst->x;
         piece_src->y = piece_dst->y;
         piece_dst->x = tmpx;
         piece_dst->y = tmpy;

         tmpi    = data->i;
         tmpj    = data->j;
         position[tmpi][tmpj]->i = piece_dst->i;
         position[tmpi][tmpj]->j = piece_dst->j;
         piece_dst->i  = tmpi;
         piece_dst->j  = tmpj;

         position[piece_src->i][piece_src->j] = piece_src;
         position[piece_dst->i][piece_dst->j] = piece_dst;

         /*dump_solution();*/
         if(is_completed())
           {
             gamewon = TRUE;
             hanoi_destroy_all_items();
             gc_bonus_display(gamewon, BONUS_SMILEY);
           }
       }
      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 104 of file hanoi_real.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 set_level ( guint  level) [static]

Definition at line 154 of file hanoi_real.c.

{

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

Here is the call graph for this function:

static void start_board ( GcomprisBoard *  agcomprisBoard) [static]

Definition at line 119 of file hanoi_real.c.

{

  if(agcomprisBoard!=NULL)
    {
      gcomprisBoard=agcomprisBoard;
      gcomprisBoard->level=1;
      gcomprisBoard->maxlevel=2;
      gcomprisBoard->sublevel=1;
      gcomprisBoard->number_of_sublevel=1; /* Go to next level after this number of 'play' */
      gc_bar_set(GC_BAR_LEVEL);

      gc_set_background(gnome_canvas_root(gcomprisBoard->canvas),
                           gc_skin_image_get("gcompris-bg.jpg"));

      boardRootItem = NULL;

      hanoi_next_level();

      gamewon = FALSE;
      pause_board(FALSE);
    }
}

Here is the call graph for this function:


Variable Documentation

gboolean board_paused = TRUE [static]

Definition at line 25 of file hanoi_real.c.

GnomeCanvasGroup* boardRootItem = NULL [static]

Definition at line 35 of file hanoi_real.c.

int gamewon [static]

Definition at line 32 of file hanoi_real.c.

GcomprisBoard* gcomprisBoard = NULL [static]

Definition at line 24 of file hanoi_real.c.

int item_height [static]

Definition at line 65 of file hanoi_real.c.

int item_width [static]

Definition at line 64 of file hanoi_real.c.

BoardPlugin menu_bp [static]
Initial value:
  {
    NULL,
    NULL,
    N_("Tower of Hanoi"),
    "",
    "Bruno Coudoin <bruno.coudoin@free.fr>",
    NULL,
    NULL,
    NULL,
    NULL,
    start_board,
    pause_board,
    end_board,
    is_our_board,
    NULL,
    NULL,
    set_level,
    NULL,
    NULL,
    NULL,
    NULL
  }

Definition at line 68 of file hanoi_real.c.

int number_of_item = 0 [static]

Definition at line 61 of file hanoi_real.c.

Definition at line 62 of file hanoi_real.c.

int number_of_item_y = 0 [static]

Definition at line 63 of file hanoi_real.c.

Definition at line 59 of file hanoi_real.c.