/*************************************************************************/ 
/***                                                                   ***/ 
/***      R A Y                            (C) 1995 NPS Software       ***/  
/***                                                                   ***/  
/***                Writen By:        Brad Broerman                    ***/  
/***                Started:          June 1994                        ***/  
/***                Last Modified:    July 2, 2000                     ***/  
/***                Version:          1.5                              ***/  
/***                                                                   ***/  
/***                                                                   ***/  
/***    A 3-D Raycasting graphics engine with up to a 64x64 cell map,  ***/  
/***  35 textures (256 color 128x128 PCX files), textured floor and    ***/  
/***  ceiling, sprites, 3 types of animated doors, 20 levels of        ***/  
/***  transparency, translucency, animated textures,lighting and       ***/  
/***  depth cueing (with fog effects), zone maps, and triggers.        ***/  
/***                                                                   ***/  
/***    To be added: 2 more door types, door side texturing, door api, ***/  
/***  sprite logic api, lighting api, var. height floors, look up/down,***/  
/***  animated palette section, main menu, stats updating,             ***/
/***  trigger api.                                                     ***/
/***                                                                   ***/  
/*************************************************************************/  
/***                            Change Log:                            ***/  
/***                                                                   ***/  
/***     06/15/94  Started RAY project                                 ***/  
/***     06/30/94  Basic raycaster engine finished.                    ***/  
/***     07/30/94  Base engine optimized.                              ***/  
/***     09/10/94  Floor / ceiling texturing added.                    ***/  
/***     09/15/94  RAY first distributed.                              ***/  
/***                   -- 4 years later --                             ***/  
/***     09/25/98  Started working on Ray again...                     ***/  
/***     10/03/98  Added depth cueing/fog effects                      ***/  
/***     10/06/98  Added garage and elevator door styles               ***/  
/***     10/10/98  Fixed doors, now recessed 1/2 way back              ***/  
/***     10/14/98  Fixed array overruns ... Thx to Jorge A. Martin     ***/  
/***     10/29/98  Added animated textures, translucency, and          ***/  
/***                 recesed tile flags. Combined T & X tiles.         ***/  
/***     11/01/98  Finally got it to run in Protected Mode!            ***/  
/***     11/10/98  Added tiled light maps.                             ***/  
/***     12/05/98  Added animated lighting                             ***/  
/***     01/11/99  Increased PCX file resolution to 128x128            ***/  
/***     02/24/99  Added zone maps and zone options.                   ***/  
/***     03/11/99  Added Triggers (except 2,3,&10) (see triggers.txt)  ***/  
/***               Released Ray version 1.5                            ***/
/***     07/02/00  Did windows port of RAY. Added resize capability.   ***/
/***               Thanks to Jorge for showin me how to do the Windows ***/
/***               port.                                               ***/
/***                                                                   ***/  
/*************************************************************************/  
#include <windows.h>

#include <time.h> 

#include <io.h> 

#include <conio.h> 

#include <stdio.h> 

#include <stdlib.h> 

#include <fcntl.h> 

#include <memory.h> 

#include <malloc.h> 

#include <math.h> 

#include <string.h>


// Windows defined stuff (from resource.h)

#define IDM_EXIT                        100

#define IDB_BITMAP1                     101

#define IDC_WINRAY2                     104

#define IDM_TEST                        200

#define IDM_ABOUT                       301

#define IDM_RUN                         40001

#define IDM_DISPLAY_320                 40002

#define IDM_DISPLAY_640                 40003

#define IDM_DISPLAY_960                 40004

#define IDM_SHOWKEYS                    40005

  
// If defined, then floor and ceiling are rendered.  
#define CAST_FLOORCIEL  
 
// How close you can get to a wall.  
#define TOOCLOSE 60  
  
// Size of the viewport. 
#define VIEWPORT_WIDTH	240 
#define VIEWPORT_HEIGHT	200 
 
// For keyboard handling (in moving player), these query the keyboard in real-time

#define KEY_DOWN(vk_code)	((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)

#define KEY_UP(vk_code)		((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)


