/* Hooks for an X11 game display for GNU Robots */

/* Copyright (C) 1998 Jim Hall, jhall1@isd.net 
   Modified from curses.c by Tom Whittock, 1998 */

/*
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/xpm.h>

#include <string.h>
#include <stdio.h>				/* for printf */
#include <unistd.h>				/* for usleep */
#include "hooks.h"
#include "api.h"
  
Display *dpy;
Window x_win;
GC gc, buf_gc;
Font text;
Atom delete_win;

#define TILE_SIZE 16
int ncols, 
    nrows,
    robot_score,
    robot_shields,
    robot_energy,
    robot_dir;

Pixmap win_buf,
       statusbar,
       space,
       food,
       wall,
       prize,
       baddie;

/* Prototype needed functions */
void exit_nicely (void);

/* Functions in this file */
void x11_update (const char *s);

/* hooks to add things to the displayed map */

/* note that hook_delete_thing(x,y) is the same as
   hook_add_thing(x,y,space) */

void
hook_add_thing (int x, int y, int thing)
{
  int w_x, w_y;
  
  w_x = x * TILE_SIZE;
  w_y = y * TILE_SIZE;
  
  switch (thing) {
    case SPACE :
      XCopyArea(dpy, space, win_buf, gc, 0, 0, TILE_SIZE, TILE_SIZE, w_x, w_y);
      break;
    case FOOD :
      XCopyArea(dpy, food, win_buf, gc, 0, 0, TILE_SIZE, TILE_SIZE, w_x, w_y);
      break;
    case PRIZE :
      XCopyArea(dpy, prize, win_buf, gc, 0, 0, TILE_SIZE, TILE_SIZE, w_x, w_y);
      break;
    case WALL :
      XCopyArea(dpy, wall, win_buf, gc, 0, 0, TILE_SIZE, TILE_SIZE, w_x, w_y);
      break;
    case BADDIE :
      XCopyArea(dpy, baddie, win_buf, gc, 0, 0, TILE_SIZE, TILE_SIZE, w_x, w_y);
      break;
    case ROBOT :
      hook_add_robot (x, y, robot_dir);
      break;
    default :
      XCopyArea(dpy, wall, win_buf, gc, 0, 0, TILE_SIZE, TILE_SIZE, w_x, w_y);
      break;
  }
  XFlush(dpy);
}

void
hook_add_robot (int x, int y, int cdir)
{
#include "xpm/robot_north.xpm"
#include "xpm/robot_east.xpm"
#include "xpm/robot_south.xpm"
#include "xpm/robot_west.xpm"

  int w_x, w_y;
  Pixmap robotN,
         robotE,
         robotW,
         robotS;

  XpmCreatePixmapFromData(dpy, x_win, robot_north_xpm, &robotN, (Pixmap *) NULL,
			  (XpmAttributes *) NULL);
  XpmCreatePixmapFromData(dpy, x_win, robot_east_xpm, &robotE, (Pixmap *) NULL,
			  (XpmAttributes *) NULL);
  XpmCreatePixmapFromData(dpy, x_win, robot_west_xpm, &robotW, (Pixmap *) NULL,
			  (XpmAttributes *) NULL);
  XpmCreatePixmapFromData(dpy, x_win, robot_south_xpm, &robotS, (Pixmap *) NULL,
			  (XpmAttributes *) NULL);

  w_x = x * TILE_SIZE;
  w_y = y * TILE_SIZE;
  switch (cdir) {
  case 'N':
    XCopyArea(dpy, robotN, win_buf, gc, 0, 0, TILE_SIZE, TILE_SIZE, w_x, w_y);
    break;
  case 'E':
    XCopyArea(dpy, robotE, win_buf, gc, 0, 0, TILE_SIZE, TILE_SIZE, w_x, w_y);
    break;
  case 'W':
    XCopyArea(dpy, robotW, win_buf, gc, 0, 0, TILE_SIZE, TILE_SIZE, w_x, w_y);
    break;
  case 'S':
    XCopyArea(dpy, robotS, win_buf, gc, 0, 0, TILE_SIZE, TILE_SIZE, w_x, w_y);
    break;
  }
}

/* hooks to animate the robot */

void
hook_robot_smell (int x, int y, int cdir)
{
  x11_update ("robot sniffs..");
}

void
hook_robot_zap (int x, int y, int cdir, int x_to, int y_to)
{
  x11_update ("robot fires little gun..");
}

void
hook_robot_feel (int x, int y, int cdir, int x_to, int y_to)
{
  x11_update ("robot feels for thing..");
}

void
hook_robot_look (int x, int y, int cdir, int x_to, int y_to)
{
  x11_update ("robot looks for thing..");
}

