/*		   ACK-3D ( Animation Construction Kit 3D )		      */
/* Main entry point   */
/* 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 "ackext.h"

/****************************************************************************
**									   **
****************************************************************************/
void main(int argc,char *argv[])
{
	    int	    i,j,done,pos,dflag;
	    int	    TablePosn;
	    int	    xPlayer,yPlayer;
	    int	    PlayerAngle;
	    int	    x1,y1;
	    int	    SkyCount;
	    int	    SkyNumber;
	    int	    DoFlash;
	    long    CosAngle,SinAngle;
	    int	    Spin,SpinAngle;
	    int	    DoorDelay;
unsigned    char    sCode;
	    long    frames,tStart,tDraw,t1;


#if DEBUG
dfp = fopen("x.dst","wt");
#else
dfp = NULL;
#endif

DoFlash = 1;

if (argc > 1)
    {
    for (i = 0; i < argc; i++)
	{
	if (!(stricmp(argv[i+1],"-F")))
	    DoFlash = 0;
	}
    }

randomize();

InitializeMouse();

strcpy(PalFile,"ack.pal");
strcpy(GridFile,"ackmap.l01");

TopColor      = SkyColor = SKY_COLOR;
BottomColor   = FloorColor = FLOOR_COLOR;
FlashColor    = SKY_FLASH;
SkyCount      = 0;
Spin	      = SpinAngle = 0;
CenterRow     = 120;
MaxObjects    = 0;
DoorSpeed     = DEFAULT_DOOR_SPEED;
StartX	      = StartY = 96;
StartAngle    = 0;
CurrentLevel  = 1;
NonSecretCode = 1;

if (BuildTables())
    exit(1);

if (ReadMasterFile("ACK3D.L01"))
    exit(1);

if (ReadMapFile())
    exit(1);

BuildXYgrid();

TopColor    = SkyColor;
BottomColor = FloorColor;
xPlayer	    = StartX;
yPlayer	    = StartY;
PlayerAngle = StartAngle;
CosAngle    = CosTable[PlayerAngle];
SinAngle    = SinTable[PlayerAngle];

ObjList[0].Sides  = 0;
ObjList[0].VidRow = CenterRow;


keyBoardInit();
oldvec=getvect(KEYBD);
setvect(KEYBD,myInt);

graphinit();

PageNum = 1;
usepage(PageNum);

LoadPalette(PalFile);
NoWalls = 0;
done	= 0;

DrawView(xPlayer,yPlayer,PlayerAngle);
SkyNumber = random(1000);

txRay  = 0L;
tyRay  = 0L;
tDOW   = 0L;
tFlip  = 0L;
frames = 0L;
tDraw  = 0L;
tStart = CLOCK_PTR;

while (!done)
    {
    CheckDoors(xPlayer,yPlayer);
    CheckObjectMovement();

    sCode = CheckSpecialCodes((yPlayer & 0xFFC0) + (xPlayer >> 6));

    if (sCode == MAP_DOWNCODE)
	{
	CurrentLevel++;
	ReadNewLevel();
	TopColor    = SkyColor;
	BottomColor = FloorColor;
	xPlayer	    = StartX;
	yPlayer	    = StartY;
	PlayerAngle = StartAngle;
	CosAngle    = CosTable[PlayerAngle];
	SinAngle    = SinTable[PlayerAngle];
	}

    if (sCode == MAP_UPCODE)
	{
	if (CurrentLevel > 1)
	    {
	    CurrentLevel--;
	    ReadNewLevel();
	    TopColor	= SkyColor;
	    BottomColor = FloorColor;
	    xPlayer	= StartX;
	    yPlayer	= StartY;
	    PlayerAngle = StartAngle;
	    CosAngle	= CosTable[PlayerAngle];
	    SinAngle	= SinTable[PlayerAngle];
	    }
	}

    if (sCode == MAP_GOALCODE)
	{
	DoGoalScreen();
	done = 1;
	break;
	}

    if (Spin)
	{
	Spin >>= 1;
	PlayerAngle += SpinAngle;
	if (PlayerAngle >= INT_ANGLE_360)
	    PlayerAngle -= INT_ANGLE_360;
	if (PlayerAngle < 0)
	    PlayerAngle += INT_ANGLE_360;
	CosAngle = CosTable[PlayerAngle];
	SinAngle = SinTable[PlayerAngle];
	}

    if (SkyCount)
	{
	if (!(SkyCount & 1))
	    TopColor = FlashColor;
	else
	    TopColor = SkyColor;

	SkyCount--;
	}

    if (DoFlash)
	{
	if (!SkyCount && random(32768) == SkyNumber)
	    {
	    SkyCount = 5;
	    SkyNumber = random(31000) + 1000;
	    }
	}

    if(keyBoard.escape)
	break;

    CheckMouse(&mouse);

    if (mouse.mdx < 0)
	{
	Spin = -mouse.mdx;
	Spin >>= 3;
	SpinAngle = -INT_ANGLE_2 * Spin;
	Spin = 1;
	}

    if (mouse.mdx > 0)
	{
	Spin = mouse.mdx;
	Spin >>= 3;
	SpinAngle = INT_ANGLE_2 * Spin;
	Spin = 1;
	}

    if (mouse.mdy < 0)
	{
	i = -mouse.mdy;
	i >>= 2;
	i += 16;
	x1 = xPlayer + (int)((CosAngle * i) >> FP_SHIFT);
	y1 = yPlayer + (int)((SinAngle * i) >> FP_SHIFT);

	if ((i = CheckHit(xPlayer,yPlayer,PlayerAngle)) == 0)
	    {
	    xPlayer = x1;
	    yPlayer = y1;
	    }
	else
	    {
	    if (i == 3)
		continue;
	    if (i == 1)
		{
		x1 = xPlayer;
		if (PlayerAngle < INT_ANGLE_180)
		    j = INT_ANGLE_90;
		else
		    j = INT_ANGLE_270;

		}
	    else
		{
		y1 = yPlayer;
		if (PlayerAngle > INT_ANGLE_270 || PlayerAngle < INT_ANGLE_90)
		    j = 0;
		else
		    j = INT_ANGLE_180;
		}


	    if (!CheckHit(xPlayer,yPlayer,j))
		{
		xPlayer = x1;
		yPlayer = y1;
		}
	    }

	}

    if (mouse.mdy > 0)
	{
	i = mouse.mdy;
	i >>= 2;
	i += 16;
	x1 = xPlayer - (int)((CosAngle * i) >> FP_SHIFT);
	y1 = yPlayer - (int)((SinAngle * i) >> FP_SHIFT);
	j = PlayerAngle + INT_ANGLE_180;
	if (j >= INT_ANGLE_360)
	    j -= INT_ANGLE_360;

	if ((i = CheckHit(xPlayer,yPlayer,j)) == 0)
	    {
	    xPlayer = x1;
	    yPlayer = y1;
	    }
	else
	    {
	    if (i == 3)
		continue;

	    if (i == 1)
		{
		x1 = xPlayer;
		if (j < INT_ANGLE_180)
		    j = INT_ANGLE_90;
		else
		    j = INT_ANGLE_270;

		}
	    else
		{
		y1 = yPlayer;
		if (j > INT_ANGLE_270 || j < INT_ANGLE_90)
		    j = 0;
		else
		    j = INT_ANGLE_180;
		}


	    if (!CheckHit(xPlayer,yPlayer,j))
		{
		xPlayer = x1;
		yPlayer = y1;
		}

	    }


	}

    if (mouse.mButtons & 2)
	{
	i = CheckHit(xPlayer,yPlayer,PlayerAngle);

	if (i == 1 && xGrid[xMapPosn] == DOOR_SECRETCODE)
	    {
	    if (xSecretColumn == 0)
		{
		xSecretmPos = xMapPosn;
		if (iLastX > xPlayer)
		    {
		    xSecretmPos1 = xMapPosn + 1;
		    xSecretColumn = 1;
		    yGrid[xMapPosn] = yGrid[xMapPosn - GRID_WIDTH];
		    }
		else
		    {
		    xSecretmPos1 = xMapPosn - 1;
		    xSecretColumn = -1;
		    yGrid[xSecretmPos1] = yGrid[xSecretmPos1 - GRID_WIDTH];
		    }
		}
	    }


	if (i == 2 && yGrid[yMapPosn] == DOOR_SECRETCODE)
	    {
	    if (ySecretColumn == 0)
		{
		ySecretmPos = yMapPosn;
		if (iLastY > yPlayer)
		    {
		    ySecretmPos1 = yMapPosn + GRID_WIDTH;
		    xGrid[yMapPosn] = xGrid[yMapPosn-1];
		    ySecretColumn = 1;
		    }
		else
		    {
		    ySecretmPos1 = yMapPosn - GRID_WIDTH;
		    xGrid[ySecretmPos1] = xGrid[ySecretmPos1 - 1];
		    ySecretColumn = -1;
		    }
		}
	    }

	if (i == 1 && xGrid[xMapPosn] == DOOR_XCODE)
	    {
	    j = FindDoorSlot(xMapPosn);
	    if (j >= 0)
		{
		Door[j].mPos = xMapPosn;
		if ((int)iLastX > xPlayer)
		    i = xMapPosn + 1;
		else
		    i = xMapPosn - 1;

		Door[j].mCode = xGrid[xMapPosn];
		Door[j].mCode1 = xGrid[i];
		Door[j].mPos1 = i;
		Door[j].ColOffset = 1;
		Door[j].Speed = DoorSpeed;
		Door[j].Type = DOOR_XCODE;
		}
	    }

	if (i == 2 && yGrid[yMapPosn] == DOOR_YCODE)
	    {
	    j = FindDoorSlot(yMapPosn);
	    if (j >= 0)
		{
		Door[j].mPos = yMapPosn;
		if ((int)iLastY > yPlayer)
		    i = yMapPosn + GRID_WIDTH;
		else
		    i = yMapPosn - GRID_WIDTH;

		Door[j].mCode = yGrid[yMapPosn];
		Door[j].mCode1 = yGrid[i];
		Door[j].mPos1 = i;
		Door[j].ColOffset = 1;
		Door[j].Speed = DoorSpeed;
		Door[j].Type = DOOR_YCODE;
		}

	    }

	}


    if(keyBoard.rightArrow)
	{
	if (keyBoard.control)
	    PlayerAngle += INT_ANGLE_45;
	else
	    PlayerAngle += INT_ANGLE_6;

	if (PlayerAngle >= INT_ANGLE_360)
	    PlayerAngle -= INT_ANGLE_360;

	CosAngle = CosTable[PlayerAngle];
	SinAngle = SinTable[PlayerAngle];
	}

    if(keyBoard.leftArrow)
	{
	if (keyBoard.control)
	    PlayerAngle -= INT_ANGLE_45;
	else
	    PlayerAngle -= INT_ANGLE_6;

	if (PlayerAngle < 0)
	    PlayerAngle += INT_ANGLE_360;


	CosAngle = CosTable[PlayerAngle];
	SinAngle = SinTable[PlayerAngle];
	}

    if(keyBoard.upArrow)
	{
	x1 = xPlayer + (int)(CosAngle >> (FP_SHIFT - 4));
	y1 = yPlayer + (int)(SinAngle >> (FP_SHIFT - 4));
	if ((i = CheckHit(xPlayer,yPlayer,PlayerAngle)) == 0)
	    {
	    xPlayer = x1;
	    yPlayer = y1;
	    }
	else
	    {
	    if (i == 3)
		continue;

	    if (i == 1)
		{
		x1 = xPlayer;
		if (PlayerAngle < INT_ANGLE_180)
		    j = INT_ANGLE_90;
		else
		    j = INT_ANGLE_270;

		}
	    else
		{
		y1 = yPlayer;
		if (PlayerAngle > INT_ANGLE_270 || PlayerAngle < INT_ANGLE_90)
		    j = 0;
		else
		    j = INT_ANGLE_180;
		}


	    if (!CheckHit(xPlayer,yPlayer,j))
		{
		xPlayer = x1;
		yPlayer = y1;
		}
	    }


	}

    if(keyBoard.downArrow)
	{
	x1 = xPlayer - (int)(CosAngle >> (FP_SHIFT - 4));
	y1 = yPlayer - (int)(SinAngle >> (FP_SHIFT - 4));

	j = PlayerAngle + INT_ANGLE_180;
	if (j >= INT_ANGLE_360)
	    j -= INT_ANGLE_360;

	if ((i = CheckHit(xPlayer,yPlayer,j)) == 0)
	    {
	    xPlayer = x1;
	    yPlayer = y1;
	    }
	else
	    {
	    if (i == 3)
		continue;

	    if (i == 1)
		{
		x1 = xPlayer;
		if (j < INT_ANGLE_180)
		    j = INT_ANGLE_90;
		else
		    j = INT_ANGLE_270;

		}
	    else
		{
		y1 = yPlayer;
		if (j > INT_ANGLE_270 || j < INT_ANGLE_90)
		    j = 0;
		else
		    j = INT_ANGLE_180;
		}


	    if (!CheckHit(xPlayer,yPlayer,j))
		{
		xPlayer = x1;
		yPlayer = y1;
		}
	    }

	}

    if (keyBoard.letA)
	{
	if (CenterRow > 90)
	    {
	    CenterRow--;
	    }
	}

    if (keyBoard.letS)
	{
	if (CenterRow < 150)
	    {
	    CenterRow++;
	    }
	}

    t1 = CLOCK_PTR;
    DrawView(xPlayer,yPlayer,PlayerAngle);
    tDraw += CLOCK_PTR - t1;
    frames++;
    }

tStart = CLOCK_PTR - tStart;

WrapUp();


printf("\nFrames  : %ld\n",frames);
printf("tDrawRtn  : %ld\n",tDraw);
printf("tTotal    : %ld\n",tStart);
printf("txRay     : %ld\n",txRay);
printf("tyRay     : %ld\n",tyRay);
printf("tDrawWalls: %ld\n",tDOW);
printf("tFlipPage : %ld\n",tFlip);
}