// Our definitions for the angles.  ANGLE_60 = width of viewport. (60 deg. FOV)  
// All the other angles are based on this.  
#define ANGLE_0     0  
#define ANGLE_1     4 
#define ANGLE_6     24  
#define ANGLE_30    120 
#define ANGLE_45    180  
#define ANGLE_60    240 
#define ANGLE_90    360  
#define ANGLE_120   480  
#define ANGLE_150   600  
#define ANGLE_180   720  
#define ANGLE_210   840  
#define ANGLE_225   900  
#define ANGLE_240   960  
#define ANGLE_270   1080  
#define ANGLE_300   1200  

#define ANGLE_330   1320
#define ANGLE_360   1440  
  
// The size of each cell. 128 makes the math easier. (also textures are 128 pixels wide)  
#define CELL_X_SIZE   128  
#define CELL_Y_SIZE   128  
  
// The maximum size of our world 64x64 cells.  
#define MAX_WORLD_ROWS 64  
#define MAX_WORLD_COLS 64  
  
// These defines are used for lighting.  
#define MAX_LIGHT_LEVELS  128  
#define PALETTE_SIZE      256ul  
#define MAX_DISTANCE      (MAX_WORLD_ROWS * MAX_WORLD_COLS)  
  
// We need a large stack.  
extern unsigned _stklen = 20480U;  
  
// The generic PCX header structure. I've listed some important fields, but  
// I won't check for them until this code is "officially" released.  
typedef struct PCX_HEADER_TYPE  
{  
    char  manufacturer;    // We don't care about these...  
    char  version;  
    char  encoding;  
    char  bits_per_pixel;  // We want an 8 here...  
    short x,y;             // We ignore these.  
    short width,height;    // Will be either 64x64 or 320x200  
    short horiz_rez;       // Forget about these...  
    short vert_rez;  
    char  EGA_palette[48]; // We won't even touch this.  
    char  reserved;  
    char  Num_Planes;      // We want 1  
    short bytes_per_line;  // Either 64 or 320  
    short palette_type;    // We can forget about these too..  
    char  padding[58];  
} PCX_HEADER;  
  
// Stores slice information for rendering. This is used so that we can  
// add sprites, transparency, etc. and have the rendering engine draw them too.  
struct col_obj  
{  
    int  top,         // Wihch row to begin drawing this slice.  
         col,         // Which screen column this slice is in.  
         scale,       // How much do I scale this slice  
         row,         // Which texture column to render for this slice.  
         texnum,      // The number of the wall/sprite texture to use.  
         lightnum,    // The number of the lighting tile to use. If -1, then use sptlight as the light for the whole sliver.  
         sptlight,    // Flat light value (if used).  
         zoneambient, // Ambient light for the zone the sliver is in.  
         usefog;      // Use the fog table or the darkness table for the sliver.  
    long dist;        // How far away is it (Used for sorting in sprites and light sourcing.)  
  
};  
  
// This implements the multiple levels of transparency we can use. The  
// objecs are ordered from nearest to farthest.  
struct scan_line_t  
{  
    col_obj line[10];  // We can go to 10 levels of transparency, sprites, etc.  
    int num_objs;  
};  
  
// This structure is kept for every texture map loaded into the game. It is  
// used (mainly) for doors and transparent items.  
struct TextureFlagsTYPE  
{  
    char IsTransparent, // 1=transparent, 0=not.  
         IsTranslucent, // 1=Translucent, 0=not.  
         IsDoor,        // 1= door, 0= regular wall.  
         DoorType,      // 1=normal, 2=elevator, 3=garage  
         IsSecretDoor,  // 1=Secret door, 0=Normal door.  
         IsRecessed,    // 1=Recessed texture(walls), 0=Not recessed  
         DoorSideTxt,   // This holds the texture number for the door sides. (Not used yet.)  
         CanWalkThru,   // 1 = you can walk trough it, 0 = Can not walk through it.  
         speed,         // How fast the door opens and closes. (cols per frame)  
         delay,         // How many frames to wait before closing the door.  
         bc,            // Upper left corner of the door  
         br,  
         ec,            // Lower right corner of the door  
         er;  
    int  AnimNbr;  
};  
  
