#include "wimp.h"
#include "wimpt.h"
#include "werr.h"
#include "coords.h"

#include <stdlib.h>

#include "polysaw.h"


#define ONE (1<<12)

int integer_sqrt(int x)
{             
int y,z,a,b,i,n,y2;
static int g[5] = {8192, 5793, 4871, 4467, 4277};

if (x==0) return 0;
n=0;
while (x < ONE)    {n--;     x = x << 2;}
while (x >= 4*ONE) {n++;     x = x >> 2;}

z = ONE;
a = ONE;
i = 0;
while ( a < x  &&  i < 4 )
    {
    while ((b = (a*g[i])/ONE) > x  &&  i < 4)    i++;
    if (i < 4)
        {
        a = b;
        z = (z*g[i+1])/ONE;
        }
    }

y = (x*ONE)/a - ONE;
y2 = (y*y)/ONE;
z = (  z*( ONE + (y/2) - (y2/8) + ((y*y2)/(ONE*16)) )  ) >> 6;
z = (n < 0) ? z>>(-n) : z<<n;
return z/ONE;
}


int roundtonearest(int a, int step)
{
if (step == 0) werr(TRUE, "roundtonearest got a 0\n");
step = abs(step);
if (a >= 0) 
  return  step*( ( a+step/2) / step);
else
  return -step*( (-a+step/2) / step);
}


void fill_out_polydefn(int p)
{
int i, x0, x1, y0, y1, maxrad, x, y;



/* find a bounding box. used for finding which piece clicked on
and for redraw.  also calc radius at which spin turns into move */

x0 = piece[p].units[0].x - HS;
y0 = piece[p].units[0].y - HS;
x1 = x0 + 2*HS;
y1 = y0 + 2*HS;
for (i=0; i < piece[p].nofunits; i++)
  {
  if (piece[p].units[i].x - HS  <  x0)   x0 = piece[p].units[i].x - HS;
  if (piece[p].units[i].y - HS  <  y0)   y0 = piece[p].units[i].y - HS;
  if (piece[p].units[i].x + HS  >  x1)   x1 = piece[p].units[i].x + HS;
  if (piece[p].units[i].y + HS  >  y1)   y1 = piece[p].units[i].y + HS;
  }
piece[p].movespin_rad = (x1-x0+y1-y0)*(x1-x0+y1-y0)/32;
maxrad = abs(x0);
if (maxrad < abs(x1)) maxrad = abs(x1);
if (maxrad < abs(y0)) maxrad = abs(y0);
if (maxrad < abs(y1)) maxrad = abs(y1);

piece[p].box.x0 = -maxrad;
piece[p].box.y0 = -maxrad;
piece[p].box.x1 =  maxrad;
piece[p].box.y1 =  maxrad;
 
/* initiallise the orientation and parity info */ 
piece[p].rotflipstate = 0;

/* associate units with sprites according to existence of
   neighbouring units */

for (i=0; i<piece[p].nofunits; i++)
  {
  int s=15, j;
  for (j=0; j<piece[p].nofunits; j++)
     {
     if (piece[p].units[j].x == piece[p].units[i].x)
         {
         if (piece[p].units[j].y == piece[p].units[i].y + 2*HS)
             s = s &~ 1;
         if (piece[p].units[j].y == piece[p].units[i].y - 2*HS)
             s = s &~ 4;
         }
     if (piece[p].units[j].y == piece[p].units[i].y)
         {
         if (piece[p].units[j].x == piece[p].units[i].x - 2*HS)
             s = s &~ 2;
         if (piece[p].units[j].x == piece[p].units[i].x + 2*HS)
             s = s &~ 8;
         }
      }
      piece[p].unitpic[i] = s;
  }

/* fill in grid  - 
formula is (x,y) goes to   grid[(-y-HS)/(2*HS)][(x-HS)/(2*HS)]   
this is centre of squares to   row, column */

for (i=0; i < piece[p].nofunits; i++)
  {
  x = piece[p].cog.x + piece[p].units[i].x;
  y = piece[p].cog.y + piece[p].units[i].y;
  grid[(-y-HS)/(2*HS)][(x-HS)/(2*HS)] |= PIECE_BIT;
  }

}


int which_piece(coords_pointstr w)
{
int p, i;
coords_pointstr pt;

for (p=0; p < nofpieces; p++)
  {
  pt.x = w.x - piece[p].cog.x;
  pt.y = w.y - piece[p].cog.y;
  /* pt is offset to centre of piece, as all piece info is rel. cog */
  if ( coords_withinbox(&pt, &piece[p].box) )   
     {
     for (i=0; i < piece[p].nofunits; i++)
        {
        if ( abs(pt.x - piece[p].units[i].x) <= HS   &&   
             abs(pt.y - piece[p].units[i].y) <= HS )   
             {
             return p;
             }
        }
     }
  }
return MAX_PIECES+1;
}



void force_grid_redraw(int row, int col)
{
wimp_redrawstr r;

r.w = board_wh;
r.box.x0 = 2*HS*col;
r.box.y0 = 2*HS*(-row-1);
r.box.x1 = r.box.x0 + 2*HS;
r.box.y1 = r.box.y0 + 2*HS;

wimpt_noerr(wimp_force_redraw(&r));
}


void force_piece_redraw(int p)
{
wimp_redrawstr r;

r.w = board_wh;
r.box.x0 = piece[p].cog.x + piece[p].box.x0;
r.box.y0 = piece[p].cog.y + piece[p].box.y0;
r.box.x1 = piece[p].cog.x + piece[p].box.x1;
r.box.y1 = piece[p].cog.y + piece[p].box.y1;

wimpt_noerr(wimp_force_redraw(&r));
}

