///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// MAP LETTERS (TO CREATE YOUR OWN MAPS):
// w - wall
// . - floor
// b - pushable box
// t - box target position
// p - player
// c - camera position, with floor
// k - camera position, with wall
// = - box created on the target position
// + - empty space
// 1-st number is the .txt. file, is the width of the grid, 2-nd number, is the height!
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// include lib:
#include <acknex.h>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// define game paths:
#define PRAGMA_PATH	"data"				// main game folder
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// pointers:
ENTITY* heroEnt;								// player
ENTITY* ghostEnt;								// visual player's model
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// game BMAP's:
BMAP* splashPcx = "splash.pcx";			// game splash screen
BMAP* pressEnterTga = "PressEnter.tga";// press enter bmap
// menu buttons (start the game):
BMAP* startOn = "startOn.tga";			// selected start button
BMAP* startOff = "startOff.tga";			// unselected start button
// exit the game:
BMAP* exitOn = "exitOn.tga";				// selected exit button
BMAP* exitOff = "exitOff.tga";			// unselected exit button
// loading bmap:
BMAP* loadingTga = "loading.tga";		// loading game image
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// the file reading strings:
STRING* line_characters ="#400";			// max amount of lines in the file
STRING* empty = "#1";						// empty string
// models:
STRING* wallMdl = "wall.mdl";				// wall model
STRING* floorMdl = "floor.mdl";			// floor model
STRING* playerMdl = "bbox.mdl";			// player's model
STRING* ghostMdl = "puschel.mdl";		// visual player's model
STRING* boxMdl = "box.mdl";				// box model
STRING* boxTargetMdl = "target.mdl";	// box target model
// levels:
STRING* map01Str = "map01.txt";			// first level
STRING* map02Str = "map02.txt";			// second level
STRING* map03Str = "map03.txt";			// third level
STRING* map04Str = "map04.txt";			// fourth level
STRING* map05Str = "map05.txt";			// fifth level
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// button sound:
SOUND* toggleButtonWav = "button.wav";	// button toggle sound
SOUND* pressButtonWav = "pressed.wav";	// button pressed sound
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// grid skills:
#define BLOCK_SIZE							32
// object types:
#define objType								skill1
#define objBoxTarget							1
#define objFloor								2
#define objWall								3
#define objHero								4
#define objBox									5
#define objCam									6
// box skills:
#define checkOnce								skill2
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// tile position:
VECTOR tilePos;								// the spawn position, for each tile
// new position of the player:
VECTOR newPos;									// new position, for us to move to
// new box position:
VECTOR newBoxPos;								// new box position, to move to
// old box position:
VECTOR oldBoxPos;								// old box position, to move player to
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// map creation stuff:
var mapWidth;									// width of the Map
var mapHeight;									// height of the map
var lines_index;								// line being read in the map
var mapRow = 0;								// amount of the rows we've read from the file
var mapCollum = 0;							// amount of the collums we've read from the file
// gameplay stuff:
var gameReady = 0;							// we aren't ready to play, till level is loaded
var boxPlaceLeft = 0;						// amount of wrong placed boxes
var currentLevel = 1;						// the level counter
// camera stuff:
var cameraArc = 35;							// it changes depending on the level
// movement stuff:
var pressedOnce = 0;							// pressed switch
var keyPressed = 0;							// moves made by player
var keyOnce = 0;								// disables/enables player's input
var keyTrigger = 0;							// triggers the input counter, if input type is 1
var keyTriggerSpeed = 0.1;					// movement speed, if input type is 1
// music handles:
var handleMusic = 0;							// music handles
var handleLogo = 0;							// logo video handle
// menu buttons:
var buttonAllow = 0;							// allow to toggle buttons
var buttonState = 0;							// start/exit buttons selection
var buttonPushed = 0;						// if we pressed the button
// prototype:
var nextLevel();
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// splash panel:
PANEL* splashPan = {
	// define bmap:
	bmap = splashPcx;
	// define layer:
	layer = 1;
	// flags:
	flags = UNTOUCHABLE;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// input panel:
PANEL* pressEnterPan = {
	// define bmap:
	bmap = pressEnterTga;
	// define layer:
	layer = 1;
	// flags:
	flags = UNTOUCHABLE | CENTER_X | CENTER_Y;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// start the game pane:
PANEL* startGamePan = {
	// define bmap:
	bmap = startOn;
	// define layer:
	layer = 2;
	// flags:
	flags = UNTOUCHABLE | CENTER_X | CENTER_Y;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// exit the game panel:
PANEL* exitGamePan = {
	// define bmap:
	bmap = exitOff;
	// define layer:
	layer = 2;
	// flags:
	flags = UNTOUCHABLE | CENTER_X | CENTER_Y;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// loading the game panel:
PANEL* loadGamePan = {
	// define bmap:
	bmap = loadingTga;
	// define layer:
	layer = 3;
	// flags:
	flags = UNTOUCHABLE | CENTER_X | CENTER_Y;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// game GUI:
PANEL* gameGuiPan = {
	// positions:
	pos_x = 64;
	pos_y = 59;
	// digits:
	digits(0, 0, 4, "Fixedsys#b", 1, keyPressed);	
	// define layer:
	layer = 3;
	// flags:
	flags = UNTOUCHABLE;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// toggle between buttons:
void toggleButtons(){
	// if we can't toggle, then function is invalid:
	if(buttonAllow == 0){ return; }
	// if we pressed the button, then function is invalid:
	if(buttonPushed > 0){ return; }
	// play pressed sound:
	snd_play(toggleButtonWav, 50, 0);
	// toggle buttons:
	buttonState += 1;
	buttonState %= 2;	
	// if start button selected:
	if(buttonState == 0){
		// chagne the bmap:
		startGamePan.bmap = startOn;
		exitGamePan.bmap = exitOff;
	}
	// if exit button selected:
	if(buttonState == 1){
		// chagne the bmap:
		startGamePan.bmap = startOff;
		exitGamePan.bmap = exitOn;
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// the polygonal wall object:
action actWall(){
	// set proper material:
	my.material = mtl_unlit;
	// make me polygonal:
	set(my, POLYGON);
	// make me static:
	reset(my, DYNAMIC);
	// wait one frame:
	wait(1);
	// set proper bbox:
	c_setminmax(my);
	// object type:
	my.objType = objWall;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// the polygonal floor object:
action actFloor(){
	// move the floor down:
	my.z -= BLOCK_SIZE;
	// set proper material:
	my.material = mtl_unlit;
	// make me passable:
	set(my, PASSABLE);
	// make me static:
	reset(my, DYNAMIC);
	// wait one frame:
	wait(1);
	// set proper bbox:
	c_setminmax(my);
	// object type:
	my.objType = objFloor;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// player's action:
action actHero(){
	// pointer:
	heroEnt = my;
	// flags:
	set(my, INVISIBLE);
	// wait one frame:
	wait(1);
	// set proper bbox:
	c_setminmax(my);
	// object type:
	my.objType = objHero;
	// save the new position:
	vec_set(newPos.x, my.x);
	// wait till we load the level:
	while(gameReady == 0){ wait(1); }
	// load next level, if needed:
	nextLevel();
	// create visual model:
	ghostEnt = ent_create(ghostMdl, my.x, NULL);
	// set proper material:
	ghostEnt.material = mtl_unlit;
	// show gui:
	set(gameGuiPan, SHOW);
	// loop:
	while(me){
		// if we press esc:
		if(key_esc){
			// exit the game:
			sys_exit("");
		}
		// change the fonts:
		draw_textmode("Fixedsys", 1, NULL, 100);		
		// help GUI:
		draw_text("[R] - RESTART", 10, 10, COLOR_WHITE);
		draw_text("[ESC] - EXIT", 10, 30, COLOR_WHITE);
		draw_text("STEP:", 10, 60, COLOR_WHITE);
		// show current level:
		draw_text(str_printf(NULL, "STAGE:   %d",  (long)(currentLevel)), 10, 80, COLOR_WHITE);
		// only once per key:
		if(keyOnce == 0){
			// if we press up key:
			if(key_cuu == 1){
				// move player upwards:
				newPos.x -= BLOCK_SIZE;
				// move only once:
				keyOnce = 1;
				// if we have visual model:
				if(ghostEnt != NULL){
					// rotate player up:
					ghostEnt.pan = 180;
				}
			}
			// if we press down key:
			if(key_cud == 1){
				// move player downwards:
				newPos.x += BLOCK_SIZE;
				// move only once:
				keyOnce = 1;
				// if we have visual model:
				if(ghostEnt != NULL){
					// rotate player up:
					ghostEnt.pan = 0;
				}
			}
			// if we pressed left key:
			if(key_cul == 1){
				// move player to the left:
				newPos.y -= BLOCK_SIZE;
				// move only once:
				keyOnce = 1;
				// if we have visual model:
				if(ghostEnt != NULL){
					// rotate player up:
					ghostEnt.pan = 270;
				}
			}
			// if we pressed right key:
			if(key_cur == 1){
				// move player to the right:
				newPos.y += BLOCK_SIZE;
				// move only once:
				keyOnce = 1;
				// if we have visual model:
				if(ghostEnt != NULL){
					// rotate player up:
					ghostEnt.pan = 90;
				}
			}
		}
		else{
			// if non of the movement key's are pressed, then we can move:
			if(key_cuu == 0 && key_cud == 0 && key_cul == 0 && key_cur == 0){
				// reset switch:
				keyOnce = 0;
			}
		}
		// if we tried to move:
		if(keyOnce == 1){
			// reset switch:
			pressedOnce = 0;
			// check for collusions (define trace_mode):
			trace_mode = IGNORE_ME | IGNORE_PASSABLE | IGNORE_PASSENTS | IGNORE_CONTENT | IGNORE_SPRITES
			| IGNORE_FLAG2 | IGNORE_WORLD | IGNORE_MAPS | IGNORE_PUSH | ACTIVATE_SHOOT;
			// make a trace:
			c_trace(my.x, newPos.x, trace_mode);
			// if we hit anything:
			if(trace_hit){
				// then we can't move:
				vec_set(newPos.x, my.x);
			}
			else{
				// move player:
				vec_set(my.x, newPos.x);
				// if we can:
				if(pressedOnce == 0){
					// we pressed the key:
					keyPressed += 1;				
					// only once:
					pressedOnce = 1;
				}
			}
		}
		// if we have visual model:
		if(ghostEnt != NULL){
			// animation speed:
			ghostEnt.skill10 += 10 * time_step;
			// animate visual model:
			ent_animate(ghostEnt, "frame", ghostEnt.skill10, ANM_CYCLE);
			// move visual model:
			vec_set(ghostEnt.x, my.x);
		}
		// wait one frame:
		wait(1);
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// check for collusions:
void checkBoxCollusion(){
	// wait one frame:
	wait(1);
	// check for collusions (define trace_mode):
	trace_mode = IGNORE_ME | IGNORE_PASSABLE | IGNORE_PASSENTS | IGNORE_CONTENT | IGNORE_SPRITES
	| IGNORE_FLAG2 | IGNORE_WORLD | IGNORE_MAPS | IGNORE_PUSH;
	// make a trace:
	c_trace(my.x, newBoxPos.x, trace_mode);
	// if we hit anything:
	if(trace_hit){
		// then we can't move:
		vec_set(newBoxPos.x, my.x);
	}
	else{
		// move the box:
		vec_set(my.x, newBoxPos.x);
		// move player's collusion:
		vec_set(newPos.x, oldBoxPos.x);
		// move player to our old position:
		vec_set(heroEnt.x, newPos.x);
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// box event:
void boxEvent(){
	// if we were hit:
	if(event_type == EVENT_SHOOT){
		// and if we were hit by player:
		if(you == heroEnt){
			// save old positions:
			vec_set(oldBoxPos.x, my.x);
			// calculate the new position:
			newBoxPos.x = my.x - (heroEnt.x - my.x);
			newBoxPos.y = my.y - (heroEnt.y - my.y);
			newBoxPos.z = my.z;
			// check for collusions:
			checkBoxCollusion();
		}
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// pushable box action:
action actBox(){
	// vector:
	VECTOR temp;
	// free vector:
	vec_fill(temp.x, 0);
	// set proper material:
	my.material = mtl_unlit;
	// make me polygonal:
	set(my, POLYGON);
	// wait one frame:
	wait(1);
	// set proper bbox:
	c_setminmax(my);
	// set event type:
	my.emask |= ENABLE_SHOOT;
	// set event function:
	my.event = boxEvent;
	// object type:
	my.objType = objBox;
	// skills:
	my.checkOnce = 0;
	// wait till we load the level:
	while(gameReady == 0){ wait(1); }
	// loop:
	while(me){
		// save our position:
		vec_set(temp.x, my.x);
		// define end position of trace:
		temp.z -= BLOCK_SIZE * 2;
		// check for target below the box (define trace_mode):
		trace_mode = IGNORE_ME | IGNORE_PASSABLE | IGNORE_PASSENTS | IGNORE_CONTENT | IGNORE_SPRITES
		| IGNORE_WORLD | IGNORE_MAPS | IGNORE_PUSH | SCAN_TEXTURE;
		// make a trace:
		c_trace(my.x, temp.x, trace_mode);
		// if we hit model:
		if(hit.entity){
			// and it's a target position:
			if(you.objType == objBoxTarget){
				// if we can, then check:
				if(my.checkOnce != 1){
					// we got one box on proper position:
					boxPlaceLeft -= 1;
					// do this once:
					my.checkOnce = 1;
				}
			}
			else{
				// if we can, then check:
				if(my.checkOnce != 2){
					// we still have one box left:
					boxPlaceLeft += 1;
					// do this once:
					my.checkOnce = 2;
				}
			}
		}
		else{
			// if we can, then check:
			if(my.checkOnce != 0){
				// we still have one box left:
				boxPlaceLeft += 1;
				// do this once:
				my.checkOnce = 0;
			}
		}
		// wait one frame:
		wait(1);
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// box target object:
action actBoxTarget(){
	// plus one box:
	boxPlaceLeft += 1;
	// move the floor down:
	my.z -= BLOCK_SIZE;
	// set proper material:
	my.material = mtl_unlit;
	// passable for movement traces:
	set(my, FLAG2 | POLYGON);
	// wait one frame:
	wait(1);
	// set proper bbox:
	c_setminmax(my);
	// object type:
	my.objType = objBoxTarget;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// camera position:
action actCamera(){
	// set flags (make passable and invisible):
	set(my, PASSABLE | INVISIBLE);
	// wait till we load the level:
	while(gameReady == 0){ wait(1); }
	// set the position of the camera:
	vec_set(camera.x, vector(my.x, my.y, my.z + 200));
	// rotate camera properly:
	vec_set(camera.pan, vector(180, -90, 0));
	// make camera isometric:
	set(camera, ISOMETRIC);
	// adjust distance:
	camera.arc = cameraArc;
	// object type:
	my.objType = objCam;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// fog, sky, clipping:
void fogColor(){
	// lods:
	vec_set(d3d_lodfactor, vector(12.5, 25, 50)); 
	// sunlight:
	sun_light = 0;
	// camera clipping parameters:
	camera.clip_near = 1;
	camera.clip_far = 2500;
	// fog parameters:
	camera.fog_start = 100; 
	camera.fog_end = 2000; 
	// fog and sky colors:
	fog_color = 4;
	// change fog color:
	vec_set(d3d_fogcolor4.blue, vector(5, 5, 5));
	// change sky color:
	vec_set(sky_color.blue, d3d_fogcolor4.blue);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// create the level:
void createLevel(STRING* mapStr){
	// reset camera angles:
	vec_set(camera.pan, vector(180, 90, 0));
	// reset player pointers:
	heroEnt = NULL;
	ghostEnt = NULL;
	// reset key counter:
	keyPressed = 0;
	// reset box counter:
	boxPlaceLeft = 0;
	// reset lines index:
	lines_index = 0;
	// freeze the game:
	gameReady = 0;
	// open the map:
	var handleMap = file_open_read(mapStr);
	// if we don't have the file:
	if(handleMap == 0){
		// show error message and exit:
		sys_exit("NO MAP FILE!");
	}
	// get it's size (width and height):
	mapWidth = file_var_read(handleMap);
	mapHeight = file_var_read(handleMap);
	// reset tile positions:
	vec_fill(tilePos, 0);
	// loop:
	for(lines_index = 0; lines_index < mapHeight; lines_index ++){
		// read the first line of the map file:
		file_str_read(handleMap, line_characters);
		// go till the end of the first line:
		for(NULL; str_len(line_characters) != 0; str_clip(line_characters, 1)){
			// read the each letter, one by one:
			str_cpy(empty, line_characters);
			// clip the returned letter, from the end of the line:
			str_trunc(empty, str_len(empty) - 1);
			// if we've found a wall:
			if(str_cmp(empty, "w") == 1){
				// create a wall model:
				ent_create(wallMdl, tilePos.x, actWall); 
			}
			// if we've found a floor:
			if(str_cmp(empty, ".") == 1){
				// create a floor model:
				ent_create(floorMdl, tilePos.x, actFloor); 
			}
			// if we've found a player:
			if(str_cmp(empty, "p") == 1){
				// create a floor model:
				ent_create(floorMdl, tilePos.x, actFloor); 
				// create a player:
				ent_create(playerMdl, tilePos.x, actHero); 
			}
			// if we've found a box:
			if(str_cmp(empty, "b") == 1){
				// create a floor model:
				ent_create(floorMdl, tilePos.x, actFloor); 
				// create a box:
				ent_create(boxMdl, tilePos.x, actBox); 
			}
			// if we've found a box target position:
			if(str_cmp(empty, "t") == 1){
				// create a target model:
				ent_create(boxTargetMdl, tilePos.x, actBoxTarget); 
			}
			// if we've found a camera with floor:
			if(str_cmp(empty, "c") == 1){
				// create a floor model:
				ent_create(floorMdl, tilePos.x, actFloor); 
				// create a camera position:
				ent_create(boxMdl, tilePos.x, actCamera); 
			}
			// if we've found a camera with wall:
			if(str_cmp(empty, "k") == 1){
				// create a wall model:
				ent_create(wallMdl, tilePos.x, actWall); 
				// create a camera position:
				ent_create(boxMdl, tilePos.x, actCamera); 
			}			
			// if we've found a box properly placed on the box:
			if(str_cmp(empty, "=") == 1){
				// create a target model:
				ent_create(boxTargetMdl, tilePos.x, actBoxTarget); 
				// create a box:
				ent_create(boxMdl, tilePos.x, actBox); 
			}
			// move the tile (spawn) position on the grid:
			tilePos.y += BLOCK_SIZE;
			// plus one row:
			mapRow += 1;
		}
		// move the tille Y position on the grid:
		tilePos.x += BLOCK_SIZE;
		// reset X tile positions:
		tilePos.y = 0;
		// reset rows:
		mapRow = 0;
		// plus one collum:
		mapCollum += 1;
	}
	// we can play now:
	gameReady = 1;
	// if we need to hide loading panel:
	if(is(loadGamePan, SHOW)){
		// hide it:
		reset(loadGamePan, SHOW);
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// restart the game:
function restartGame(){
	// don't do anything, till we create the level:
	if(gameReady == 0){ return; }
	// if we need to show loading panel:
	if(!is(loadGamePan, SHOW)){
		// show it:
		set(loadGamePan, SHOW);
	}
	// hide gui:
	reset(gameGuiPan, SHOW);
	// play pressed sound:
	snd_play(toggleButtonWav, 50, 0);
	// freeze input:
	freeze_mode = 1;
	// load empty level:
	level_load("");
	// wait for a while:
	wait(1);
	// unfreeze the game:
	freeze_mode = 0; 
	// if we need to load a first level:
	if(currentLevel == 1){
		// load it:
		createLevel(map01Str);
	}
	// if we need to load a second level:
	if(currentLevel == 2){
		// load it:
		createLevel(map02Str);
	}
	// if we need to load a third level:
	if(currentLevel == 3){
		// load it:
		createLevel(map03Str);
	}
	// if we need to load a fourth level:
	if(currentLevel == 4){
		// load it:
		createLevel(map04Str);
	}
	// if we need to load a fifth level:
	if(currentLevel == 5){
		// load it:
		createLevel(map05Str);
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// load current level:
void loadLevel(){
	// if we need to show loading panel:
	if(!is(loadGamePan, SHOW)){
		// show it:
		set(loadGamePan, SHOW);
	}
	// if we have an empty level number:
	if(currentLevel == 0){
		// set default first level:
		currentLevel = 1;
	}
	// if we need to load a first level:
	if(currentLevel == 1){
		// load it:
		createLevel(map01Str);
		// set proper arc:
		cameraArc = 40;
	}
	// if we need to load a second level:
	if(currentLevel == 2){
		// load it:
		createLevel(map02Str);
		// set proper arc:
		cameraArc = 40;
	}
	// if we need to load a third level:
	if(currentLevel == 3){
		// load it:
		createLevel(map03Str);
		// set proper arc:
		cameraArc = 40;
	}
	// if we need to load a fourth level:
	if(currentLevel == 4){
		// load it:
		createLevel(map04Str);
		// set proper arc:
		cameraArc = 35;
	}
	// if we need to load a fifth level:
	if(currentLevel == 5){
		// load it:
		createLevel(map05Str);
		// set proper arc:
		cameraArc = 35;
	}
	// if we have to load the sixth level:
	if(currentLevel == 6){
		// show game is finished message:
		error("You've Finished The Game!");
		// exit:
		sys_exit("");
	}
	// wait till we load the level:
	while(gameReady == 0){ wait(1); }
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// next level loader:
void nextLevel(){
	// wait till all boxes are placed:
	while(boxPlaceLeft > 0){ wait(1); }
	// hide gui:
	reset(gameGuiPan, SHOW);
	// play a sound:
	snd_play(pressButtonWav, 40, 0);
	// load next level:
	currentLevel += 1;
	// freeze input:
	freeze_mode = 1;
	// load empty level:
	level_load("");
	// wait for a while:
	wait(1);
	// unfreeze the game:
	freeze_mode = 0;
	// load it:
	loadLevel();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// the main game loop:
void gameLoop(){
	// change background, fog colors:
	fogColor();
	// endless loop:
	while(1){
		// update position of the press enter panel:
		loadGamePan.pos_x = (screen_size.x / 2) - (bmap_width(loadGamePan.bmap) / 2);
		loadGamePan.pos_y = screen_size.y / 1.2;
		// wait one frame:
		wait(1);
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// main game function:
void main(){
	// video modes:
	video_set(800, 600, 16, 2);
	// no wide-screen:
	video_aspect = 1.333;
	// window title:
	video_window(NULL, NULL, NULL, "PushTheBox");	
	// doppler factor:
	doppler_factor = 0;
	// show all errors:
	warn_level = 6;
	// max fps limit:
	fps_max = 30;
	// min fps:
	fps_min = 20;
	// smooth out fps:
	time_smooth = 0.5;
	// freeze input:
	freeze_mode = 1;
	// load empty level:
	level_load("");
	// wait for a while:
	wait(1);
	// unfreeze the game:
	freeze_mode = 0;
	// run game loop:
	gameLoop();
	// play A8 logo:
	handleLogo = media_play("A8AnimLogo.wmv", NULL, 80);
	// wait till it's finished:
	while(media_playing(handleLogo)){
		// if we press any key while playing the logo:
		if(key_esc){
			// turn it off:
			break; 
		} 
		// wait one frame:
		wait(1); 
	}
	// turn off the logo, if needed:
	if(media_playing(handleLogo)){
		// turn it off:
		media_stop(handleLogo);
	}
	// wait for a while:
	wait(-0.5);
	// play menu music:
	handleMusic = media_loop("menu.wav", NULL, 80);
	// make panels visible:
	set(splashPan, SHOW);
	set(pressEnterPan, SHOW);
	// init splash positions:
	splashPan.pos_x = 0;
	splashPan.pos_y = 0;
	// change splash screen scale:
	splashPan.scale_x = (screen_size.x / bmap_width(splashPcx));
	splashPan.scale_y = (screen_size.y / bmap_height(splashPcx));	
	// update position of the press enter panel:
	pressEnterPan.pos_x = (screen_size.x / 2) - (bmap_width(pressEnterTga) / 2);
	pressEnterPan.pos_y = screen_size.y / 1.2;
	// wait for a while:
	wait(-0.1);
	// wait till enter is pressed:
	while(!key_enter){
		// init splash positions:
		splashPan.pos_x = 0;
		splashPan.pos_y = 0;
		// change splash screen scale:
		splashPan.scale_x = (screen_size.x / bmap_width(splashPcx));
		splashPan.scale_y = (screen_size.y / bmap_height(splashPcx));	
		// hide the enter panel:
		if((total_frames % 10) == 0){
			// if we need to:
			if(is(pressEnterPan, SHOW)){
				// hide it:
				reset(pressEnterPan, SHOW);
			}	
		}
		// show the enter panel:
		if((total_frames % 20) == 0){
			// if we need to:
			if(!is(pressEnterPan, SHOW)){
				// show it:
				set(pressEnterPan, SHOW);
			}	
		}
		// update position of the press enter panel:
		pressEnterPan.pos_x = (screen_size.x / 2) - (bmap_width(pressEnterTga) / 2);
		pressEnterPan.pos_y = screen_size.y / 1.2;
		// wait one frame:
		wait(1);
	}
	// play pressed sound:
	snd_play(pressButtonWav, 40, 0);
	// hide all panels:
	reset(splashPan, SHOW);
	reset(pressEnterPan, SHOW);
	// realise the memory:
	bmap_purge(splashPan.bmap);
	bmap_purge(pressEnterPan.bmap);
	// wait for a while:
	wait(-0.5);
	// allow to toggle buttons:
	buttonAllow = 1;
	// toggle buttons:
	on_cuu = toggleButtons;
	on_cud = toggleButtons;
	// set proper position of the buttons (start button):
	startGamePan.pos_x = (screen_size.x / 2) - (bmap_width(startGamePan.bmap) / 2);
	startGamePan.pos_y = screen_size.y / 1.3;
	// exit button:
	exitGamePan.pos_x = (screen_size.x / 2) - (bmap_width(exitGamePan.bmap) / 2);
	exitGamePan.pos_y = screen_size.y / 1.2;
	// show buttons:
	set(startGamePan, SHOW);
	set(exitGamePan, SHOW);
	// show menu (till we haven't pressed the button yet):
	while(buttonPushed == 0){
		// set proper position of the buttons (start button):
		startGamePan.pos_x = (screen_size.x / 2) - (bmap_width(startGamePan.bmap) / 2);
		startGamePan.pos_y = screen_size.y / 1.3;
		// exit button:
		exitGamePan.pos_x = (screen_size.x / 2) - (bmap_width(exitGamePan.bmap) / 2);
		exitGamePan.pos_y = screen_size.y / 1.2;
		// if we pressed the enter:
		if(key_enter){
			// then break the loop:
			buttonPushed = 1;
		}
		// wait one frame:
		wait(1);
	}
	// hide buttons:
	reset(startGamePan, SHOW);
	reset(exitGamePan, SHOW);
	// realise the memory:
	bmap_purge(startGamePan.bmap);
	bmap_purge(exitGamePan.bmap);
	// play pressed sound:
	snd_play(pressButtonWav, 40, 0);
	// wait for a while:
	wait(-0.5);
	// if we selected exit:
	if(buttonState == 1){
		// then close the game:
		sys_exit("");
	}
	// don't allow to toggle buttons:
	buttonAllow = 0;
	// load the level:
	loadLevel();
	// wait till we load the level:
	while(gameReady == 0){ wait(1); }
	// stop the old menu music:
	if(media_playing(handleMusic)){
		// turn it off:
		media_stop(handleMusic);
	}
	// restart the game:
	on_r = restartGame;
	// play intro sound:
	handleMusic = media_play("intro.wav", NULL, 80);
	// wait till it's finished:
	wait(-2.4);
	// start playing a music loop:
	handleMusic = media_loop("music.wav", NULL, 80);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////