#include <stdlib.h>
#include <stdio.h>
#include <alloc.h>
#include "boodles.h"
#include "xlib.h"
#include "xtext.h"

int score = 0;
int turns = 0;
int numboodles, numgrumjugs;
boodlepiece ** boodles;
boodlepiece ** grumjugs;


icon logo;

void load_boodle_icons(void)
{
  logo.load("boodlog.drw");

  factor::load_factor(BOODLE, "", "", "", "", "", "boodle", "", "", "", "");
  factor::load_factor(BOODLEWIZ, "","","","","", "boodwiz", "","","","");
  factor::load_factor(BOODLINO, "","","","","","boodlino", "", "", "", "");
  factor::load_factor(BOODLETTAH, "","","","","","boodlett", "","","","");
  factor::load_factor(UNSETBOODLEBLASTER, "","","","","","ubblast", "","","","");
  factor::load_factor(GRUMKING, "","","","","","grumking", "","","","");
  factor::load_factor(GRUMBUGGY, "","","","","lgrumbug","grumbugg", "grumbugg","","","");
  factor::load_factor(UNSETGRUMBOMB, "","","","","","grumbom4", "", "", "", "");
  factor::load_factor(GRUMJUG, "", "", "sgrumjug", "", "lgrumjug", "cgrumjug", "grumjug",
			       "", "ngrumjug", "");
  factor::load_factor(DEAD, "", "", "", "", "", "grave", "", "", "", "");
  factor::load_factor(BOODLEBLASTER, "", "", "", "", "", "bblast", "", "","","");
  factor::load_factor(GRUMBOMB, "","","","","","grumbomb","","","","");
  factor::load_factor(CURSOR, "","","","","","cursor","","","","");
  factor::load_factor(BROKEBUGGY, "","","","","","brokebug", "","","","");
  factor::load_factor(SAFEBOODLE, "","","","","","house","","","","");
  fevent::load_fevent(3, "","","","","","grumbomb","","","","");
  event::load_event(1, "spell");
  fevent::load_fevent(0, "","","","","","boodbop", "","","","");
  fevent::load_fevent(1, "","","sgrumjug", "","lgrumbop","cgrumjug","rgrumbop","","ngrumjug","");
  fevent::load_fevent(2, "","","","","","bblast","","","","");
  FILE *f;
  char far * newfnt = (char far *) farmalloc(256*16+4);
  f=fopen("6x8b.fnt","rb");
  fread(newfnt,1,256*8+4,f);
  fclose(f);
  x_register_userfont(newfnt);
  x_set_font(2);
}

void getdeltas(byte direction, int &deltax, int &deltay)
{
  deltax = deltay = 0;
  switch(direction)
  {
    case NORTH     : --deltay; break;
    case SOUTH     : ++deltay; break;
    case WEST      : --deltax; break;
    case CENTER    : break;
    case EAST      : ++deltax; break;
    case NORTHWEST : --deltay; --deltax; break;
    case NORTHEAST : --deltay; ++deltax; break;
    case SOUTHWEST : ++deltay; --deltax; break;
    case SOUTHEAST : ++deltay; ++deltax; break;
  }
}

void boodlepiece::grumwomp(animactor * thebomb)
{
  if (my_identity != DEAD)  //no need to womp dead critters...
  {
    thebomb->spawn((animactor *) new bombeat);
    die();
  }
}


void boodlepiece::advance(void)
{
  factor::advance();
  animactor * thebomb;
  if ((thebomb = (animactor *)isinsquare(GRUMBOMB)) && (my_identity != DEAD))
    grumwomp(thebomb); //we're sending grumwomp the address of the bomb,
		       //not the womped target.
}

void boodlepiece::attack(boodlepiece * target)
{
}


void boodlepiece::drop(void)
{
  if (cargo != NULL)
  {
    cargo->put(mapx, mapy);
    cargo = NULL;
  }
}

