//A* Pathfinding program - 8 directions
//Ian Copland 0601545
//################################################################################
//
//								A* Pathfinding!
//	Controls are simple, left click to drop a starting posistion, then right click
//to place any walls, then left click again to drop a finish position, and it will
//begin!
//################################################################################

#include <windows.h>
#include <windowsx.h>
#include <stdio.h>
#include <mmsystem.h>
#include <math.h>
#include <iostream>
using namespace std;
#include <queue>


#define WIDTH 26
#define HEIGHT 19



int ticker =0;

HBITMAP		theOldFrontBitMap, theOldBackBitMap;
HWND        ghwnd;
RECT		screenRect;
HDC			backHDC, frontHDC, bitmapHDC;	//Hardware device contexts for the Buffers

BOOL waitFor(unsigned long delay);
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);

bool keys[256];
int mousex;
int mousey;
bool leftButton=0;
bool rightButton=0;
bool lbuttonPressed=0;
bool rbuttonPressed=0;

struct node//struct of nodes - which are basically positions on the grid, for storing in the priority_queue
{
	int x;
	int y;
	int step;
	int heuristic;
};

struct nodeLess : public binary_function <node, node, bool>//works out the order of the priority queue 
{
  bool operator()(
     const node& _Left, 
     const node& _Right
  ) const
  {
	  return _Left.step+_Left.heuristic >_Right.step+_Right.heuristic;
  }
};

typedef struct Sprite// the sprite struct, stores info bout any sprite onscreen
{
	int imagex, imagey;
	int x_pos,y_pos;
	int bmHeight;
	int bmWidth;
	HBITMAP bitmap;
	HBITMAP bmmask;

	Sprite(int h=29,int w=29,int xpos=0,int ypos=0,int ix=0,int iy=0){bmHeight=h;bmWidth=w;x_pos=xpos;y_pos=ypos;imagex=ix;imagey=iy;}
} Sprite;

void RegisterMyWindow(HINSTANCE hInstance)
{
    WNDCLASSEX  wcex;									

    wcex.cbSize        = sizeof (wcex);				
    wcex.style         = CS_HREDRAW | CS_VREDRAW;		
    wcex.lpfnWndProc   = WndProc;						
    wcex.cbClsExtra    = 0;								
    wcex.cbWndExtra    = 0;								
    wcex.hInstance     = hInstance;						
    wcex.hIcon         = 0; 
    wcex.hCursor       = LoadCursor (NULL, IDC_ARROW);	
															
    wcex.hbrBackground = (HBRUSH) (COLOR_WINDOW+1);
    wcex.lpszMenuName  = NULL;							
    wcex.lpszClassName = "FirstWindowClass";				
    wcex.hIconSm       = 0; 

	RegisterClassEx (&wcex);							
}

BOOL InitialiseMyWindow(HINSTANCE hInstance, int nCmdShow)
{
	HWND        hwnd;
	hwnd = CreateWindow ("FirstWindowClass",					
						 "Pathfinding Program",		  	
						 WS_OVERLAPPEDWINDOW,	
						 0,			
						 0,			
						 800,			
						 600,			
						 NULL,					
						 NULL,					
						 hInstance,				
						 NULL);								
	if (!hwnd)
	{
		return FALSE;
	}

    ShowWindow (hwnd, nCmdShow);						
    UpdateWindow (hwnd);	
	ghwnd = hwnd;
	return TRUE;

}



BOOL WaitFor(unsigned long delay)
{
	static unsigned long clockStart = 0;
	unsigned long timePassed;
	unsigned long now = timeGetTime();

	timePassed = now - clockStart;
	if (timePassed >  delay)
	{
		clockStart = now;
		return TRUE;
	}
	else
		return FALSE;
}	
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{


    switch (message)											
    {														
		case WM_CREATE:	
			break;

		case WM_SIZE:
			break;	

		case WM_KEYDOWN:
			keys[wParam]=true;
			break;

		case WM_KEYUP:
			keys[wParam]=false;
			break;

		case WM_MOUSEMOVE:
			mousex = LOWORD (lParam);
			mousey = HIWORD (lParam);
			break;

		case WM_PAINT:
			
	
		    break;
		case WM_LBUTTONDOWN:
			lbuttonPressed=1;
			leftButton=1;
			break;
		case WM_LBUTTONUP:
			leftButton=0;
			break;
		case WM_RBUTTONDOWN:
			rbuttonPressed=1;
			rightButton=1;
			break;
		case WM_RBUTTONUP:
				rightButton=0;
			break;

		case WM_DESTROY:	
			
			PostQuitMessage(0);	
								
			break;				
	}													

	return DefWindowProc (hwnd, message, wParam, lParam);		
															
}

