/****************************************************************
 ***                                                          ***
 ***     widget.c                                             ***
 ***         The 16 puzzle.  Demonstrate SetWidgetPosition    ***
 ***                                                          ***
 ****************************************************************/
/*
 * This demo implements the well known 16 puzzle. It is implemented
 * by playing with widget positions. In general, the positions of
 * EZ widgets should be left to the EZ library.
 */
#include "EZ.h"
#define ABSV(x) ( x > 0? x: -(x))

extern void  exit();
static int   button_callback(); 
static int   randomize(); 
static EZ_Widget *buttons[4][4];     /* the buttons         */
static int width = 39, height = 33;  /* size of the buttons */
static int emptyx = 3, emptyy = 3;   /* the empty slot      */

main(ac, av)
     int  ac;
     char **av;
{
  int        i,j, k;
  char       str[4];
  EZ_Widget  *toplevel, *frame, *label, *tmp, *tmp1;
  
  EZ_Initialize(ac,av,1);
  toplevel = EZ_CreateFrame(NULL,NULL);                   /* the toplevel frame */
  EZ_ConfigureWidget(toplevel, EZ_STACKING, EZ_VERTICAL,
		     EZ_WIDTH, 200, EZ_HEIGHT, 300, 0);

  label = EZ_CreateLabel(toplevel, "The 16 Puzzle Demo"); /* a label */
  EZ_ConfigureWidget(label, EZ_FOREGROUND, "blue",
		     EZ_FONT_NAME,  "-Adobe-Times-Bold-R-Normal--*-180-*-*-*-*-*-*", 
		     0);
  frame = EZ_CreateFrame(toplevel, NULL);                 /* the button box  */
  EZ_ConfigureWidget(frame, EZ_PADX,0, EZ_PADY,0,
		     EZ_BORDER_TYPE,EZ_BORDER_DOWN, 
		     EZ_BORDER_WIDTH, 2, 0);

  tmp = EZ_CreateFrame(toplevel, NULL); 
  tmp1 = EZ_CreateButton(tmp, "Quit",0);                  /* the quit button  */
  EZ_ConfigureWidget(tmp1, EZ_CALLBACK, exit, 0);
  tmp1 = EZ_CreateButton(tmp, "Scramble",0);              /* the new game btn */
  EZ_ConfigureWidget(tmp1, EZ_CALLBACK, randomize, 0);

  for(i = 0; i < 4; i++)  
    for(j = 0; j < 4; j++)
      {
	if(i + j != 6) /* need 15 buttons, ignore the last one */
	  {
	    k = 4 * i + j;
	    sprintf(str,"%d",k+1);
	    tmp = buttons[i][j] = EZ_CreateButton(frame,str,-1);
	    EZ_SetWidgetIntData(tmp, k);
	    EZ_ConfigureWidget(tmp, EZ_X, 3 + j * width, EZ_Y, 3 + i * height,
			       EZ_WIDTH, width, EZ_HEIGHT, height, 
			       EZ_CALLBACK, button_callback, 0);
	  }
      }
  srand(getpid());
  EZ_DisplayWidget(toplevel);
  EZ_EventMainLoop();
}
/******************************************************************************/
static int button_callback(widget)
     EZ_Widget *widget;
{
  int tmp, x, y;

  tmp = EZ_GetWidgetIntData(widget);
  x = tmp >> 2;
  y = tmp & 0x3;

  if(ABSV(emptyx - x) + ABSV(emptyy - y) == 1) /* next to the empty square */
    {
      int tx = emptyx, ty = emptyy;
      emptyx = x; emptyy = y;
      EZ_SetWidgetIntData(widget, 4 * tx + ty);
      EZ_SetWidgetPosition(widget, 3 + ty * width, 3 + tx * height);
    }
}
/******************************************************************************/
static int randomize(widget)
     EZ_Widget *widget;
{
  int i, x, y;
  for(i = 0; i < 512; i++)
    {
      x = (rand()>> 5) % 4;
      y = (rand()>> 5) % 4;
      if((x + y != 6)) button_callback(buttons[x][y]);
    }
}
/******************************************************************************/