void
hook_robot_grab (int x, int y, int cdir, int x_to, int y_to)
{
  x11_update ("robot grabs thing..");
}

void
hook_init (void)
{
  /* Initialize X11 */
#include "xpm/statusbar.xpm"
#include "xpm/space.xpm"
#include "xpm/food.xpm"
#include "xpm/wall.xpm"
#include "xpm/prize.xpm"
#include "xpm/baddie.xpm"
  
  Atom prots[6];
  XClassHint classhint;
  XWMHints *hints;
  XGCValues values;
  int x;
      
  if ((dpy = XOpenDisplay("")) == NULL) {
    printf("Couldn't open the X Server Display!\n");
    exit(1); /* Exit nicely isn't needed yet, and causes segfault */
  }
  
  delete_win = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
  
  x_win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 
          ncols*TILE_SIZE, nrows*TILE_SIZE+32, 0, 0, 0);
  
  prots[0] = delete_win;
  XSetWMProtocols(dpy, x_win, prots, 1);
  
  XStoreName(dpy, x_win, "GNU Robots");
  
  classhint.res_name = "robots";
  classhint.res_class = "Robots";
  XSetClassHint(dpy, x_win, &classhint);
  
  /* XSetCommand() seems to segfault... */
  
  hints = XAllocWMHints();
  hints->window_group = x_win;
  hints->flags = WindowGroupHint;
  XSetWMHints(dpy, x_win, hints);
  
  XMapWindow(dpy, x_win);

  text = XLoadFont(dpy, "-*-helvetica-medium-r-*-*-*-120-*-*-*-*-*-*");
  values.font = text;
  values.foreground = WhitePixel(dpy, DefaultScreen(dpy));  

  gc = XCreateGC(dpy, x_win, GCFont|GCForeground, &values);

  win_buf = XCreatePixmap(dpy, x_win, ncols*TILE_SIZE, nrows*TILE_SIZE+32, 
                          DefaultDepth(dpy, DefaultScreen(dpy)));
  
  buf_gc = XCreateGC(dpy, win_buf, GCFont|GCForeground, &values);

  XpmCreatePixmapFromData(dpy, win_buf, statusbar_xpm, &statusbar, (Pixmap *) NULL,
                          (XpmAttributes *) NULL);
  XpmCreatePixmapFromData(dpy, x_win, space_xpm, &space, (Pixmap *) NULL,
                          (XpmAttributes *) NULL);
  XpmCreatePixmapFromData(dpy, x_win, food_xpm, &food, (Pixmap *) NULL,
                          (XpmAttributes *) NULL);
  XpmCreatePixmapFromData(dpy, x_win, wall_xpm, &wall, (Pixmap *) NULL,
                          (XpmAttributes *) NULL);
  XpmCreatePixmapFromData(dpy, x_win, prize_xpm, &prize, (Pixmap *) NULL,
                          (XpmAttributes *) NULL);
  XpmCreatePixmapFromData(dpy, x_win, baddie_xpm, &baddie, (Pixmap *) NULL,
                          (XpmAttributes *) NULL);
  x = 0;
  while (x < (ncols * TILE_SIZE)) {
    XCopyArea(dpy, statusbar, win_buf, buf_gc, 0, 0, 96, 32, x, nrows*TILE_SIZE);
    x = x + 96;
  }
  XFlush(dpy);
}

void
hook_close (void)
{
  /* End X11 mode */
  XDestroyWindow(dpy, x_win);
  XUnloadFont(dpy, text);
  XFreePixmap(dpy, statusbar);
}

void
x11_update (const char *s)
{
  int x;
  char *status = malloc(20);
  
  x = 0;
  while (x < (ncols * TILE_SIZE)) {
    XCopyArea(dpy, statusbar, win_buf, gc, 0, 0, 96, 32, x, nrows*TILE_SIZE);
    x = x + 96;
  }

  XDrawString(dpy, win_buf, gc, 3, nrows*TILE_SIZE+16, s, strlen(s));

  sprintf(status, "Robot Energy: %3d", robot_energy);
  XDrawString(dpy, win_buf, gc, 160, nrows*TILE_SIZE+12, status, strlen(status));

  sprintf(status, "Robot Score: %3d", robot_score);
  XDrawString(dpy, win_buf, gc, 160, nrows*TILE_SIZE+25, status, strlen(status));

  sprintf(status, "Robot Shields: %3d", robot_shields);
  XDrawString(dpy, win_buf, gc, 270, nrows*TILE_SIZE+12, status, strlen(status));

  XCopyArea(dpy, win_buf, x_win, gc, 0, 0, ncols*TILE_SIZE, nrows*TILE_SIZE+32, 0, 0);
  XFlush(dpy);

  usleep(500000); /* Half a million microseconds */
}
