/*		   ACK-3D ( Animation Construction Kit 3D )		      */
/* Door routines      */
/* Author: Lary Myers */

#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <sys/stat.h>
#include "ack3d.h"
#include "ackext.h"

/****************************************************************************
** Locate a door from its Map coordinate and return the index to the	   **
** caller.								   **
**									   **
****************************************************************************/
int FindDoor(int MapPosn)
{
    int	    index;

for (index = 0; index < MAX_DOORS; index++)
    {
    if (MapPosn == Door[index].mPos || MapPosn == Door[index].mPos1)
	return(index);
    }

return(-1);
}

/****************************************************************************
** Find an empty slot for a door. If the door already occupies a slot and  **
** it is in a non-closed state then return error.			   **
**									   **
****************************************************************************/
int FindDoorSlot(int MapPosn)
{
    int	    index;

index = FindDoor(MapPosn);
if (index >= 0 && Door[index].ColOffset)
    return(-1);

for (index = 0; index < MAX_DOORS; index++)
    {
    if (Door[index].mPos == -1)
	return(index);

    }

return(-1);
}

/****************************************************************************
** Check all the doors to see what state they are in. If a door's column   **
** offset is non-zero then it is either opening or closing, so add in the  **
** speed of the door and check for fully open and fully closed conditions. **
**									   **
**									   **
****************************************************************************/
void CheckDoors(int xPlayer,int yPlayer)
{
	 int	i,MapPosn,mPos,mPos1;
	 int	column,mx,my,DeltaGrid;
unsigned char	mCode,mCode1;

for (i = 0; i < MAX_DOORS; i++)
    {
    if (Door[i].ColOffset)
	{
	Door[i].ColOffset += Door[i].Speed;
	mPos = Door[i].mPos;
	mPos1 = Door[i].mPos1;

   /* Door is closing and is visible. Put old codes back to make non-passable */
	if (Door[i].Speed < 0 && Door[i].ColOffset < 65)
	    {
	    MapPosn = (yPlayer & 0xFFC0) + (xPlayer >> 6);
	    if (MapPosn == mPos ||
		MapPosn == mPos1)
		{
		Door[i].ColOffset -= Door[i].Speed;
		continue;
		}

	    if (Door[i].Type == DOOR_XCODE)
		{
		if (xObjGrid[mPos] || xObjGrid[mPos1])
		    {
		    Door[i].ColOffset -= Door[i].Speed;
		    continue;
		    }

		xGrid[mPos]  = Door[i].mCode;
		xGrid[mPos1] = Door[i].mCode1;
		}
	    else
		{
		if (yObjGrid[mPos] || yObjGrid[mPos1])
		    {
		    Door[i].ColOffset -= Door[i].Speed;
		    continue;
		    }
		yGrid[mPos]  = Door[i].mCode;
		yGrid[mPos1] = Door[i].mCode1;
		}

/* Door is close enough to fully closed to get rid of the door from the array */
	    if (Door[i].ColOffset < 3)
		{
		Door[i].ColOffset = 0;
		Door[i].mPos	  = -1;
		Door[i].mPos1	  = -1;
		}

	    }


	if (Door[i].ColOffset > 0xA0)
	    Door[i].Speed = -Door[i].Speed;
	}
    }


/* Now check for any action occuring in a secret door. This is currently  */
/* setup to handle only one door at a time in the X and Y directions, but */
/* it should be fairly straightforward to use a list of doors, similiar	  */
/* to normal doors, to handle more than one.				  */
if (xSecretColumn)
    {
    if (xSecretColumn > 0)	    /* See if the door is to the right of us */
	{
	mPos = xSecretmPos1;
	DeltaGrid = -1;
	xSecretColumn += DoorSpeed;
	}
    else
	{
	mPos = xSecretmPos;
	DeltaGrid = 0;
	xSecretColumn -= DoorSpeed;
	}

    my = mPos & 0xFFC0;
    mx = (mPos - my) << 6;

    if (abs(xSecretColumn) > GRID_SIZE)	    /* Beyond one grid square */
	{
	mx += xSecretColumn;
	my = my + (mx >> 6);
	if (xGrid[my])			    /* No further, an obstruction */
	    {
	    xGrid[xSecretmPos] = 0;
	    xGrid[xSecretmPos1] = 0;
	    my += DeltaGrid;
	    xGrid[my] = NonSecretCode;
	    xGrid[my+1] = NonSecretCode;
	    yGrid[my] = NonSecretCode;
	    yGrid[my + GRID_WIDTH] = NonSecretCode;
	    xSecretColumn = 0;
	    }
	else
	    {
	    if (my != mPos)
		{
		xGrid[xSecretmPos] = 0;
		xGrid[xSecretmPos1] = 0;
		if (xSecretColumn > 0)
		    {
		    xSecretColumn -= 63;
		    xGrid[my] = DOOR_SECRETCODE;
		    xSecretmPos1 = my;
		    my--;
		    xGrid[my] = DOOR_SECRETCODE;
		    xSecretmPos = my;
		    }
		else
		    {
		    xSecretColumn += 63;
		    xGrid[my] = DOOR_SECRETCODE;
		    xGrid[my+1] = DOOR_SECRETCODE;
		    xSecretmPos = my;
		    xSecretmPos = my+1;
		    }
		}
	    } /* End if (xGrid[my]) ... else ...	 */
	}     /* End if (abs(xSecretColumn) > GRID_SIZE) */
    }	      /* End if (xSecretColumn)			 */

/* Perform same process on a secret door that may be moving in the Y */
/* direction. The same door can move either way, depending on which  */
/* angle the player struck it at.				     */
if (ySecretColumn)
    {
    if (ySecretColumn > 0)
	{
	mPos = ySecretmPos1;
	DeltaGrid = -GRID_WIDTH;
	ySecretColumn += DoorSpeed;
	}
    else
	{
	mPos = ySecretmPos;
	DeltaGrid = 0;
	ySecretColumn -= DoorSpeed;
	}

    my = mPos & 0xFFC0;
    mx = (mPos - my) << 6;

    if (abs(ySecretColumn) > GRID_SIZE)
	{
	my += ySecretColumn;
	my = (my & 0xFFC0) + (mx >> 6);
	if (yGrid[my])
	    {
	    yGrid[ySecretmPos] = 0;
	    yGrid[ySecretmPos1] = 0;
	    my += DeltaGrid;
	    xGrid[my] = NonSecretCode;
	    xGrid[my+1] = NonSecretCode;
	    yGrid[my] = NonSecretCode;
	    yGrid[my + GRID_WIDTH] = NonSecretCode;
	    ySecretColumn = 0;
	    }
	else
	    {
	    if (my != mPos)
		{
		yGrid[ySecretmPos] = 0;
		yGrid[ySecretmPos1] = 0;
		if (ySecretColumn > 0)
		    {
		    ySecretColumn -= 63;
		    yGrid[my] = DOOR_SECRETCODE;
		    ySecretmPos1 = my;
		    my -= GRID_WIDTH;
		    yGrid[my] = DOOR_SECRETCODE;
		    ySecretmPos = my;
		    }
		else
		    {
		    ySecretColumn += 63;
		    yGrid[my] = DOOR_SECRETCODE;
		    yGrid[my+GRID_WIDTH] = DOOR_SECRETCODE;
		    ySecretmPos = my;
		    ySecretmPos = my+GRID_WIDTH;
		    }
		}
	    }
	}
    }

}