// This structure keeps the parameters for the lights, including light type,  
// and blink parameters.  
struct LightFlagsTYPE  
{  
    char LightType;           // Either a 1, or a 2. 1: Regular blink, 2: Custom blink.  
    int  PulseWidth,          // For a regular blink, defines the pulse.  
         Period,  
         CurrPatternIndx;     // counter... see ProcessBlinkLights() for usage.  
    char *PulsePattern;       // For a custom blinking light, this is the pattern: 1 - on, 0= off.  
    char *OriginalBitmap; // Used to track the original bitmap. see ProcessBlinkLights() for usage.  
    int  AnimNbr;  
};  
  
// This structure keeps track of all the doors that are opening and closing  
// at any particular time.  
struct Open_Doors_Info  
{  
    char USED;          // Used in finding an empty spot to use. See the code.  
    int  x,             // Map location of the door.  
         y,  
         delay,         // The door's delay from above.  
         Orig_Txt_Num,  // The texture number of the original (un-opened) door.  
         New_Txt_Num,   // Points to the working copy of the door tex.  
         Pcnt_opened,   // Percent opened.  
         Num_Col_Opnd,  // The number of columns the door is opening.  
         Opening;       // 1=opening, 0=closing.  
};  
  
// This structure keeps track of information associated with all doors on the map.  
// Work in progress.  
struct Door_Info  
{  
    int x,            // Map location of the door.  
        y,  
        locked,       // Can I open it or not? 1 = Locked , 0 = Un-Locked.  
        opening;      // lets up know if the texture is not the original one. (!= 0) --> Don't touch!  
};  
  
// This is the basic structure for the sprites.  
struct Sprite_Type  
  
{  
    char *Frames[8];  // Stores the views (angles object can be viewed from)  
    int  translucent; // Specifies wether or not this sprites texture is translucent. (Sprites are always transparent)  
};  
  
// Sprite instance variables.  
// Work in progrss,  
struct object  
{  
    int sprite_num,  // The sprite array object we're using.  
        x,           // The sprites position in the map (fine coordiates)  
        y,  
        angle,       // The angle the sprite is facing.  
        state;       // The sprites state (To be used later)  
};  

// The struct that holds the player information. (I am keeping this separate from object since I

// plan on changing the two considerably.

struct player_t
{
	long x,                    // The players X position, in fine coordinates. 

         y,                    // The players Y position, in fine coordinates. 

         view_angle;           // The angle which the player is facing. 

};

  
//    This structure holds information about anumated textures. This includes the  
//  frames, and counter / timing information.  
struct Animations_Typ  
{  
    char **Frames;      // Array of pointers to the frames.  
    int    Flagged,       // 1=Animate this texture, 0=Show only 1st frame.  
           Txt_Nbr,       // Which texture in the map this applies to.  
           Delay,         // Delay time between frames.  
           Timer,         // Counts the delay for this texture.  
           Curr_Frame,    // The frame we are currently showing.  
           Nbr_Frames;    // The number of frames.  
};  
  
//   This structure holds information about the various defined zones. These zones  
// could be rooms, the outside, etc.  
struct zone_info  
{  
    char ambient,       // Ambient light level 0-64 for this zone.  
         inside,        // 1=inside, 0=outside  (turns on/off ceiling lighting)  
         fog;           // 1=Use fog, 0=use normal depth cueing.  
};  
  
//   This structure is used to record trigger information.  
// Work in progrss...  
struct trigger_info  
{  
    int  Trigger_Nbr,  
         Trigger_Type,  
         Trigger_Area_Type,  
         X1, Y1,  
         X2, Y2,  
         Radius,  
         MapX,  
         Mapy,  
         ZoneNbr,  
         NewLightLvl,  
         NewAngle,  
         TxtNbr;  
    char NewFileName[13];  
};  

//

//    This enum is used in the window procedure to change the procedures functionality

//  based on game state (displaying the title, displaying the menu, or running the game ).

//

enum {	SEQ_TITLESCREEN = 1,
		SEQ_FADETOGAME, 
		SEQ_PLAYGAME,
		SEQ_FADETOLEVEL, 
		SEQ_MENUDISPLAY
} GameState_Typ;
  
