/******************* ( Animation Construction Kit 3D ) ***********************/
/*			  Ray Casting Routines				     */
/* CopyRight (c) 1993	   Author: Lary Myers				     */
/*****************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <dos.h>
#include <mem.h>
#include <alloc.h>
#include <io.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <sys\stat.h>
#include "ack3d.h"
#include "ackeng.h"
#include "ackext.h"

	    UCHAR   yLight;
	    UCHAR   xLight;


/****************************************************************************
** This routine cast rays along the X walls of the map to determine when   **
** a wall is struck. A zero returned indicates no wall was found, else the **
** bitmap number of the wall is returned.				   **
** If a wall is found the variables LastY1 and iLastX are set to the map   **
** coordinates of the wall and xMapPosn is the actual map coordinate.	   **
**									   **
****************************************************************************/
UINT xRay(int x,int y,int angle,ACKENG *ae)
{
    UINT    Color;
    int	    i,j,mx,my;
    int	    TablePosn;
    int	    MapPosn,CurPosn;
    int	    xBeg;
    long    xPos,xNext;
    int	    BitmapColumn;
    int	    xCenter,yCenter,xAdj;
    int	    ObjPosn;
    int	    oBegX,oBegY;
    long    yPos;
    long    yNext;
    long    xd,yd,sy;
    long    ObjDist;

xBeg  = x & 0xFFC0;		/* Get upper left corner of square    */
yNext = yNextTable[angle];	/* PreCalc'd value of 64 * Tan(angle) */

if (angle > INT_ANGLE_270 || angle < INT_ANGLE_90)
    {
    xPos  = xBeg + GRID_SIZE;	/* Looking to the right */
    xNext = GRID_SIZE;		/* Positive direction	*/
    }
else
    {
    xPos  = xBeg;		/* Looking to the left	*/
    xNext = -GRID_SIZE;		/* Negative direction	*/
    yNext = -yNext;
    }

/* Calculate the Y coordinate for the current square */
yPos = (((long)xPos - (long)x) * LongTanTable[angle]) + ((long)y << FP_SHIFT);

while (1)
    {
    if (xPos < 0 || xPos > GRID_XMAX ||
	yPos < 0 || yPos > GRID_YMAXLONG)
	break;

/**************	  Fixed point	  Y/64 * 64	X / 64 ***********/
    MapPosn = ((yPos >> FP_SHIFT) & 0xFFC0) + (xPos >> 6);

/* Check to see if a wall is being struck by the ray */
    if ((Color = ae->xGrid[MapPosn]) != 0)
	{
	xMapPosn = MapPosn;	    /* Hold onto the map location */
	iLastX	 = xPos;
	LastY1	 = yPos;
	if ((Color & 0xFF) == DOOR_XCODE)    /* Is this a door? */
	    {
	    yd = (yPos >> FP_SHIFT) & 0xFFC0;	/* Get the left side */
	    xd = yd + GRID_SIZE;		/* And the right side */
	    ObjDist = (yPos + (yNext >> 1)) >> FP_SHIFT; /* Calc door distance */
	    if (ObjDist < yd || ObjDist > xd)	/* Is door visible? */
		{
		xPos += xNext;			/* Nope, continue casting */
		yPos += yNext;			/* the ray as before	  */
		continue;
		}

	    LastY1 = yPos + (yNext >> 1);	/* Adjust the X,Y values so   */
	    iLastX += (xNext >> 1);		/* the door is halfway in sq. */
	    }

	if (Color & DOOR_TYPE_SECRET)
	    {
	    if (xSecretColumn != 0)
		{
		sy = xSecretColumn * LongTanTable[angle];
		ObjDist = (yPos + sy) >> FP_SHIFT;
		yd = (yPos >> FP_SHIFT) & 0xFFC0;   /* Get the left side */
		xd = yd + GRID_SIZE;		    /* And the right side */
		if (ObjDist < yd || ObjDist > xd)   /* Is door visible? */
		    {
		    xPos += xNext;		    /* Nope, continue casting */
		    yPos += yNext;		    /* the ray as before      */
		    continue;
		    }
		LastY1 = yPos + sy;
		iLastX += xSecretColumn;
		}
	    }

	xLight = LightMap[MapPosn];
	return(Color);
	}

    xPos += xNext;	/* Next X coordinate (fixed at 64 or -64)   */
    yPos += yNext;	/* Next calculated Y coord for a delta of X */
    }

return(0);		/* Return that no wall was found */
}