HBITMAP LoadABitmap(LPSTR szFileName)
{
	return (HBITMAP)LoadImage(NULL, szFileName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
}

void drawSprite(Sprite theSprite)
{
	HBITMAP originalBitMap;
	//draw sprite
	originalBitMap = (HBITMAP)SelectObject(bitmapHDC,theSprite.bitmap);
	BitBlt(backHDC,theSprite.x_pos,theSprite.y_pos,theSprite.bmWidth,theSprite.bmHeight,bitmapHDC,theSprite.imagex,theSprite.imagey,SRCCOPY);
	SelectObject(bitmapHDC,originalBitMap); 
}

void setBuffers()
{
	GetClientRect(ghwnd, &screenRect);	//creates rect based on window client area
	frontHDC = GetDC(ghwnd);			// Initialises front buffer device context (window)
	backHDC = CreateCompatibleDC(frontHDC);// sets up Back DC to be compatible with the front
	bitmapHDC=CreateCompatibleDC(backHDC);
	theOldFrontBitMap = CreateCompatibleBitmap(frontHDC, screenRect.right, 
		screenRect.bottom);		//creates bitmap compatible with the front buffer
    theOldBackBitMap = (HBITMAP)SelectObject(backHDC, theOldFrontBitMap);
								//creates bitmap compatible with the back buffer
	FillRect(backHDC, &screenRect, (HBRUSH)GetStockObject(0));	
}

void displayFrame()
{
		BitBlt(frontHDC, screenRect.left,screenRect.top, screenRect.right, 
		screenRect.bottom, backHDC, 0, 0, SRCCOPY);
		FillRect(backHDC, &screenRect, (HBRUSH)GetStockObject(0));	
}

void releaseResources()
{
	SelectObject(backHDC,theOldBackBitMap);
	DeleteDC(backHDC);
	DeleteDC(bitmapHDC);
	ReleaseDC(ghwnd,frontHDC);
}

void mapGrid(Sprite Square[HEIGHT][WIDTH]){
	int i,j,no_of_squares=0;
	for (i=0;i<HEIGHT;i++)
		for (j=0;j<WIDTH;j++){
			//this simply maps out the positions of the Squares into a big grid
			Square[no_of_squares/WIDTH][no_of_squares%WIDTH].x_pos=30*j;
			Square[no_of_squares/WIDTH][no_of_squares++%WIDTH].y_pos=30*i;

		}
}

void reset(priority_queue<node,vector<node>,nodeLess> &wset, int pos_state[HEIGHT][WIDTH],Sprite Square[HEIGHT][WIDTH],int pathlength[HEIGHT][WIDTH]){
	int i,j;
	//resets everything for once it all begins again 
	while (!wset.empty())
			wset.pop();
	for (i=0;i<HEIGHT;i++)
		for (j=0;j<WIDTH;j++){
			Square[i][j].imagex=0;
			pos_state[i][j]=0; //set all squares as possible.
			pathlength[i][j]=0;
		}

}

bool startPosition(Sprite Square[HEIGHT][WIDTH],priority_queue<node,vector<node>,nodeLess> &wset,int pos_state[HEIGHT][WIDTH],int pathlength[HEIGHT][WIDTH]){
	node start_pos;
	//when the left mouse button is pressed, and within the grid boundries, draw the start position
	if (lbuttonPressed==1 && mousex<WIDTH*30 && mousey<HEIGHT*30){
		reset(wset,pos_state,Square, pathlength);
		start_pos.x=(int)mousex/30;
		start_pos.y=(int)mousey/30;
		start_pos.step=0;
		start_pos.heuristic=0;
		wset.push(start_pos);
		pos_state[mousey/30][mousex/30]=2;
		pathlength[mousey/30][mousex/30]=0;
		Square[mousey/30][mousex/30].imagex=29;
		return 1;
	}
	return 0;
}

bool endPosition(Sprite Square[HEIGHT][WIDTH],int pos_state[HEIGHT][WIDTH], node &end_pos){
	//when the left mouse button is pressed, and within the grid boundries, draw the end position
	if (lbuttonPressed==1 && mousex<WIDTH*30 && mousey<HEIGHT*30 && pos_state[mousey/30][mousex/30]!=2){
		pos_state[mousey/30][mousex/30]=1;
		Square[mousey/30][mousex/30].imagex=59;
		end_pos.x=mousex/30;
		end_pos.y=mousey/30;
		end_pos.step=0;
		end_pos.heuristic=0;
		return 1;
	}
	return 0;
}

void walls(Sprite Square[HEIGHT][WIDTH],int pos_state[HEIGHT][WIDTH]){
	//if the right mouse button is pressed, and within the grid boundries, draw a wall
	if (rbuttonPressed==1 && mousex<WIDTH*30 && mousey<HEIGHT*30 && pos_state[mousey/30][mousex/30]!=2){
		pos_state[mousey/30][mousex/30]=4;
		Square[mousey/30][mousex/30].imagex=119;
	}
}


int calc_heuristic(node next_pos, node end_pos){
	//calculates the heuristic value for working out the order in the priority queue
	int dy,dx,h;
	dx=abs(end_pos.x-next_pos.x);
	dy=abs(end_pos.y-next_pos.y);
	if (dx>=dy)
		h=(dx-dy)*10+dy*14;
	if (dy>dx)
		h=(dy-dx)*10+dx*14;
	return h;
}
int checkWset(priority_queue<node,vector<node>,nodeLess>&wset,int pos_state[HEIGHT][WIDTH],Sprite Square[HEIGHT][WIDTH],node end_pos,int pathlength[HEIGHT][WIDTH]){
	node current_pos,next_pos;
	//if theres no path, then tell user
	if (wset.empty()){
		MessageBox(NULL,"There is no Path for you. turn back.","Error!!!!!!!",MB_OK);
		return 0;
	}
	//checks if the current position is the end position, and if not, then add all the surrounding squares to the Wset
	//and update thier heuristic and pathlength, thus pushing back all the not so likely squares to the back of the priority
	//queue
	current_pos=wset.top();
	wset.pop();
		if (pos_state[current_pos.y][current_pos.x]==1){
			while (!wset.empty())
				wset.pop();
			wset.push(current_pos);
			return 3;
		}else{
			if (pos_state[current_pos.y][current_pos.x]!=2){	
				Square[current_pos.y][current_pos.x].imagex=208;
				pos_state[current_pos.y][current_pos.x]=5;
				current_pos.step=pathlength[current_pos.y][current_pos.x];
			}
			//push all squares that can be moved to into the wset
			//push up
			if (current_pos.y>0)
				if (pos_state[current_pos.y-1][current_pos.x]==0 || pos_state[current_pos.y-1][current_pos.x]==1){
					if (pos_state[current_pos.y-1][current_pos.x]==0){
						Square[current_pos.y-1][current_pos.x].imagex=89;
						pos_state[current_pos.y-1][current_pos.x]=3;
					}
					next_pos.x=current_pos.x;
					next_pos.y=current_pos.y-1;
					next_pos.step=current_pos.step+10;
					pathlength[current_pos.y-1][current_pos.x]+=current_pos.step+10;
					next_pos.heuristic=calc_heuristic(next_pos,end_pos);
					wset.push(next_pos);
				}
			//push right
			if (current_pos.x<WIDTH-1)
				if (pos_state[current_pos.y][current_pos.x+1]==0 || pos_state[current_pos.y][current_pos.x+1]==1){
					if (pos_state[current_pos.y][current_pos.x+1]==0){
						pos_state[current_pos.y][current_pos.x+1]=3 ;
						Square[current_pos.y][current_pos.x+1].imagex=89;
					}
					next_pos.x=current_pos.x+1;
					next_pos.y=current_pos.y;
					next_pos.step=current_pos.step+10;
					pathlength[current_pos.y][current_pos.x+1]+=current_pos.step+10;
					next_pos.heuristic=calc_heuristic(next_pos,end_pos);
					wset.push(next_pos);
				}
			
			//push down
			if (current_pos.y<HEIGHT-1)
				if (pos_state[current_pos.y+1][current_pos.x]==0 || pos_state[current_pos.y+1][current_pos.x]==1){
					if (pos_state[current_pos.y+1][current_pos.x]==0){
						pos_state[current_pos.y+1][current_pos.x]=3;
						Square[current_pos.y+1][current_pos.x].imagex=89;
					}
					next_pos.x=current_pos.x;
					next_pos.y=current_pos.y+1;
					next_pos.step=current_pos.step+10;
					pathlength[current_pos.y+1][current_pos.x]+=current_pos.step+10;
					next_pos.heuristic=calc_heuristic(next_pos,end_pos);
					wset.push(next_pos);
				}

			//push left
			if (current_pos.x>0)
				if (pos_state[current_pos.y][current_pos.x-1]==0 || pos_state[current_pos.y][current_pos.x-1]==1){
					if (pos_state[current_pos.y][current_pos.x-1]==0){
						pos_state[current_pos.y][current_pos.x-1]=3;
						Square[current_pos.y][current_pos.x-1].imagex=89;
					}
					next_pos.x=current_pos.x-1;
					next_pos.y=current_pos.y;
					next_pos.step=current_pos.step+10;
					pathlength[current_pos.y][current_pos.x-1]+=current_pos.step+10;
					next_pos.heuristic=calc_heuristic(next_pos,end_pos);
					wset.push(next_pos);
				}
			//push diag up/right
			if (current_pos.y>0 && current_pos.x<WIDTH-1)
				if (pos_state[current_pos.y-1][current_pos.x+1]==0 || pos_state[current_pos.y-1][current_pos.x+1]==1){
					if (pos_state[current_pos.y-1][current_pos.x+1]==0){
						Square[current_pos.y-1][current_pos.x+1].imagex=89;
						pos_state[current_pos.y-1][current_pos.x+1]=3;
					}
					next_pos.x=current_pos.x+1;
					next_pos.y=current_pos.y-1;
					next_pos.step=current_pos.step+14;
					pathlength[current_pos.y-1][current_pos.x+1]+=current_pos.step+14;
					next_pos.heuristic=calc_heuristic(next_pos,end_pos);
					wset.push(next_pos);
				}
			//push diag down/right
			if (current_pos.x<WIDTH-1 && current_pos.y<HEIGHT-1)
				if (pos_state[current_pos.y+1][current_pos.x+1]==0 || pos_state[current_pos.y+1][current_pos.x+1]==1){
					if (pos_state[current_pos.y+1][current_pos.x+1]==0){
						pos_state[current_pos.y+1][current_pos.x+1]=3 ;
						Square[current_pos.y+1][current_pos.x+1].imagex=89;
					}
					next_pos.x=current_pos.x+1;
					next_pos.y=current_pos.y+1;
					next_pos.step=current_pos.step+14;
					pathlength[current_pos.y+1][current_pos.x+1]+=current_pos.step+14;
					next_pos.heuristic=calc_heuristic(next_pos,end_pos);
					wset.push(next_pos);
				}
			//push diag down/left
			if (current_pos.y<HEIGHT-1 && current_pos.x>0)
				if (pos_state[current_pos.y+1][current_pos.x-1]==0 || pos_state[current_pos.y+1][current_pos.x-1]==1){
					if (pos_state[current_pos.y+1][current_pos.x-1]==0){
						pos_state[current_pos.y+1][current_pos.x-1]=3;
						Square[current_pos.y+1][current_pos.x-1].imagex=89;
					}
					next_pos.x=current_pos.x-1;
					next_pos.y=current_pos.y+1;
					next_pos.step=current_pos.step+14;
					pathlength[current_pos.y+1][current_pos.x-1]+=current_pos.step+14;
					next_pos.heuristic=calc_heuristic(next_pos,end_pos);
					wset.push(next_pos);
				}
			//push diag left/up
			if (current_pos.x>0 && current_pos.y>0)
				if (pos_state[current_pos.y-1][current_pos.x-1]==0 || pos_state[current_pos.y-1][current_pos.x-1]==1){
					if (pos_state[current_pos.y-1][current_pos.x-1]==0){
						pos_state[current_pos.y-1][current_pos.x-1]=3;
						Square[current_pos.y-1][current_pos.x-1].imagex=89;
					}
					next_pos.x=current_pos.x-1;
					next_pos.y=current_pos.y-1;
					next_pos.step=current_pos.step+14;
					pathlength[current_pos.y-1][current_pos.x-1]+=current_pos.step+14;
					next_pos.heuristic=calc_heuristic(next_pos,end_pos);
					wset.push(next_pos);
				}
			//if the squares to the sides have already been checked, but movement from the current square is quicker....
			//up
			if ((pos_state[current_pos.y-1][current_pos.x]==5 || pos_state[current_pos.y-1][current_pos.x]==3) && pathlength[current_pos.y][current_pos.x]+10<pathlength[current_pos.y-1][current_pos.x])
				pathlength[current_pos.y-1][current_pos.x]=pathlength[current_pos.y][current_pos.x]+10;
			//right
			if ((pos_state[current_pos.y][current_pos.x+1]==5 || pos_state[current_pos.y][current_pos.x+1]==3) && pathlength[current_pos.y][current_pos.x]+10<pathlength[current_pos.y][current_pos.x+1])
				pathlength[current_pos.y][current_pos.x+1]=pathlength[current_pos.y][current_pos.x]+10;
			//down
			if ((pos_state[current_pos.y+1][current_pos.x]==5 || pos_state[current_pos.y+1][current_pos.x]==3) && pathlength[current_pos.y][current_pos.x]+10<pathlength[current_pos.y+1][current_pos.x])
				pathlength[current_pos.y+1][current_pos.x]=pathlength[current_pos.y][current_pos.x]+10;
			//left
			if ((pos_state[current_pos.y][current_pos.x-1]==5 || pos_state[current_pos.y][current_pos.x-1]==3) && pathlength[current_pos.y][current_pos.x]+10<pathlength[current_pos.y][current_pos.x-1])
				pathlength[current_pos.y][current_pos.x-1]=pathlength[current_pos.y][current_pos.x]+10;

			//up/right
			if ((pos_state[current_pos.y-1][current_pos.x+1]==5 || pos_state[current_pos.y-1][current_pos.x+1]==3) && pathlength[current_pos.y][current_pos.x]+14<pathlength[current_pos.y-1][current_pos.x+1])
				pathlength[current_pos.y-1][current_pos.x+1]=pathlength[current_pos.y][current_pos.x]+14;
			//right/down
			if ((pos_state[current_pos.y+1][current_pos.x+1]==5 || pos_state[current_pos.y+1][current_pos.x+1]==3) && pathlength[current_pos.y][current_pos.x]+14<pathlength[current_pos.y+1][current_pos.x+1])
				pathlength[current_pos.y+1][current_pos.x+1]=pathlength[current_pos.y][current_pos.x]+14;
			//down/left
			if ((pos_state[current_pos.y+1][current_pos.x-1]==5 || pos_state[current_pos.y+1][current_pos.x-1]==3) && pathlength[current_pos.y][current_pos.x]+14<pathlength[current_pos.y+1][current_pos.x-1])
				pathlength[current_pos.y+1][current_pos.x-1]=pathlength[current_pos.y][current_pos.x]+14;
			//left/up
			if ((pos_state[current_pos.y-1][current_pos.x-1]==5 || pos_state[current_pos.y-1][current_pos.x-1]==3) && pathlength[current_pos.y][current_pos.x]+14<pathlength[current_pos.y-1][current_pos.x-1])
				pathlength[current_pos.y-1][current_pos.x-1]=pathlength[current_pos.y][current_pos.x]+14;

			return 2;
		}

}

int drawPath(priority_queue<node,vector<node>,nodeLess> &wset,int pos_state[HEIGHT][WIDTH],Sprite Square[HEIGHT][WIDTH],int pathlength[HEIGHT][WIDTH]){
	node current_pos,next_pos;
	int i,path[8]={50000,50000,50000,50000,50000,50000,50000,50000},smallest=0;
	current_pos=wset.top();
	wset.pop();
	//this remaps the path by returning looking for the lowest pathlength value on all the squares arround the current
	//square and jumps to it, repeating this until it finds the start again

	//push up
	if (current_pos.y>0 && pos_state[current_pos.y-1][current_pos.x]!=0 && pos_state[current_pos.y-1][current_pos.x]!=1 && pos_state[current_pos.y-1][current_pos.x]!=3 && pos_state[current_pos.y-1][current_pos.x]!=4)
		path[0]=pathlength[current_pos.y-1][current_pos.x];
	//push diag up/right
	if (current_pos.y>0 && current_pos.x<WIDTH-1 && pos_state[current_pos.y-1][current_pos.x+1]!=0 && pos_state[current_pos.y-1][current_pos.x+1]!=1 && pos_state[current_pos.y-1][current_pos.x+1]!=3 && pos_state[current_pos.y-1][current_pos.x+1]!=4)
		path[1]=pathlength[current_pos.y-1][current_pos.x+1];
	//push right
	if (current_pos.x<WIDTH-1 && pos_state[current_pos.y][current_pos.x+1]!=0 && pos_state[current_pos.y][current_pos.x+1]!=1 && pos_state[current_pos.y][current_pos.x+1]!=3 && pos_state[current_pos.y][current_pos.x+1]!=4)
		path[2]=pathlength[current_pos.y][current_pos.x+1];
	//push diag right/down
	if (current_pos.x<WIDTH-1 && current_pos.y<HEIGHT-1 && pos_state[current_pos.y+1][current_pos.x+1]!=0 && pos_state[current_pos.y+1][current_pos.x+1]!=1 && pos_state[current_pos.y+1][current_pos.x+1]!=3 && pos_state[current_pos.y+1][current_pos.x+1]!=4)
		path[3]=pathlength[current_pos.y+1][current_pos.x+1];
	//push down
	if (current_pos.y<HEIGHT-1 && pos_state[current_pos.y+1][current_pos.x]!=0 && pos_state[current_pos.y+1][current_pos.x]!=1 && pos_state[current_pos.y+1][current_pos.x]!=3 && pos_state[current_pos.y+1][current_pos.x]!=4)
		path[4]=pathlength[current_pos.y+1][current_pos.x];
	//push diag down/left
	if (current_pos.y<HEIGHT-1 && current_pos.x>0 && pos_state[current_pos.y+1][current_pos.x-1]!=0 && pos_state[current_pos.y+1][current_pos.x-1]!=1 && pos_state[current_pos.y+1][current_pos.x-1]!=3 && pos_state[current_pos.y+1][current_pos.x-1]!=4)
		path[5]=pathlength[current_pos.y+1][current_pos.x-1];
	//push left
	if (current_pos.x>0 && pos_state[current_pos.y][current_pos.x-1]!=0 && pos_state[current_pos.y][current_pos.x-1]!=1 && pos_state[current_pos.y][current_pos.x-1]!=3 && pos_state[current_pos.y][current_pos.x-1]!=4)
		path[6]=pathlength[current_pos.y][current_pos.x-1];
	//push left/up
	if (current_pos.x>0 && current_pos.y>0 && pos_state[current_pos.y-1][current_pos.x-1]!=0 && pos_state[current_pos.y-1][current_pos.x-1]!=1 && pos_state[current_pos.y-1][current_pos.x-1]!=3 && pos_state[current_pos.y-1][current_pos.x-1]!=4)
		path[7]=pathlength[current_pos.y-1][current_pos.x-1];
	//find smallest
	for (i=0;i<8;i++)
		if (path[i]<path[smallest] && path[i]!=1 && path[i]!=3)
			smallest=i;
	
	//draw smallest
	if (smallest==0){//up
		Square[current_pos.y-1][current_pos.x].imagex=148;
		next_pos.x=current_pos.x;
		next_pos.y=current_pos.y-1;
		next_pos.step=0;
		next_pos.heuristic=0;
		wset.push(next_pos);
	}
	if (smallest==1){//up/right
		Square[current_pos.y-1][current_pos.x+1].imagex=148;
		next_pos.x=current_pos.x+1;
		next_pos.y=current_pos.y-1;
		next_pos.step=0;
		next_pos.heuristic=0;
		wset.push(next_pos);
	}
	if (smallest==2){//right
		Square[current_pos.y][current_pos.x+1].imagex=148;
		next_pos.x=current_pos.x+1;
		next_pos.y=current_pos.y;
		next_pos.step=0;
		next_pos.heuristic=0;
		wset.push(next_pos);
	}
	if (smallest==3){//right/down
		Square[current_pos.y+1][current_pos.x+1].imagex=148;
		next_pos.x=current_pos.x+1;
		next_pos.y=current_pos.y+1;
		next_pos.step=0;
		next_pos.heuristic=0;
		wset.push(next_pos);
	}
	if (smallest==4){//down
		Square[current_pos.y+1][current_pos.x].imagex=148;
		next_pos.x=current_pos.x;
		next_pos.y=current_pos.y+1;
		next_pos.step=0;
		next_pos.heuristic=0;
		wset.push(next_pos);
	}
	if (smallest==5){//down/left
		Square[current_pos.y+1][current_pos.x-1].imagex=148;
		next_pos.x=current_pos.x-1;
		next_pos.y=current_pos.y+1;
		next_pos.step=0;
		next_pos.heuristic=0;
		wset.push(next_pos);
	}
	if (smallest==6){//left
		Square[current_pos.y][current_pos.x-1].imagex=148;
		next_pos.x=current_pos.x-1;
		next_pos.y=current_pos.y;
		next_pos.step=0;
		next_pos.heuristic=0;
		wset.push(next_pos);
	}
	if (smallest==7){//left/up
		Square[current_pos.y-1][current_pos.x-1].imagex=148;
		next_pos.x=current_pos.x-1;
		next_pos.y=current_pos.y-1;
		next_pos.step=0;
		next_pos.heuristic=0;
		wset.push(next_pos);
	}
	if (pos_state[next_pos.y][next_pos.x]==2){
		Square[next_pos.y][next_pos.x].imagex=29;
		return 0;
	}
	return 3;
}


int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int nCmdShow)			
{									
    MSG         msg;	
	int i,j,prog_state=0;
	node end_pos;
	int pathlength[HEIGHT][WIDTH];
	Sprite Square[HEIGHT][WIDTH];
	int pos_state[HEIGHT][WIDTH]; // 0=empty; 1 = goal; 2 = start; 3 = pending in wset; 4=wall; 5 = been checked
	priority_queue<node,vector<node>,nodeLess> wset;

	Square[0][0].bitmap = LoadABitmap("squares.bmp");
	if (!Square[0][0].bitmap)
		return FALSE;
	for (i=0;i<HEIGHT;i++)
		for (j=0;j<WIDTH;j++){
			Square[i][j].bitmap = Square[0][0].bitmap;
			pos_state[i][j]=0; //set all squares as possible.
			pathlength[i][j]=0; //set all pathlengths to 0
		}
	mapGrid(Square);
	RegisterMyWindow(hInstance);

   	if (!InitialiseMyWindow(hInstance, nCmdShow))
	return FALSE;
	setBuffers();

	while (TRUE)		// -------------program loop --------------			
    {							
		if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
		{
		    if (msg.message==WM_QUIT)
				break;
			TranslateMessage (&msg);							
			DispatchMessage (&msg);
		}

		else
		{		
			if (WaitFor(10))
			{	
				//game logic functions....
				if (prog_state==0){
					if (startPosition(Square,wset,pos_state,pathlength))
						prog_state=1;
				}else if (prog_state==1){
					if (endPosition(Square,pos_state,end_pos))
						prog_state=2;
				}
				if (prog_state<2){
				walls(Square,pos_state);
				}
				if (prog_state==2){
					prog_state=checkWset(wset,pos_state,Square,end_pos,pathlength);
				}
				if (prog_state==3){
					prog_state=drawPath(wset,pos_state,Square,pathlength);
				}
				//drawing functions....
				for (i=0;i<HEIGHT;i++)
					for (j=0;j<WIDTH;j++)
						drawSprite(Square[i][j]);
				displayFrame();	
				lbuttonPressed=0;
				rbuttonPressed=0;
			}

		}
    }		//---------end of program loop---------------

    releaseResources();
	return (int)msg.wParam;										
}