void boodlepiece::move(byte direction)
{
  int deltax, deltay;
  getdeltas(direction, deltax, deltay);
  if (movesleft > 0)
  if (((((mymap->mapdata[mapx + deltax][mapy + deltay].my_terrain_type & 239) == GRASS) ||
     (mymap->mapdata[mapx + deltax][mapy + deltay].my_terrain_type & 239) == VALLEY))
     && (((my_identity == GRUMJUG) || (my_identity == GRUMBUGGY) || (my_identity == BROKEBUGGY))
       ||((my_identity != GRUMJUG)
	 &&(my_identity != GRUMBUGGY)
	 &&(my_identity != BROKEBUGGY)
	 &&(!(mymap->isinsquare(mapx+deltax, mapy+deltay, GRUMJUG))))))
    switch (direction)
    {
      case NORTH     : addcommand(FINESLIDE, 4, 0,0, -24); --movesleft; break;
      case SOUTH     : addcommand(FINESLIDE, 4, 0,0, 24); --movesleft; break;
      case WEST      : addcommand(FINESLIDE, 4, 0, -24, 0); --movesleft; break;
      case CENTER    : addcommand(DO_NOTHING, 0,0,0,0); --movesleft; break;
      case EAST      : addcommand(FINESLIDE, 4, 0, 24,0); --movesleft; break;
      case NORTHWEST : addcommand(FINESLIDE, 4, 0,-24, -24); --movesleft; break;
      case NORTHEAST : addcommand(FINESLIDE, 4, 0,24, -24); --movesleft; break;
      case SOUTHWEST : addcommand(FINESLIDE, 4, 0,-24, 24); --movesleft; break;
      case SOUTHEAST : addcommand(FINESLIDE, 4, 0,24, 24); --movesleft; break;
    }
  if (((mymap->mapdata[mapx + deltax][mapy + deltay].my_terrain_type & 239) == VALLEY)
      && (my_identity != GRUMJUG)
      && (my_identity != GRUMBUGGY))
  {
    movesleft = 0;
    ++score;
    if (my_identity == BOODLETTAH)
      score += 3;
    assign_icon(SAFEBOODLE, ONEFACE);
  }
}

void boodlepiece::setmovement(void)
{};

void boodlepiece::die(void)
{
  assign_icon(DEAD, ONEFACE, DEAD);
  if (cargo != NULL)
    cargo->put(mapx, mapy);
  movesleft = 0;
};


void boodle::setmovement(void)
{
  movesleft = random(6) + 1;
  if ((my_identity == DEAD) || (my_identity == SAFEBOODLE))
    movesleft = 0;
};

void boodle::pick_up(void)
{
  boodlepiece * target;
  if (((target = (boodlepiece *)isinsquare(UNSETBOODLEBLASTER)) != NULL) && (cargo == NULL))
  {
    target->remove();
    cargo = target;
  }
}

void boodlino::move(byte direction)
{
  int deltax = 0, deltay = 0;
  boodlepiece * target;
  getdeltas(direction, deltax, deltay);
  if (target = (boodlepiece *)mymap->isinsquare(mapx + deltax, mapy + deltay, GRUMJUG))
    {
    attack(target);
    return;
    }
  if ((my_identity != DEAD) && (movesleft > 0))
    boodlepiece::move(direction);
}

void boodlino::attack(boodlepiece * target)
{
  if (random(6) + 1 < 4)
    {
    spawn(new boodbop);
    target->die();
    }
  else
    target->attack(this);
}

void boodleblaster::setmovement(void) {movesleft = 0;};

void grumjug::setmovement(void) {movesleft = 1;if (my_identity == DEAD) movesleft = 0;};

void grumjug::pick_up(void)
{
  boodlepiece * target;
  if (((target = (boodlepiece *)isinsquare(UNSETGRUMBOMB)) != NULL) && (cargo == NULL))
  {
    target->remove();
    cargo = target;
  }
}