/****************************************************************************
** This routine cast rays along the Y walls of the map to determine when   **
** a wall is struck. A zero returned indicates no wall was found, else the **
** bitmap number of the wall is returned.				   **
** If a wall is found the variables LastX1 and iLastY are set to the map   **
** coordinates of the wall and xMapPosn is the actual map coordinate.	   **
**									   **
****************************************************************************/
UINT yRay(int x,int y,int angle,ACKENG *ae)
{
    UINT    Color;
    int	    i,j,mx,my;
    int	    MapPosn;
    int	    yBeg;
    long    yPos,yNext;
    int	    BitmapColumn;
    int	    xCenter,yCenter,yAdj;
    int	    ObjPosn;
    int	    oBegX;
    long    xPos;
    long    xNext;
    long    xd,yd,ObjDist,sx;

yBeg  = y & 0xFFC0;		/* Same as div 64 then mul 64	       */
xNext = xNextTable[angle];	/* Pre-calc'd value of 64 / tan(angle) */

if (angle < INT_ANGLE_180)
    {
    yPos  = yBeg + GRID_SIZE;	/* Looking down	      */
    yNext = GRID_SIZE;		/* Positive direction */
    }
else
    {
    yPos  = yBeg;		/* Looking up	      */
    yNext = -GRID_SIZE;		/* Negative direction */
    xNext = -xNext;
    }

/* Calculate the X coordinate for the current square */
xPos = (((long)yPos - (long)y) * LongInvTanTable[angle]) + ((long)x << FP_SHIFT);

oBegX = 0;

while (1)
    {
    if (xPos < 0 || xPos > GRID_XMAXLONG ||
	yPos < 0 || yPos > GRID_YMAX)
	break;

/***********   Y/64 * 64	 Fixed point and /64 ******/
    MapPosn = (yPos & 0xFFC0) + (xPos >> (FP_SHIFT+6));

/** Check for a wall being struck **/
    if ((Color = ae->yGrid[MapPosn]) != 0)
	{
	yMapPosn = MapPosn;		/* Hold onto map position */
	LastX1	 = xPos;
	iLastY	 = yPos;

	if ((Color & 0xFF) == DOOR_YCODE)	 /* Is this a door? */
	    {
	    yd = (xPos >> FP_SHIFT) & 0xFFC0;	/* Calc top side of square   */
	    xd = yd + GRID_SIZE;		/* And bottom side of square */
	    ObjDist = (xPos + (xNext >> 1)) >> FP_SHIFT;
	    if (ObjDist < yd || ObjDist > xd)	/* Is door visible? */
		{
		xPos += xNext;		/* No, continue on with ray cast */
		yPos += yNext;
		continue;
		}

	    LastX1 = xPos + (xNext >> 1);   /* Adjust coordinates so door is */
	    iLastY += (yNext >> 1);	    /* Halfway into wall	     */
	    }

	if (Color & DOOR_TYPE_SECRET)
	    {
	    if (ySecretColumn != 0)
		{
		sx = ySecretColumn * LongInvTanTable[angle];
		ObjDist = (xPos + sx) >> FP_SHIFT;
		yd = (xPos >> FP_SHIFT) & 0xFFC0;   /* Get the top side	   */
		xd = yd + GRID_SIZE;		    /* And the bottom side */
		if (ObjDist < yd || ObjDist > xd)   /* Is door visible? */
		    {
		    xPos += xNext;		    /* Nope, continue casting */
		    yPos += yNext;		    /* the ray as before      */
		    continue;
		    }
		LastX1 = xPos + sx;
		iLastY += ySecretColumn;
		}

	    }

	yLight = LightMap[MapPosn];
	return(Color);
	}

    xPos += xNext;		/* Next calculated X value for delta Y */
    yPos += yNext;		/* Next fixed value of 64 or -64       */

    if (++oBegX > 64)		/* Check a maximum number of squares   */
	break;
    }

return(0);		/* Return here if no Y wall is found */
}