// These globals are used for speeding up the tracing and rendering parts.  
// These are copied from the col_obj structure above.  
long sliver_dist;  
int  sliver_start,  // Where (y) to begin drawing the slice.  
     sliver_column, // Screen column to draw in.  
     sliver_scale,  // Height of the sliver (pixels).  
     sliver_row,    // Column of the texture to draw.  
     sliver_map,    // Which texture to use.  
     sliver_light,  // Which lighting tile to use.  
     sliver_sptlt,  // Lighting level for sprites.  
     sliver_zoneamb,// Ambient light delta for the current zone.  
     sliver_usefog, // If 1, use fog table, else use darkness table.  
  
// These are used in the tracing process. They are global for the same reason as above.  
    cell_xx,       // These store the coordinates for the horiz. trace.  
    cell_yx,       //  
    cell_xy,       // These store the coordinates for the vert. trace.  
    cell_yy;       //  
  
// These are global because they're used all over, and I wanted to generate them ONLY  

// at the beginning of the program. It also saves us on stack usage.  


// Information needed by the application itself.

HWND ghWnd;			// Handle to the main window.

BOOL bIsActive;		// Tells us when we should be rendering, and when we should stop.

BOOL bRunGame;		// Tells us wether we are running the game or showing the title screen.

HINSTANCE hInst;	// current application instance

LPCTSTR lpszAppName  = "WinRay2"; // The application and window class name.

LPCTSTR lpszTitle    = "WinRay"; // The main window title.


// Pointers to double buffer info and address. 

BITMAPINFO *BitMapInfo ;
HBITMAP DblBuff;
unsigned char *double_buffer;
    
// Vaarious pointers and constants used while rendering the images.

int    WORLD_ROWS = 64;             // Current size of the map.  
int    WORLD_COLUMNS = 64;  
long   WORLD_X_SIZE = 8192;         // Total size of the world (64cells x 128 per cell)  
long   WORLD_Y_SIZE = 8192;  
char   *AutoMapBkgd;  
char   *world = NULL;               // pointer to matrix of cells that make up world  
char   *FloorMap = NULL;            // pointer to the matrix of cells that define the floor textures.  
char   *CeilMap = NULL;             // pointer to the matrix of cells that define the ceiling textures.  
char   *ZoneMap = NULL;             // pointer to the matrix of calls that define the 'zones' for various effects.  
char   TriggerMap[64][64];          // Assists in quick detection of simple triggers. Maps location to trigger number.  
char   *CeilLightMap = NULL;        // pointer to the ceiling light map.  
char   *FloorLightMap = NULL;       // pointer to the floor light map.  
int    Num_Textures = 0;            // The number of textures we've loaded.  
char   *WallTextures[90];           // The 64x64 wall textures, door textures, and visible sprites.  
int    Num_Light_Tiles = 0;         // The number of lighting tiles for the floor/ceiling light maps.  
char   *LightMapTiles[30];          // The 64x64 lighting map tiles.  
char   *LightLevel = NULL;          // Gives the lighting level as a function of distance.  
char   *LightMap = NULL;            // Maps a color/light pair into a pallete value for depth cueing. 32*256 in size.  
char   *FogMap = NULL;              // Maps a color/light pair into a pallete value for fog effects. 32*256 in size.  
char   *Translucency = NULL;        // Trans. lookup. Blends a color/color pair with 10% color 1, 90% color 2. Gives palette value.  
char   *BkgBuffer = NULL;           // The background picture.  
long   *tan_table = NULL;           // tangent tables used to compute initial  
long   *inv_tan_table = NULL;       // intersections with ray  
long   *y_step = NULL;              // x and y steps, used to find intersections  
long   *x_step = NULL;              // after initial one is found  
long   *cos_table = NULL;           // used to cacell out fishbowl effect  
long   *sin_table = NULL;           // Used for movement in different directions.  
long   *inv_cos_table = NULL;       // used to compute distances by calculating  
long   *inv_sin_table = NULL;       // the hypontenuse  
long   *sliver_factor = NULL;       // Scale factor for texture slivers.  
long   Floor_Row_Table[151];        // Pre-calculated row start values.  
long   *Floor_inv_cos_table = NULL; // The following tables are used in the math for the floor/ceiling.  
long   *Floor_cos_table = NULL;  
long   *Floor_sin_table = NULL;  
long   *Floor_Dx_table = NULL;  
long   row[200];                    // Pre-calculates 320*row.  
int    oldmode;                     // Original grahics/text mode when the game starts.  
char   palette[256][3];             // The current palette.  
int    Num_Sprites = 0;             // The number of sprites defined.  
int    Num_Objects = 0;             // The number of objects defined.  
int    Sprite_Frame[361];           // Determines frame to display for sprites.  
int    Num_Animations = 0;          // The number of animated textures we are using.  
int    Num_LightAnimations = 0;     // The number of animated lighting tiles we are using.  
int    Num_Triggers = 0;            // The number of defined triggers.  
short  ambient_level = 3;           // The global ambient light level.  
struct scan_line_t       scan_lines[240];          // Stores the scan-line info.  
struct TextureFlagsTYPE  TextureFlags[81];         // Stores the texture flags for each loaded texture.  
struct LightFlagsTYPE    LightFlags[30];           // Stores the flags for the lights.  
struct Open_Doors_Info   Opening_Doors[10];        // Moving door info.  
struct zone_info         ZoneAttr[20];             // Attributes for the zones. Currently: ambient light, fog, and inside/outside  
struct Sprite_Type       Sprites[10];              // The sprites. These are the bitmaps.  
struct object            Objects[30];              // The actual objects that use the sprites.  
struct Animations_Typ    Animations[10];           // Up to 10 animated textures.  
struct Animations_Typ    Light_Animations[10];     // Up to 10 animated lighting tiles.  
struct trigger_info      Triggers[10];             // The loaded triggers.  


