#define __RAWKS_LIDE__
#define DBG 0
#define FIXME 0

#include "defines.h"
#include "struct.h"
#include "protos.h"
#include "globals.h"

/* I took this from the imfamous Chris Fout's `bz' code.  It can also be
   found in that big white algorithms book with the little red mobile on
   front. By the way, Chris, BZ is the most awesome game in the world.
   - Aaron Michael Hightower */
/*-----------------------------------------------------------------------------
 * INTERSECTION_CHECK - checks for the intersection of two lines.  One line
 *  is defined by the points r0 and r1; the other line is defined by the
 *  points r2 and r3.
 *
 *  Line 1 is defined by:       Pt = r0 + s * ( r1 - r0 ) ;     0 <= s <= 1
 *  Line 2 is defined by:       Pt = r2 + t * ( r3 - r2 ) ;     0 <= t <= 1
 *
 *  Set the two equal, solve for s and t.  If s and t are both between
 *  0 and 1 (inclusive), the lines intersect.  Return 1 if the lines
 *  intersect, 0 otherwise.
 *---------------------------------------------------------------------------*/
int intersect(float r0[2],float r1[2],float r2[2],float r3[2],float *s)
{
  float denom,denom1,denom2;
  float ns, nt;
  float dx10, dy10;
  float dx20, dy20;
  float dx32, dy32;

  dx10 = r1[0] - r0[0];
  dy10 = r1[1] - r0[1];

  dx20 = r2[0] - r0[0];
  dy20 = r2[1] - r0[1];

  dx32 = r3[0] - r2[0];
  dy32 = r3[1] - r2[1];

  denom1 = dy10 * dx32;
  denom2 = dx10 * dy32;

  /* Fail if lines are parallel. */
  if (denom1 == denom2)
    return (0);

  denom = denom1 - denom2;

  ns = dx32 * dy20 - dy32 * dx20;
  nt = dx10 * dy20 - dy10 * dx20;

  /* Fail if s or t will be greater than 1 (s = ns/denom ; t = nt/denom). if(
   * ns > denom || nt > denom ) return( 0 ) ; */

  /* Fail if s or t are less than 0 (negative, which happens if ns or nt are
   * of different signs than denom) or greater than 1 (if abs(ns) or abs(nt)
   * are greater than abs(denom) ). */
  if (denom < 0) {
    if (ns > 0 || nt > 0 || ns < denom || nt < denom) {
      return (0);
    }
  } else {
    if (ns < 0 || nt < 0 || ns > denom || nt > denom) {
      return (0);
    }
  }
#if 0
  *s = ns / denom;
#endif

  return (1);
}

void my_intersect(float p1[2],float p2[2],float p3[2],float p4[2],float *s)
{
  C_WHITE;
  bgnclosedline();
  v2f(p1);
  v2f(p2);
  endclosedline();
  C_RED;
  bgnclosedline();
  v2f(p3);
  v2f(p4);
  endclosedline();
  sginap(120);
#if 1
  swapbuffers();
#endif
}

int intersect_all(float p1[2],float p2[2],int player)
{
  int rot;
  int i,j;
  float s;

  for(i=Firstbullet_i;i!=Nextbullet_i;i=INC_BULLET(i)) {
    if(B[i].ttl<=0 || B[i].exempt) continue;
#if DBG
    /* This allowed me to look at which lines were being tested for
       intersection.  I have seen similar games that don't allow your
       bullets to wrap around to the other side of the screen because
       it makes it hard to maintain the integrity of the intersection
       tests.  I hacked it, but at least it works! - AMH */
      
    my_intersect(p1,p2,&B[i].V[Frm].x,&B[i].V[2+Frm].x,&s);
#endif
    if(B[i].player != player &&
       intersect(p1,p2,&B[i].V[Frm].x,&B[i].V[2+Frm].x,&s)) {
      P[B[i].player].hit += 1;
      B[i].ttl = -2;

      return B[i].player;
      /* A rock is killed - no id needed since rocks called this */
    }
  }
  for(i=1;i<=Num_players;i++) {
    if(i==player) continue; /* What a (*&^% kludge!!! */
    rot = P[i].rot[Frm];
    if(P[i].dead || P[i].exempt) continue; /* exemption via bbox */

    for(j=0;j<P[i].ship->num_verts-1;j++) {
#if DBG
      my_intersect(p1,p2,&P[i].modg->verts[j].x,&P[i].modg->verts[j+1].x,&s);
#endif
    if(intersect(p1,p2,&P[i].modg->verts[j].x,&P[i].modg->verts[j+1].x,&s))
	/* Return the id of the player who has died :-( bye - sniff */
	return -i;
    }
#if DBG
    my_intersect(p1,p2,&P[i].modg->verts[0].x,&P[i].modg->verts[j].x,&s);
#endif
    if(intersect(p1,p2,&P[i].modg->verts[0].x,&P[i].modg->verts[j].x,&s))
      return -i;
#if DBG
    my_intersect(p1,p2,&P[i].V[Frm].x,&P[i].V[2+Frm].x,&s);
#endif
    if(intersect(p1,p2,&P[i].V[Frm].x,&P[i].V[2+Frm].x,&s))
      /* Check vector movement of ship(s) for collision */
      return -i;
  }
  return 0;
}

int intersect_ships(int player,float p1[2],float p2[2])
{
  int rot;
  int i,j;
  float s;

  for(i=player+1;i<=Num_players;i++) {
    rot = P[i].rot[Frm];
    if(i==player || P[i].dead || P[i].exempt) continue;
    /* exemption via bbox , if player dead, or if player is self */

    for(j=0;j<P[i].ship->num_verts-1;j++) {
#if DBG
      my_intersect(p1,p2,&P[i].modg->verts[j].x,&P[i].modg->verts[j+1].x,&s);
#endif
    if(intersect(p1,p2,&P[i].modg->verts[j].x,&P[i].modg->verts[j+1].x,&s))
      /* Return the id of the player who has died :-( bye - sniff */
      return -i;
    }
#if DBG
    my_intersect(p1,p2,&P[i].modg->verts[0].x,&P[i].modg->verts[j].x,&s);
#endif
    if(intersect(p1,p2,&P[i].modg->verts[0].x,&P[i].modg->verts[j].x,&s))
      return -i;
#if DBG
    my_intersect(p1,p2,&P[i].V[Frm].x,&P[i].V[2+Frm].x,&s);
#endif
    if(intersect(p1,p2,&P[i].V[Frm].x,&P[i].V[2+Frm].x,&s))
      /* Check vector movement of ship(s) for collision */
      return -i;
  }
  return 0;
}
