// main.cpp
#include <iostream>
#include <ncurses.h>
#include <vector>
#include <algorithm>
#include <functional>
#include "game.h"
#include "drawscreen.h"

/*	
 *		This program is free software: you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License as published by
 *	the Free Software Foundation, either version 3 of the License, or
 *	(at your option) any later version.
 *
 *		This program is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU General Public License for more details.
 * 
 *		You should have received a copy of the GNU General Public License
 *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

/*
 * 	These dependancies must be installed to compile this program in ubuntu:
 *	sudo apt-get install build-essential ncurses-dev
 *	
 *	Compile & run on linux:
 *	g++ -Wall main.cpp game.cpp drawscreen.cpp -lncurses -std=c++11
 * 
 *  Run:
 *	./a.out 
 * 
 */


/*	
 * 	This game starts off with the main character in a blank rectangle bordered
 *  area with no other objects. With the instuctions below you can build your
 *  own level in realtime; add enemies, players, objects, create automatic
 *  movements... Later on there will be the ability to save the map to disk.
 * 
 * 
 * 	Gameplay:
 * 
 *	a = left
 *	d = right
 *	s = down / stop jumping
 *	w = jump / up, when in edit mode
 * 
 * 
 *  unrestricted movement:
 * 
 *  up arrow
 *  down arrow
 *  left arrow
 *  right arrow
 * 
 *	steers character but is unrestrained and allows to go through objects.
 *  used mostly in edit mode
 * 
 * 
 *	e = edit mode
 *
 *	edit mode allows one to move around the board without gravity effects 
 *	on particular character
 * 
 * 
 *	r = record moves
 * 
 * 	when 'r' is pressed the game starts recording your moves. press
 *	'r' again to go back into play mode and playback the moves. note
 *	that while playing moves you cannot control the character. to
 * 	regain control simply press 'r' twice. this will record 0 moves
 *	and allow movement freedom. also, moves will not play in edit mode
 *
 * 
 * 	1-9 = switch to player number < keypressed >
 * 
 *	you can automatically switch to any other player by
 * 	pressing their player number button
 * 
 * 
 *  0 = control object
 * 
 *  pressing '0' whilst hovering over an object allows you to become that object
 * 
 * 
 *  '-' and '=', cycle through and change character types
 * 
 * 
 *  n = new object
 * 
 *  pressing 'n' make a new object appear right behind the current object.
 *  you must be in edit mode to add objects or game will go into infinit
 *  recursion due to pusher function in the collision method; bug
 * 
 * 
 *  c = clear object
 * 
 *  hover over a character and press 'c' to clear them
 * 
 * 
 *	q / esc = quit game
 *
 * 
 * 
 * 
 * 	Benefits of game:
 *  
 *  - NOTES!!! - Almost every line of code has notes, not on 'what' is
 *	  happening, but 'why' it has to happen :)
 * 	- 0 number of errors or warnings  in compile (g++ -wall mode)
 *	- debugging stats on screen during gameplay
 *  - sectioned areas for speed and large maps
 *	- infinit player ability
 *  - multiple collision cooridinates per object (as many as needed)
 *  - most data is not hardcoded
 *  - using c++11 features (must compile for c++11)
 *  - easily upgradable to graphics (have done before with SDL)
 *  - collision detection can detect collision at any speed/skip rate
 *  - four direction distance detection on dashboard (can add other directions)
 * 	- easy to add split / dual screens / dual/triple... games
 * 	- all objects / characters treated the same. whatever a player
 * 	  can do, all objects can do, eg.. enemies, and even a brick, can jump.
 *    as well, enemies, player, and a brick can fly...
 * 	- can morpth or take over control of any other player or object
 * 	- encapsulated data; no #defines, static, and other global variables
 *
 * 
 *	bugs (what game is without bugs??):
 * 
 *  #1 there is a bug that causes the characters to sink into
 *	the platform when entering and leaving other sections. temp fix
 * 	can be implimented by uncommenting line 141/142 in drawscreen.cpp.
 *  temp fix applied by default
 *	
 *  #2 the method 'moveSection' in game.cpp causes system to lose players
 *  focus and alternates to other players can be temp fixed by commenting
 *  out this method
 * 
 *  #3 game.cpp, 'collision' method has a built in system that will be used
 *  to allow objects to move players, and players to move other players. this
 *  is not fully implimented and will cause infinit recursion if trying to
 *  add a new object whilst not in edit mode. temp fix applied by default
 *  in game.cpp, method 'keyboardCommand', case 110.
 * 
 * 
 * 	Please note that I am a beginner programmer and this is my second
 * 	small C++ game. I have not made a map or implimented any other
 *  features as I feel it would be better focus on the basics.
 * 
 *  Comments regarding programming style are programming tips are
 *  welcomed and encouraged. Please refrain from giving ideas
 *  regarding gameplay and gameplay options, such as, "You should make
 *  the character be able to shoot and duck." I am not looking for such
 *  input.
 *  
 */

int main()
{
	
	// create draw object
	DrawScreen drawGame;
	
	// create game object vector
	std::vector<std::vector<Game>> obj;
	
	// create game character objects
	Game::initialiseGame(obj, drawGame);
	
	// run game
	while (drawGame.keepPlaying())
	{
		// get key presses and slow down game speed
		drawGame.grabKeys();
		
		// draw objects
		drawGame.drawboard(obj);
		
		// calculate the lowest and highest section within range
		register unsigned int lowSection, highSection;
		drawGame.sectionLowTohigh(obj, lowSection, highSection);

		// move objects		
		for(unsigned int currentSection = lowSection;
			currentSection <= highSection; ++currentSection)
			for(unsigned int i = 0; i < obj[currentSection].size(); ++i)
				obj[currentSection][i].moveCharacter(obj, drawGame, currentSection, i);
		
		// draw all data to screen
		refresh();

	}

	// shut down ncurses and exit
	endwin();
	
	return 0;
}