// The following items are game state information:

char   ShowAutomap = 0;                            // This flag tells if the automap is on or off.

char   TorchLevel = 8;                             // This is the light level the players torch is putting out.

short  ClientWidth = 320;                          // The current screen dimentions.

short  ClientHeight = 200;                         //

short  ClientxPos;                                 // The current screen position.

short  ClientyPos;                                 //

struct player_t			Player_1;				   // The player.

enum   GameState_Typ	GameState;                 // This is a state variable that guides us in the WM_TIMER message.


// This is used for the title animation sequence.

char   *FireSrc; 

// 
// Function Prototypes: 
// 
// Thses functions are the primitive screen handling functions: 
void clearscrn(char c);  
void copyscrn (char far *Buffer);  
void dissolveto(char far *Buffer);  
void blit(void);
 
// These functions build and maintain the data tables. 
void free_tables(void);  
int  Die(char *string); 
int  Build_Tables(void);  
void CalcTorchLevel(int level);  
 
// These functions handle loading and saving game graohics. 
int  Save_Pcx(char *filename, unsigned char far *Buffer, unsigned long width, unsigned long height);  
char *Load_PCX(char *filename, unsigned long size, int load_pal);  
int  transpose(char far *Bitmap);  
int  load_bkgd(char *filename);  
int  Load_Wall(char *filename,int offset);  
int  Load_Light_Tile(char *filename,int offset);  
char far *Load_Sprite (char *filename);  
 
// This function loads a map file. 
unsigned char translateChar(unsigned char ch); 
void Clear_Map(void); 
int  Load_Map(long &initx, long &inity, long &initang, char *MapFileName);  
 
// The following functions render the world...  
void draw_sliver_transparent(void);  
void draw_sliver_trans(void);  
void draw_sliver(void);  
int  Cast_X_Ray(long x, long y, long view_angle, long &yi_save, long &x_save, int &lighttile, int &zone);  
int  Cast_Y_Ray(long x, long y, long view_angle, long &xi_save, long &y_save, int &lighttile, int &zone);  
void Texture_FloorCeil(long x, long y, long view_angle);  
void process_sprites(long x, long y, long view_angle);  
void DrawAutomap(long Xpos, long Ypos);  
void Render_View(long x,long y,long view_angle);  
 
// The last few functions perform the game logic...  
void delay2(long time); 
int  start_door(int x, int y);  
void open_doors();  
void close_doors();  
void ProcessTrigger(long &x, long &y, long &view_angle, int TriggerNbr);  
void CheckTriggers(long &x, long &y, long &view_angle);  
int  Rotate_Animations(void);  
void processblinklights(void);  
void ProccessUserMovement( void );
void MainLoop(void); 
int  InitTitleAnimation (void);
void AnimateFireScreen (void);
int  EndTitleAnimation (void);

// And finally, the main process. 
int InitEngine(void);  
void init_double_buffer(void);
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow);
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);