void grumjug::move(byte direction)
{
  int deltax, deltay;
  boodlepiece * target;
  getdeltas(direction, deltax, deltay);
  if (deltax < 0) turn(WEST);
  if (deltax > 0) turn(EAST);
  if (target = (boodlepiece *)mymap->isinsquare(mapx + deltax, mapy + deltay, BOODLINO))
  {
    attack(target);
    return;
  }
  else if (target = (boodlepiece *)mymap->isinsquare(mapx + deltax, mapy + deltay, BOODLETTAH))
  {
    attack(target);
    return;
  }
  else if (target = (boodlepiece *)mymap->isinsquare(mapx + deltax, mapy + deltay, BOODLEWIZ))
  {
    attack(target);
    return;
  }
  else if (target = (boodlepiece *)mymap->isinsquare(mapx + deltax, mapy + deltay, BOODLE))
  {
    attack(target);
    return;
  }
  if ((my_identity != DEAD) && (mymap->mapdata[mapx+deltax][mapy+deltay].my_terrain_type != VALLEY))
    boodlepiece::move(direction);
}

void grumjug::attack(boodlepiece * target)
{
  switch(target->my_identity)
  {
    case BOODLINO: if (random(6) + 1 < 4)
		   {
		     spawn(new grumbop);
		     target->die();
		   }
		   else
		     target->attack(this);
		   break;
    case BOODLE:
    case BOODLEWIZ:
    case BOODLETTAH: if (random(6) + 1 < 6)
		     {
		       spawn(new grumbop);
		       target->die();
		     }
		     else
		       target->attack(this);
		     break;
  }
}

void grumking::setmovement(void) {movesleft = 0;};

void grumbuggy::pick_up(void)
{
  boodlepiece * target;
  if (((target = (boodlepiece *)isinsquare(GRUMJUG)) != NULL) && (cargo == NULL))
  {
    target->remove();
    target->my_identity = CARRIEDGRUMJUG;
    cargo = target;
  }
  else if (((target = (boodlepiece *)isinsquare(GRUMJUG)) != NULL) && (cargo2 == NULL) ||
     (((target = (boodlepiece *)isinsquare(UNSETGRUMBOMB)) != NULL) && (cargo2 == NULL)))
  {
    target->remove();
    if (target->my_identity == GRUMJUG)
      target->my_identity = CARRIEDGRUMJUG;
    cargo2 = target;
  }
  if (movesleft == 0)
    movesleft = 4;
}

void grumbuggy::drop(void)
{
  if (cargo2 != NULL)
  {
    cargo2->put(mapx, mapy);
    if (cargo2->my_identity == CARRIEDGRUMJUG)
      cargo2->my_identity = GRUMJUG;
    cargo2 = NULL;
  }
  else if (cargo != NULL)
  {
    cargo->put(mapx, mapy);
    if (cargo->my_identity == CARRIEDGRUMJUG)
      cargo->my_identity = GRUMJUG;
    cargo = NULL;
    movesleft = 0;
  }
}


void grumbuggy::setmovement(void)
{
  if (cargo != NULL)
  {
    movesleft = 4;
  }
  else
    movesleft = 0;
  if (my_identity == BROKEBUGGY)
    movesleft = 0;
};


void grumbuggy::move(byte direction)
{
  int deltax, deltay;
  getdeltas(direction, deltax, deltay);
  boodlepiece::move(direction);
  if (((mymap->mapdata[mapx+deltax][mapy+deltay].my_terrain_type & 16) == 16) &&
     (mymap->mapdata[mapx+deltax][mapy+deltay].my_terrain_type != VALLEY))

  {
    assign_icon(BROKEBUGGY, ONEFACE);
    movesleft = 0;
  }
}

void grumbomb::move(byte direction)
{
  assign_icon(GRUMBOMB, ONEFACE);
  movesleft = 0;
}

void grumbomb::setmovement(void)
{
    movesleft = 0;
};
