Browse Source

Commit invaders version 4.5

Enrico Guiraud 4 years ago
commit
187efd0af2
51 changed files with 4895 additions and 0 deletions
  1. 67 0
      README.txt
  2. 1 0
      args.tmp
  3. 5 0
      big_alienboss.dat
  4. 5 0
      big_alienboss.dat.old
  5. 1 0
      body.cpp
  6. 16 0
      body.hpp
  7. 68 0
      boss.cpp
  8. 29 0
      boss.hpp
  9. 341 0
      bossrush.cpp
  10. 300 0
      box.cpp
  11. 40 0
      box.hpp
  12. 17 0
      bullet.cpp
  13. 19 0
      bullet.hpp
  14. 115 0
      checkboss.sh
  15. 1 0
      dati.dat
  16. 94 0
      definitions.hpp
  17. 77 0
      definitions.hpp.bu
  18. 38 0
      enemy.cpp
  19. 23 0
      enemy.hpp
  20. 2020 0
      functions.cpp
  21. 129 0
      functions.hpp
  22. 9 0
      game_object.cpp
  23. 14 0
      game_object.hpp
  24. 344 0
      invaders.cpp
  25. 324 0
      invaders_fork.cpp
  26. 10 0
      latest.dat
  27. 6 0
      maderna.dat
  28. 6 0
      maero.dat
  29. 91 0
      makefile
  30. 8 0
      myboss.dat.old
  31. 44 0
      notes.dat
  32. 12 0
      objectsIDs.txt
  33. 0 0
      palombo
  34. 5 0
      palombo.dat
  35. 5 0
      palombo.dat.old
  36. 58 0
      pic.cpp
  37. 25 0
      pic.hpp
  38. 213 0
      player.cpp
  39. 29 0
      player.hpp
  40. 5 0
      powerup.cpp
  41. 12 0
      powerup.hpp
  42. 45 0
      records.dat
  43. 2 0
      records_bossrush.dat
  44. 18 0
      rocket.cpp
  45. 19 0
      rocket.hpp
  46. 66 0
      setboss.sh
  47. 43 0
      setsize.sh
  48. 6 0
      spoletini.dat
  49. 6 0
      spoletini.dat.old
  50. 44 0
      wall.cpp
  51. 20 0
      wall.hpp

+ 67 - 0
README.txt

@@ -0,0 +1,67 @@
+#==Space Invaders==
+#
+#Original game was created and developed by Giacomo Parolini and Enrico Guiraud (year 2010-2011)
+#License: GNU GPL
+#
+#Avaiable game versions:
+# -invaders2.0
+# -invaders2.1
+# -invaders3.0
+# -invaders3.1
+# -invaders3.2
+# -invaders3.3
+# -invaders3.4
+# -invaders3.5
+# -invaders3.6
+# -invaders4.0
+# -invaders4.1
+# -invaders4.2
+# -invaders4.3
+# -invaders4.3.5
+# -curses_invaders2.0
+# -curses_invaders3.0
+# -curses_invaders3.5
+# -curses_invaders4.0
+# -curses_invaders4.1
+# -curses_invaders4.2
+# -curses_invaders4.3
+# -GL_invaders
+#
+#All versions are written in C++. 
+#
+#curses_invaders versions were developed by Giacomo Parolini and differ from the previous ones for exploiting library <ncurses.h> for graphic terminal management.
+#GL_invaders versions were developed by Enrico Guiraud and exploit GL libraries such as <glutm/window.h> and <glt/project.h> for graphics.
+#
+#System Requirements:
+#All versions are Linux x-executable files, so will only run within Linux environment.
+#However, files CAN be compiled also in MacOS environment.
+#
+#GL_invaders versions require GLT libraries in order to be compiled and run.
+#note that the macro GLT_DIR in GL_invaders's makefile refers to a specific folder, therefore, if you want to compile the game on your computer, you'll need to match the correct destination for macro GLT_DIR!
+#
+#curses_invaders versions require the library <ncurses.h> and may not work correctly on some terminals. Versions 3.0 and following also contain executable "bossrush".
+#
+#curses_invaders4.0 and following include the <pthread.h> library (used for executing sounds and music). Sound and music work only in terminals with command "beep".
+#
+#since v.4.3, game controls are customizable at the beginning of the game.
+#
+#Other: header files are *.hpp and implementations are *.cpp.
+#
+#Makefile includes the following dummy macros:
+# -open: opens all source files
+# -openhpp: opens all header files
+# -opencpp: opens all implementations
+# -clean: removes all objects
+# -cleanall: removes all objects and executable
+# -remake: removes previous objects and compiles
+#
+#CREATING AND EDITING BOSSES
+#curses_invaders4.0 and following also come with the scripts checkboss.sh and setboss.sh, written by Enrico Guiraud. These scripts are used to edit the five game bosses, allowing the player to create his custom bosses. 
+#In order to create a boss, follow these steps:
+# *1: create a file named <custom_boss_name>.dat and open it with any text editor (like Gedit, Vim or Notepad).
+# *2: "draw" your boss in ASCII-style. You don't have to pay attention of the rows' lengths, as checkboss.sh will fix them automatically. Just be sure the lines and the columns fit the game board (game board's dimensions are written in definitions.hpp as "R" and "C").
+# *3: save your file.dat and launch either checkboss.sh (if you just want to adjust your boss's dimensions) or directly setboss.sh (to add the boss to the game). Syntax of checkboss.sh is "./checkboss.sh <bossname.dat>" or "./checkboss <bossname>". Syntax of setboss.sh is "./setboss.sh <bossname> <level>"; the script will substitute the boss of the <level>-th game level (1=easy, 2=medium, 3=hard, 4=impossible, 5=special boss) with your custom boss. Notice that setboss.sh needs you to pass the argument WITHOUT the ".dat".
+# *4: play to test your new boss! If you want to restore the original boss, just run setboss.sh once again passing the original boss as argument.
+
+
+#...and yes: cheats ARE available, just try and find them ;)

+ 1 - 0
args.tmp

@@ -0,0 +1 @@
+palombo.dat

+ 5 - 0
big_alienboss.dat

@@ -0,0 +1,5 @@
+ \__ ______ __/  
+\___  =  =  ___/ 
+ |  | =  = |  |  
+     \_  _/      
+    /  ||  \     

+ 5 - 0
big_alienboss.dat.old

@@ -0,0 +1,5 @@
+ \__ ______ __/  
+\___  =  =  ___/ 
+ |  | =  = |  |  
+     \_  _/      
+    /  ||  \     

+ 1 - 0
body.cpp

@@ -0,0 +1 @@
+#include "body.hpp"

+ 16 - 0
body.hpp

@@ -0,0 +1,16 @@
+#ifndef _body_hpp
+#define _body_hpp
+
+#include "definitions.hpp"
+
+
+class body
+{
+	public:
+	body(){ width=0; height=0; }
+	body(int w, int h) { width=w; height=h; }
+	int width, height;
+};
+
+
+#endif

+ 68 - 0
boss.cpp

@@ -0,0 +1,68 @@
+#include "boss.hpp"
+
+boss::boss(int x, int y, int life, int w, int h, std::string newname) : enemy(x,y), pic(w,h) 
+{
+	name = newname;
+	health=life;
+	healthmax=life;
+	id=16;
+	alive=false;
+}
+
+void boss::next_pos()
+{
+	if((x==0 && direction==1) || (x==C-width-1 && direction==0))
+		direction=2;
+	
+	switch(direction){
+		case 0:
+			x++;
+			break;
+		case 1:
+			x--;
+			break;
+		case 2:
+			y++;
+			if(x==0)
+				direction=0;
+			else direction=1;
+			break;
+	}
+}
+
+void boss::set_life(int life){
+	health=life;
+	healthmax=life;
+}
+
+
+void boss::shoot(std::list<bullet> & bullets){	      //random bomb-dropping	
+	for(std::list<bullet>::reverse_iterator it=bullets.rbegin(); it!=bullets.rend(); ++it)
+		if((it->x==x+width/3 || it->x==x+2*width/3) && it->y==y+height)
+			return;
+	bullet new_bomb(x+width/3,y+height,8);
+	bullets.push_back(new_bomb);
+	bullet new_bomb2(x+2*width/3,y+height,8);
+	bullets.push_back(new_bomb2);
+}
+
+boss& boss::operator=(boss& otherboss)
+{
+	x=otherboss.x;
+	y=otherboss.y;
+	health=otherboss.health;
+	healthmax=otherboss.health;
+	width=otherboss.width;
+	height=otherboss.height;
+	name=otherboss.name;
+	
+	picture = new char* [otherboss.height];
+	for(int i=0; i<height; ++i)
+		picture[i] = new char[otherboss.width];
+	
+	for(int i=0;i<height;i++)
+		for(int j=0;j<width;j++)
+			picture[i][j] = otherboss.picture[i][j];
+				
+	return *this;		//just to get rid of the compiler warning 
+}

+ 29 - 0
boss.hpp

@@ -0,0 +1,29 @@
+#ifndef _boss_hpp
+#define _boss_hpp
+
+#include "enemy.hpp"
+#include "pic.hpp"
+#include <cstring>
+
+typedef std::list<bullet> b_list;
+
+class boss: public enemy, public pic
+{
+	public:
+	boss() { id=16; alive=false; }
+	
+	boss(int x, int y, int life, int w, int h, std::string newname); //id is automatically set to 16, alive set to FALSE
+	
+	void next_pos();
+	//inheriting direction from enemy
+	int health,healthmax;
+	std::string name;
+	void set_life(int);
+
+	void shoot(std::list<bullet> & bullets);
+	
+	boss& operator=(boss&);
+	
+};
+
+#endif

+ 341 - 0
bossrush.cpp

@@ -0,0 +1,341 @@
+#include "definitions.hpp"
+#include "rocket.hpp"
+#include "enemy.hpp"
+#include "player.hpp"
+#include "boss.hpp"
+#include "powerup.hpp"
+#include "functions.hpp"
+#include "wall.hpp"
+#include <mutex>
+#include <thread>
+
+std::mutex m_player;
+std::mutex m_enemies;
+std::mutex m_bombs;
+std::mutex m_bullets;
+std::mutex m_rockets;
+std::mutex m_pow;
+std::mutex m_boss;
+std::mutex m_walls;
+
+using std::cout;
+using std::endl; 
+using std::min;
+using std::max;
+
+int main(int argc,char** argv)
+{
+
+	if(argc>1){
+		if(strcmp(argv[1],"--uber-debug")!=0 && strcmp(argv[1],"--info")!=0){
+			cout<<"Usage: "<<argv[0]<<" [--info]"<<endl;
+			return 1;
+		}
+	
+		if(strcmp(argv[1],"--info")==0){
+			cout<<endl<<"Curses Invaders 4.4 - Bossrush"<<endl;
+			cout<<endl<<"Game developed by Giacomo Parolini (jp) and Enrico Guiraud (blue) in years 2010-2013."<<endl;
+			cout<<"Source code is available under request to jp@lcm.mi.infn.it (it's quite ugly, I warn you ;-) )"<<endl;
+			cout<<"Report any bug to the same mail address."<<endl<<endl;
+			return 1;
+		}
+	}
+
+	typedef std::list<bullet> b_list;
+  	typedef std::vector<wall> w_vec;
+  	typedef std::list<rocket> r_list;
+	
+	srand(time(NULL));
+	
+	//OBJECTS INIZIALIZATION
+
+	player player1;						//player is automatically created in [C/2][R]
+	boss bosses[5];						//vector of bosses
+	b_list bullets;                				//list of player's bullets
+	b_list bombs;						//list of enemies' bombs
+	b_list powerups;					//list of powerups
+	r_list rockets;						//list of rockets
+	boss boss1;
+	std::list<enemy> enemies;
+	int refresh_time=100;          				//how long the program waits before refreshing the screen
+	int chflag=0;						//cheat flag: 0=normal, 1=cheats allowed.
+	int num=0;
+	int commands[CMD_NUM]={'a','d','w','s','p',' ','l','m','q'};
+	
+	WINDOW *Score,*BossHP;
+	
+	//PARAMETERS/UTILITIES
+	double shootrate;				  	//probability of an enemy shooting a bomb 
+	int command;						//keyboard input
+	int score=0;					   	//score: gain +100 when an enemy is destroyed and +50 when a bomb is destroyed
+	char level='1';						//difficulty level
+	
+	create_std_bosses();
+	std::string bossname1=getenv("HOME");
+	bossname1=bossname1+RECORD_DIR+BOSS_FILE1+".dat";
+	boss newboss1(1,1,100,9,6,BOSS_FILE1);	
+	newboss1.loadpicture(bossname1.c_str());	
+	std::string bossname2=getenv("HOME");
+	bossname2=bossname2+RECORD_DIR+BOSS_FILE2+".dat";
+	boss newboss2(1,1,200,11,5,BOSS_FILE2);
+	newboss2.loadpicture(bossname2.c_str());
+	std::string bossname3=getenv("HOME");
+	bossname3=bossname3+RECORD_DIR+BOSS_FILE3+".dat";
+	boss newboss3(1,1,300,9,6,BOSS_FILE3);
+	newboss3.loadpicture(bossname3.c_str());
+	std::string bossname4=getenv("HOME");
+	bossname4=bossname4+RECORD_DIR+BOSS_FILE4+".dat";
+	boss newboss4(1,1,400,11,6,BOSS_FILE4);
+	newboss4.loadpicture(bossname4.c_str());
+	std::string bossname5=getenv("HOME");
+	bossname5=bossname5+RECORD_DIR+BOSS_FILE5+".dat";
+	boss newboss5(1,1,500,17,5,BOSS_FILE5);
+	newboss5.loadpicture(bossname5.c_str());
+	
+	bosses[0]=newboss1;
+	bosses[1]=newboss2;
+	bosses[2]=newboss3;
+	bosses[3]=newboss4;
+	bosses[4]=newboss5;
+
+	boss1=bosses[0];
+	boss1.alive=true;
+
+	player1.weaponclass=1;
+	
+	//NCURSES STUFF
+	initscr();
+	curs_set(0);
+	noecho();	
+	cbreak();
+	keypad(stdscr,TRUE);
+	start_color();
+	init_pair(0,COLOR_WHITE,COLOR_BLACK);
+	init_pair(1,COLOR_GREEN,COLOR_BLACK);	//PLAYER
+	init_pair(2,COLOR_RED,COLOR_BLACK);	//ENEMY
+	init_pair(3,COLOR_YELLOW,COLOR_BLACK);	//BULLETS-POWERUPS
+	init_pair(4,COLOR_MAGENTA,COLOR_BLACK);	//WALLS
+	init_pair(5,COLOR_CYAN,COLOR_BLACK);	//BOSS
+	init_pair(6,COLOR_BLUE,COLOR_BLACK);	//BOMBS
+	init_pair(7,COLOR_RED,COLOR_RED);
+	init_pair(8,COLOR_GREEN,COLOR_GREEN);
+	init_pair(9,COLOR_BLACK,COLOR_GREEN);
+	
+	WALLS_NUM=3;
+	
+	w_vec walls(WALLS_NUM);
+	
+	Score=newwin(3,10,R/3,C+3);
+	BossHP=newwin(3,15,R/3-3,C+3);
+	
+	int i=0;
+	for(w_vec::iterator it=walls.begin(); it!=walls.end(); ++it, ++i)				//creating walls (in a quite symmetric pattern)
+		it->create((i+1)*(C/(3*WALLS_NUM+1))+i*(2*C/(3*WALLS_NUM+1)),2*R/3,(int)min(6,2*C/(3*WALLS_NUM+1)),2,3);
+
+	choose_level_bossrush(shootrate,refresh_time,level,commands);
+	
+	player1.set_commands(commands);
+	
+	if(atoi(&level)<3)
+		player1.weaponclass=2;
+
+	erase();
+	
+	if(argc>1)
+		if(strcmp(argv[1],"--uber-debug")==0){ player1.weaponclass=5; player1.weaponclassrkt=5; player1.rocketlauncher=true; player1.length=MAX_LENGTH; }
+	
+	std::thread t_draw(draw,std::ref(player1),std::ref(bullets),std::ref(bombs),std::ref(enemies),std::ref(walls),std::ref(powerups),std::ref(rockets),std::ref(boss1));
+	
+/////////ENTERING MAIN LOOP
+	
+	while(1)
+	{
+		napms(refresh_time);					//ncurses sleep function (ms)
+
+		timeout(0);
+	    	command = getch();
+	    	              
+	    	if(command!=ERR)                        		//READING INPUT
+	    		command = tolower(command);     
+	    		           
+	    	if(command == commands[8]){ 						//q = exit game
+	    		endwin();
+	    		cout<<lightgreen<<"Game exited correctly."<<none<<endl;
+	    		return 1;
+	    	}  
+
+	    	if(command == commands[4])
+	    		pause_game(chflag);						//p = pause game
+
+	    	if(chflag==1)									//cheats
+	    		get_cheat(command,player1,enemies,shootrate);
+	    	        
+	    	if(command == commands[0] || command == KEY_LEFT || command == commands[1] || command == KEY_RIGHT || ((command == commands[2]|| command == KEY_UP || command == commands[3] || command == KEY_DOWN) && chflag==1)){   	//a or d = move player (if cheats are triggered, also w and s)
+	    		for(int i=player1.x;i<player1.x+player1.length;i++) mvaddch(player1.y,i,' ');	
+	    		player1.next_pos(command);	
+	    	}	    
+	    		
+		if(command==commands[5] || command==commands[6]) {               		//spacebar = shoot!
+			player1.shoot(bullets);
+			if(player1.rocketlauncher) player1.shootrkt(rockets);
+		}
+						
+
+		for(int i=0;i<boss1.width;i++) mvaddch(boss1.y,boss1.x+i,' ');
+		for(int j=0;j<boss1.height;j++){
+			mvaddch(boss1.y+j,boss1.x,' ');
+			mvaddch(boss1.y+j,boss1.x+boss1.width-1,' ');
+		}
+		boss1.next_pos();
+		if((double)rand()/RAND_MAX<shootrate*10.)		
+			boss1.shoot(bombs);	
+		
+		
+		if(!bullets.empty())						//evaluate new bullets' positions
+			for(b_list::iterator it=bullets.begin(); it!=bullets.end(); ++it){
+				mvaddch(it->y,it->x,' ');
+				it->next_pos();
+			}
+				
+		bullets.unique();      					//remove duplicates of bullets (i.e. player can't shoot enemies)
+
+		if(!rockets.empty())						//evaluate new bullets' positions
+			for(r_list::iterator it=rockets.begin(); it!=rockets.end(); ++it){
+				mvaddch(it->y,it->x,' ');
+				it->next_pos();
+			}
+				
+		rockets.unique(); 
+
+		if(!bombs.empty())						//evaluate new bombs' positions
+			for(b_list::iterator it=bombs.begin(); it!=bombs.end(); ++it){
+				mvaddch(it->y,it->x,' ');
+				it->next_pos();
+			}
+			          	
+		bombs.unique();						//remove duplicates of bombs
+
+		if(!powerups.empty())						//new powerups' positions
+			for(b_list::iterator it=powerups.begin(); it!=powerups.end(); ++it){
+				mvaddch(it->y,it->x,' ');
+				it->next_pos();
+			}
+				
+		powerups.unique(); 	 //FIXME: THIS ONLY WORKS ON CONSECUTIVE ELEMENTS OF THE LIST!! we should at least sort powerups before calling unique()
+
+		interactions(player1,bullets,bombs,enemies,walls,powerups,rockets,boss1,score);
+		
+		
+		if(boss1.health<=0)
+			if(num<4){
+				score+=250*atoi(&level)*(num+1);
+				for(int i=max(0,boss1.y-1);i<min(R-1,boss1.y+boss1.height+1);i++)
+					for(int j=0;j<C;j++)
+						mvaddch(i,j,' ');
+				num++;
+				mvwprintw(BossHP,0,1,"             ");
+				if((double)rand()/RAND_MAX<0.25*num){
+					if((double)rand()/RAND_MAX<1./POWERUP_RATIO){
+						if((double)rand()/RAND_MAX<1./ROCKET_RATIO){
+							powerup newpowerup(boss1.x,boss1.y+1,512);
+							powerups.push_back(newpowerup);
+						}
+						else{
+							powerup newpowerup(boss1.x,boss1.y+1,128);
+							powerups.push_back(newpowerup);
+						}
+					}
+					else{
+						powerup newpowerup(boss1.x,boss1.y+1);
+						powerups.push_back(newpowerup);
+					}
+				}
+				if(num==4 && player1.weaponclass<3) player1.weaponclass++;
+				boss1=bosses[num];
+				boss1.alive=true;
+			}
+
+		///////ENDGAME CHECKS               
+		if(boss1.health<1 && num==4)  					//YOU WON!!
+		{
+			Victory_bossrush(boss1.name,score,level,chflag);
+			
+			WINDOW *replay;
+			
+			replay=newwin(3,25,26,20);
+			box(replay,ACS_VLINE,ACS_HLINE);
+			
+			if(playagain(replay))                           //playagain() returns true if player wants to play again, false otherwise
+			{
+				delwin(replay);
+				timeout(500);
+				score=0;
+				erase();
+				refresh();
+				choose_level_bossrush(shootrate, refresh_time,level,commands);
+				reset(player1, enemies, boss1, bullets, bombs, walls, powerups,rockets, level,chflag); // reset box, player, enemy and deletes all bullets and bombs
+				resetbosses(bosses,boss1,player1);
+				num=0;
+				if(atoi(&level)<3)
+					player1.weaponclass=2;
+				erase();
+				refresh();
+				continue;  
+			}
+			else { 
+				endwin();
+				cout<<lightgreen<<"Game exited correctly."<<none<<endl;
+				return 0;
+			}	
+		}
+				
+			
+		if(gameover(player1,bombs))
+		{	
+			Defeat(score);
+			
+			WINDOW* replay;
+		
+			replay=newwin(3,25,17,20);
+			box(replay,ACS_VLINE,ACS_HLINE);
+			
+			if(playagain(replay))                                        //playagain() returns true if player wants to play again, false otherwise
+			{
+				delwin(replay);
+				timeout(500);
+				score=0;
+				erase();
+				refresh();
+				choose_level_bossrush(shootrate, refresh_time, level,commands);
+				reset(player1, enemies, boss1, bullets, bombs, walls, powerups,rockets, level,chflag);       // reset box, player, enemy and delete all bullets and bombs
+				resetbosses(bosses,boss1,player1);
+				num=0;
+				if(atoi(&level)<3)
+					player1.weaponclass=2;
+				erase();
+				refresh();
+				continue;  
+			}
+			else { 
+				endwin();
+				cout<<lightgreen<<"Game exited correctly."<<none<<endl;
+				return 0;
+			}		
+		}
+		
+		write_score(Score,score);
+	
+		if(boss1.alive){
+			write_bosshp(BossHP,boss1.health,boss1.healthmax,boss1.name);
+			wrefresh(BossHP);
+		}
+		
+		wrefresh(Score);
+		refresh();
+
+	}  
+////////END OF MAIN LOOP
+
+	endwin();
+	return 0;
+}

+ 300 - 0
box.cpp

@@ -0,0 +1,300 @@
+#include "box.hpp"
+
+void Box::refresh(b_list& bullets, b_list& bombs, e_list& enemies, player& player1, int &score, boss& boss1,w_vec &walls, b_list& powerups,r_list& rockets)
+{
+	clear();			//Empty matrix
+	upload(bullets, bombs, enemies, player1, boss1, walls, powerups, rockets);	//writes id values on matrix
+	kill(bullets, bombs, enemies, score, boss1, walls, powerups, player1, rockets);	//evaluates interactions and removes what should be removed
+	clear();			//empty again
+	upload(bullets, bombs, enemies, player1, boss1, walls, powerups, rockets);	//rewrites survived game objects' id
+}
+
+
+
+void Box::print()		//this method is used for debugging purposes, not in game
+{
+	for(int k=0; k<R; k++)
+	{
+		for(int l=0; l<C; l++)
+			cout << matrix[k][l] << " ";
+		cout << endl;
+	}
+	cout << endl;
+}
+
+
+
+void Box::clear()
+{
+	for(int i=0; i<R; i++)
+		for(int j=0; j<C; j++)
+			matrix[i][j]=0;			
+}
+
+
+
+void Box::upload(b_list & bullets, b_list& bombs, e_list& enemies, player& player1, boss& boss1, w_vec &walls, b_list & powerups,r_list& rockets)	//writes on the box the IDs of all game objects (even if superimposed). Also uploads curses's window 
+{
+
+	e_list::const_iterator e_end = enemies.end();
+	for(e_list::iterator it=enemies.begin(); it!=e_end; ++it)
+		if(it->alive){
+			attron(COLOR_PAIR(2));
+			mvaddch(it->y,it->x,ENEMY_SPRITE);			
+			matrix[it->y][it->x]+=it->id;
+		}
+	
+	if(!bullets.empty())
+		for(b_list::iterator it=bullets.begin(); it!=bullets.end(); ++it){
+			attron(COLOR_PAIR(3));
+			mvaddch(it->y,it->x,BULLET_SPRITE);
+			matrix[it->y][it->x]+=it->id;
+		}
+		
+	if(!rockets.empty())
+		for(r_list::iterator it=rockets.begin(); it!=rockets.end(); ++it){
+			attron(COLOR_PAIR(4));
+			mvaddch(it->y,it->x,ROCKET_SPRITE);
+			matrix[it->y][it->x]+=it->id;
+		}
+
+	if(!bombs.empty())
+		for(b_list::iterator it=bombs.begin(); it!=bombs.end(); ++it){
+			attron(COLOR_PAIR(6));
+			mvaddch(it->y,it->x,BOMB_SPRITE);
+			matrix[it->y][it->x]+=it->id;
+		}
+		
+	if(!powerups.empty())
+		for(b_list::iterator it=powerups.begin(); it!=powerups.end(); ++it){
+			if(it->id==64){
+				attron(COLOR_PAIR(3));
+				mvaddch(it->y,it->x,POWERUP1_SPRITE);
+			}
+			else if(it->id==128){
+				attron(COLOR_PAIR(1));
+				mvaddch(it->y,it->x,POWERUP2_SPRITE);
+			}
+			else{
+				attron(COLOR_PAIR(4));
+				mvaddch(it->y,it->x,POWERUP3_SPRITE);
+			}
+			matrix[it->y][it->x]+=it->id;
+		}
+				
+	for(int i=player1.x; i<player1.x+player1.length; ++i){
+		attron(COLOR_PAIR(1));
+		mvaddch(player1.y,i,PLAYER_SPRITE);
+		matrix[player1.y][i]+=player1.id;
+	}
+	
+	for(unsigned int i=0;i<walls.size();i++)
+		for(int k=0;k<walls[i].height;k++)
+			for(int j=0;j<walls[i].width;j++)
+				if(walls[i].health[k][j]>0){
+					attron(COLOR_PAIR(4));
+					if(walls[i].health[k][j]==1)
+						attron(COLOR_PAIR(2));
+					mvaddch(walls[i].y+k,walls[i].x+j,WALL_SPRITE);
+					matrix[walls[i].y+k][walls[i].x+j]+=walls[i].id;
+				}
+				
+	if(boss1.alive)					
+		for(int i=boss1.y; i<boss1.y+boss1.height; i++)
+			for(int j=boss1.x; j<boss1.x+boss1.width; j++){
+				if(boss1.health>.5*boss1.healthmax)
+					attron(COLOR_PAIR(5));
+				else if(boss1.health>.25*boss1.healthmax)
+					attron(COLOR_PAIR(3));
+				else
+					attron(COLOR_PAIR(2));
+				mvaddch(i,j,boss1.picture[i-boss1.y][j-boss1.x]);
+				matrix[i][j]+=boss1.id;
+			}
+	
+}
+
+
+
+void Box::kill(b_list & bullets, b_list& bombs, e_list& enemies, int &score, boss& boss1, w_vec &walls, b_list & powerups, player& player1,r_list& rockets)   //controls what changes the box's elements must undergo
+{	
+	
+	for(int i=0; i<R; i++)
+		for(int j=0; j<C; j++)
+		{
+			if(i==0 || i==R-1)
+				switch(matrix[i][j])					//destroys bullets and bombs at box's limits
+				{		              			//DESTRUCTION SHOULD HAPPEN AFTER THEY'VE BEEN PRINTED ONCE!!
+					case 2:
+					case 8:
+					case 64:
+					case 128:
+					case 256:
+					case 512:
+						destroy(i,j,bullets,bombs,enemies,powerups,rockets);
+						break;
+					default:
+						break;
+				}
+			if(!boss1.alive && matrix[i][j]==16) destroy(i,j,bullets,bombs,enemies,powerups,rockets);
+				
+				switch (matrix[i][j])     //id player=1 bullet=2 enemy=4 bomb=8 boss=16 wall=32 powerup+=64, powerup-=128, rocket=256, powerupX=512
+				{		                   
+					case 2:               //destruction cases: 6=enemy+bullet; 10=bomb+bullet; 14=bomb+enemy+bullet; and so on...
+						if(i!=0)
+							if(matrix[i-1][j]==8)	//to make the bullets less 'transparent'...
+							{
+								destroy(i, j, bullets,bombs, enemies,powerups,rockets);
+								destroy(i-1, j, bullets,bombs,enemies,powerups,rockets);
+								score+=50;
+							}
+						break; 
+
+					case 6:			//enemy+bullet
+						score+=100;
+						destroy(i,j,bullets,bombs,enemies,powerups,rockets);
+						if((double)rand()/RAND_MAX<(double)AVERAGE_DROP/ENEMY_NUM)	//a powerup is dropped (AVERAGE_DROP is the mean number of powerups dropped per play in Normal mode)
+						{
+							if((double)rand()/RAND_MAX<1./POWERUP_RATIO){		//1 powerup out of POWERUP_RATIO is either a "-" (with ID 128 instead of 64) or a "X"
+								if((double)rand()/RAND_MAX<1./ROCKET_RATIO){ 	//1 powerup out of ROCKET_RATIO*POWERUP_RATIO is a "X" (ID 512)
+									powerup newpowerup(j,i+1,512);		
+									powerups.push_back(newpowerup);
+								}
+								else{
+									powerup newpowerup(j,i+1,128);		
+									powerups.push_back(newpowerup);
+								}
+							}
+							else{
+								powerup newpowerup(j,i+1);		//otherwise, it is a "+"
+								powerups.push_back(newpowerup);
+							}
+								
+						}
+						break;
+					case 10:			//bomb+bullet
+						score+=50;
+						destroy(i,j,bullets,bombs,enemies,powerups,rockets);
+						break;
+					case 14:			//bomb+enemy+bullet
+						score+=150;
+						destroy(i,j,bullets,bombs,enemies,powerups,rockets);
+						break;
+					case 18:			//boss+bullet
+					case 272:
+						if(j>=boss1.x+boss1.width/2-2 && j<=boss1.x+boss1.width/2+2)
+							boss1.health--;
+						break;	
+					case 34:			//wall+bullet
+					case 40:			//wall+bomb
+					case 288:			//wall+rocket
+						destroy(i,j,bullets,bombs,enemies,powerups,rockets);
+						for(unsigned int k=0;k<walls.size();k++)
+							if(j>=walls[k].x && j<=walls[k].x+walls[k].width && i>=walls[k].y && i<=walls[k].y+walls[k].height)	//finds out what wall has been hit
+								walls[k].health[i-walls[k].y][j-walls[k].x]--;		//subtracts 1 HP to the hit wall's correct health matrix's element 
+						break;
+					case 65:			//"+" powerup+player
+						if(player1.weaponclass<MAX_WEAPONCLASS)
+							player1.weaponclass++;
+						destroy(i,j,bullets,bombs,enemies,powerups,rockets);
+						break;
+					case 68:			//"+" powerup+enemy
+					case 72:			//"+" powerup+bomb
+					case 80:			//"+" powerup+boss
+					case 132:			//"-" powerup+enemy [etc.]
+					case 136:
+					case 144:
+					case 516:			//"X" powerup+enemy [etc.]
+					case 520:
+					case 528:
+						destroy(i,j,bullets,bombs,enemies,powerups,rockets);
+						break;
+					case 129:			//"-" powerup+player
+						if(player1.length>2){
+							mvaddch(player1.y,player1.x+player1.length-1,' ');
+							player1.length--;
+						}
+						destroy(i,j,bullets,bombs,enemies,powerups,rockets);
+						break;
+					case 260:			//enemy+rocket
+					case 264:			//bomb+rocket
+						destroy(i,j,bullets,bombs,enemies,powerups,rockets);
+						break;
+					case 513:			//player+"X" powerup
+						player1.rocketlauncher=TRUE;
+						destroy(i,j,bullets,bombs,enemies,powerups,rockets);
+						break;
+				}
+		}
+}
+
+void Box::destroy(int Y, int X, b_list & bullets, b_list& bombs, e_list& enemies, b_list & powerups,r_list& rockets)	 //destroys any bomb/enemy/bullet/powerup/rocket found in matrix[Y][X]
+{
+
+	b_list::iterator it;
+	r_list::iterator itr;
+	
+	if(!bullets.empty()){
+		it=bullets.begin();                         //we could use remove_if() if i could just think of a way...
+		while(it!=bullets.end())
+		{
+			if(it->x==X && it->y==Y)
+			{
+				mvaddch(it->y,it->x,' ');
+				it = bullets.erase(it);
+				break;
+			} else ++it;
+		}
+	}
+
+	if(!rockets.empty()){
+		itr=rockets.begin();                        
+		while(itr!=rockets.end())
+		{
+			if(itr->x==X && itr->y==Y)
+			{
+				mvaddch(itr->y,itr->x,' ');
+				itr = rockets.erase(itr);
+				break;
+			} else ++itr;
+		}
+	}
+
+	if(!bombs.empty()){
+		it=bombs.begin();                         
+		while(it!=bombs.end())
+		{
+			if(it->x==X && it->y==Y)
+			{
+				mvaddch(it->y,it->x,' ');
+				it = bombs.erase(it);
+				break;
+			} else ++it;
+		}
+	}
+		
+	if(!powerups.empty()){
+		it=powerups.begin();            	     
+		while(it!=powerups.end())
+		{
+			if(it->x==X && it->y==Y)
+			{
+				mvaddch(it->y,it->x,' ');
+				it = powerups.erase(it);
+				break;
+			}else ++it;
+		}
+	}
+
+	e_list::const_iterator e_end = enemies.end();
+	
+	for(e_list::iterator it=enemies.begin(); it!=e_end; ++it)	       //this cycle destroys an enemy in X,Y (quite unefficiently?)
+		if(it->x==X && it->y==Y)
+		{
+			it->alive=false;
+			break;
+		}
+}
+
+
+

+ 40 - 0
box.hpp

@@ -0,0 +1,40 @@
+#ifndef _box_
+#define _box_
+
+#include "player.hpp"
+#include "rocket.hpp"
+#include "enemy.hpp" 	
+#include "boss.hpp"
+#include "wall.hpp"
+#include "powerup.hpp"
+#include "definitions.hpp"
+
+using std::cout; using std::endl;
+
+typedef std::list<bullet> b_list;
+typedef std::list<enemy> e_list;
+typedef std::vector<wall> w_vec;
+typedef std::list<rocket> r_list;
+
+class Box
+{
+	
+	public:
+	Box() { clear(); }
+	~Box() {}
+	
+	int matrix[R][C];                                                 		 //the position matrix
+	void refresh(b_list&, b_list&, e_list&, player&, int &score, boss& boss1,w_vec &walls, b_list & powerups,r_list&);  	 //empties, uploads, kills, empties again, uploads again matrix
+	void print();                                                   		  //prints the position matrix
+	void clear();                                                    		 //fills matrix with 0's
+	void destroy(int X, int Y, b_list & bullets, b_list& bombs, e_list& enemies, b_list & powerups,r_list&);     //destroys bullets, bombs and enemies in (X,Y)
+	
+	private:	                                                   
+	void upload(b_list & bullets, b_list& bombs, e_list& enemies, player& player1, boss& boss1,w_vec &walls, b_list & powerups,r_list&);    //fills matrix with objects id's
+	void kill(b_list & bullets, b_list& bombs, e_list& enemies, int &score, boss& spole,w_vec &walls, b_list & powerups, player & player1,r_list&);           //checks where there's something to destroy
+	
+
+};
+
+#endif
+

+ 17 - 0
bullet.cpp

@@ -0,0 +1,17 @@
+#include "bullet.hpp"
+
+void bullet::next_pos()
+{
+	switch(id){
+		case 2:
+			y--;
+			break;
+		case 8:
+		case 64:
+		case 128:
+		case 512:
+			y++;
+			break;
+	}
+			
+}

+ 19 - 0
bullet.hpp

@@ -0,0 +1,19 @@
+#ifndef _bullet_
+#define _bullet_
+
+#include "game_object.hpp"
+
+class bullet : public game_object
+{
+	
+	public:
+	bullet(int X,int Y,int ID) : game_object(X,Y,ID) {}  //constructor
+	~bullet() {}
+	
+	void next_pos();            //evaluates next position checking bullet's id (laser or bomb) 
+	
+	bool operator==(bullet& other) { if(other.x==x && other.y==y && other.id==id) return true; else return false; }
+		
+};
+
+#endif

+ 115 - 0
checkboss.sh

@@ -0,0 +1,115 @@
+#!/bin/bash
+
+# This script checks all arguments (or if no arguments are given, all files named *.dat in the directory),
+# with the exception of records.dat,
+# and prompts for cutting lines and characters in excess
+# i.e. cuts lines after the $MAX_LINES-th line and characters after the $MAX_CHARS-th character in each line
+# The script also adds as many blank spaces as needed to even the character count on each line
+# i.e. in the and each line will have $LONGEST_LINE characters in total
+# Old boss.dat file is copied to boss.dat.old to prevent data loss. I'm aware this is a coward's walkaround
+# to the fact this script has issues.
+
+# KNOWN BUGS:
+# - there is no return value checking from the functions called
+# - first bug implies that boss.dat file could be substituted with an empty file, or worse
+
+# Please report any bugs or suggestions to me .D
+
+#wc -L is the length of the longest line
+#wc -m is the character count for the file
+#wc -l is the line count for the file
+
+MAX_CHARS=10
+MAX_LINES=10
+FILES=""
+
+if [ $# -eq 1 -a $1 == "-h" ]; then echo Usage: $0 \<bossname.dat\>.; exit 1; fi
+
+if [ $# -gt 0 ]; then
+	#check that file exists
+	for k in $@; do
+		if [ ! -e $k -a ! $k.dat ]; then
+			echo $k does not exist!
+			echo ignoring argument
+			continue
+		else
+			#check that file has .dat extension
+			if [[ "$k" =~ dat$  ]]; then
+				FILES="$FILES $k"
+			else
+				if [[ "Sk.dat" =~ dat$ ]]; then
+					echo File $k is not a .dat, but a file named $k.dat exists. Did you mean that file? \(Y/N\)
+					read ans
+					if [ $ans != "y" -a $ans != "Y" ]; then exit 1 
+					else
+						FILES="$FILES $k.dat"
+						continue
+					fi
+				else
+					echo $k does not look like a .dat file
+					echo ignoring argument
+					continue
+				fi
+			fi
+		fi
+	done
+else
+	FILES=`ls *.dat 2> /dev/null`
+fi
+
+echo $FILES > args.tmp
+
+#FOR EACH boss.dat FILE
+for i in `cat args.tmp`; do
+	if [ $i == "records.dat" -o $i == "notes.dat" ]; then continue; fi
+	
+	#MAKE A BACKUP COPY	
+	cp $i $i.old
+
+	#CUT LINES IN EXCESS
+	N_LINES=`wc -l $i | cut -f1 -d' '`
+	if [ $N_LINES -gt $MAX_LINES ]; then
+		echo file $i has too many lines \($N_LINES\): cut lines in excess? Y\\N
+		read ans
+		while [ $ans != 'y' -a $ans != 'Y' -a $ans != 'n' -a $ans != 'N' ]; do
+			echo cut lines in excess? Y\\N
+			read ans
+		done
+		if [ $ans == 'y' -o $ans == 'Y' ]; then
+			head -$MAX_LINES $i > output.tmp
+			mv output.tmp $i
+			N_LINES=`wc -l $i | cut -f1 -d' '`
+			echo file has now $N_LINES lines
+		fi
+		echo
+	fi
+	
+	#CUT CHARACTERS IN EXCESS
+	LONGEST_LINE=`wc -L $i | cut -f1 -d' '`
+	if [ $LONGEST_LINE -gt $MAX_CHARS ]; then
+		echo file $i has at least one line that is longer than permitted. max length is $MAX_CHARS
+		echo cut characters in excess? Y\\N
+		read ans
+		while [ $ans != 'y' -a $ans != 'Y' -a $ans != 'n' -a $ans != 'N' ]; do  
+                        echo cut lines in excess? Y\\N
+                        read ans
+                done
+		if [ $ans == 'y' -o $ans == 'Y' ]; then
+			cat $i | cut -c1-$MAX_CHARS > output.tmp2
+			mv output.tmp2 $i
+			LONGEST_LINE=`wc -L $i | cut -f1 -d' '`
+			echo longest line has now $LONGEST_LINE characters 
+		fi
+		echo
+	fi
+
+	#ADD BLANK SPACES AT THE END OF LINES
+	for j in `seq 1 $MAX_CHARS`; do
+		sed 's/.*/& /' $i > output.tmp3
+		mv output.tmp3 $i
+	done
+	cat $i | cut -c1-$LONGEST_LINE > output.tmp4
+	mv output.tmp4 $i
+done
+
+rm args.tmp

+ 1 - 0
dati.dat

@@ -0,0 +1 @@
+lkaid landed on the strange ground of the Void Planet. It was quite an exotic panorama: blue grass and pink-leaved trees aside, the whole planet seemed to be constantly experiencing a

+ 94 - 0
definitions.hpp

@@ -0,0 +1,94 @@
+#ifndef _definitions_
+#define _definitions_
+
+//MAIN LIBRARIES INCLUDES
+#include <cstdlib>
+#include <ctime>
+#include <fstream>
+#include <sstream>
+#include <algorithm>
+#include <iostream>
+#include <iomanip>
+#include <list>
+#include <vector>
+#include <cmath>
+#include <unistd.h>
+//#include <pthread.h>	//for sounds
+#include <sys/stat.h>	//for making directories
+#include <ncurses.h>	//for graphics
+#include <mutex>
+
+
+//GAME BOX DIMENSIONS
+#define R 30	//rows (Y)
+#define C 60	//columns (X)
+
+//GAME DEFINES
+#define AVERAGE_DROP 2
+#define POWERUP_RATIO 2
+#define ROCKET_RATIO 3
+#define MAX_WEAPONCLASS 5
+#define MAX_WEAPONCLASSRKT 5
+#define MAX_LENGTH 20
+#define CMD_NUM 9
+#ifdef R
+#define MAX_WIDTH R
+#endif
+#ifdef C
+#define MAX_HEIGHT C
+#endif
+#define GLOBAL_DIR "/home/150/invaders/"
+#define RECORD_DIR "/.invaders/"
+#define RECORD_FILE "records.dat"
+#define RECORD_FILE_BOSSRUSH "records_bossrush.dat"
+#define CHEAT_CODE "pinkie"
+#define BOSS_FILE1 "spoletini"
+#define BOSS_FILE2 "palombo"
+#define BOSS_FILE3 "maderna"
+#define BOSS_FILE4 "maero"
+#define BOSS_FILE5 "big_alienboss"
+#define PLAYER_SPRITE '='
+#define ENEMY_SPRITE '#'
+#define BULLET_SPRITE '|'
+#define BOMB_SPRITE 'o'
+#define POWERUP1_SPRITE '+'
+#define POWERUP2_SPRITE '-'
+#define POWERUP3_SPRITE 'X'
+#define WALL_SPRITE '@'
+#define ROCKET_SPRITE '^'
+
+//THREAD DEFINES
+//#define THREADS_NUM 5
+
+//COLORS
+#define red "\033[31m" 
+#define crimson "\033[1;31m"
+#define magenta "\033[35m" 
+#define violet "\033[1;35m"  
+#define green "\033[32m" 
+#define lightgreen "\033[1;32m" 
+#define blue "\033[34m" 
+#define lightblue "\033[1;34m" 
+#define none "\033[0m" 
+#define yellow "\033[33m" 
+#define orange "\033[1;33m"
+#define cyan "\033[36m"
+#define azure "\033[1;36m"
+#define grey "\e[1;30m"
+#define backred "\033[41m" 
+#define backcyan "\033[46m"
+#define backgreen "\033[1;42m" 
+
+static int ENEMY_NUM=1;
+static int WALLS_NUM;
+
+extern std::mutex m_player;
+extern std::mutex m_enemies;
+extern std::mutex m_bombs;
+extern std::mutex m_bullets;
+extern std::mutex m_rockets;
+extern std::mutex m_pow;
+extern std::mutex m_boss;
+extern std::mutex m_walls;
+
+#endif

+ 77 - 0
definitions.hpp.bu

@@ -0,0 +1,77 @@
+#ifndef _definitions_
+#define _definitions_
+
+//MAIN LIBRARIES INCLUDES
+#include <cstdlib>
+#include <ctime>
+#include <fstream>
+#include <sstream>
+#include <algorithm>
+#include <iostream>
+#include <iomanip>
+#include <list>
+#include <vector>
+#include <cmath>
+//#include <unistd.h>
+#include <pthread.h>
+#include <ncurses.h>
+
+//GAME BOX DIMENSIONS
+#define R 30	//rows (Y)
+#define C 60	//columns (X)
+
+//GAME DEFINES
+#define AVERAGE_DROP 2
+#define POWERUP_RATIO 2
+#define ROCKET_RATIO 3
+#define MAX_WEAPONCLASS 5
+#define MAX_WEAPONCLASSRKT 5
+#define MAX_LENGTH 20
+#ifdef R
+#define MAX_WIDTH R
+#endif
+#ifdef C
+#define MAX_HEIGHT C
+#endif
+#define CHEAT_CODE "pinkie"
+#define BOSS_FILE1 "myboss"
+#define BOSS_FILE2 "palombo"
+#define BOSS_FILE3 "maderna"
+#define BOSS_FILE4 "maero"
+#define BOSS_FILE5 "big_alienboss"
+#define PLAYER_SPRITE '='
+#define ENEMY_SPRITE '#'
+#define BULLET_SPRITE '|'
+#define BOMB_SPRITE 'o'
+#define POWERUP1_SPRITE '+'
+#define POWERUP2_SPRITE '-'
+#define POWERUP3_SPRITE 'X'
+#define WALL_SPRITE '@'
+#define ROCKET_SPRITE '^'
+
+//THREAD DEFINES
+#define THREADS_NUM 5
+
+//COLORS
+#define red "\033[31m" 
+#define crimson "\033[1;31m"
+#define magenta "\033[35m" 
+#define violet "\033[1;35m"  
+#define green "\033[32m" 
+#define lightgreen "\033[1;32m" 
+#define blue "\033[34m" 
+#define lightblue "\033[1;34m" 
+#define none "\033[0m" 
+#define yellow "\033[33m" 
+#define orange "\033[1;33m"
+#define cyan "\033[36m"
+#define azure "\033[1;36m"
+#define grey "\e[1;30m"
+#define backred "\033[41m" 
+#define backcyan "\033[46m"
+#define backgreen "\033[1;42m" 
+
+static int ENEMY_NUM=40;
+static int WALLS_NUM;
+	
+#endif

+ 38 - 0
enemy.cpp

@@ -0,0 +1,38 @@
+#include "enemy.hpp"
+
+
+enemy::enemy() : game_object() { id=4; alive=true; direction=0; }
+
+enemy::enemy(int X,int Y) : game_object(X,Y,4) { alive=true; direction=0; }  
+
+
+void enemy::next_pos(){
+
+	if( (direction==0 && x==C-1) || (direction==1 && x==0) )
+		direction=2;
+
+	switch (direction){			//assegno a direction un valore 0,1,2
+		case 0:				//0 significa che si sta muovendo verso destra
+			x++;
+			break;
+		case 1:				//1 verso sinistra
+			x--;
+			break;
+		case 2:				//2 verso il basso (quando incontra la parete).
+			y++;
+			break;
+	}
+
+	if(direction==2)
+	{
+		if(x==0) direction=0;
+		else direction=1;
+	}
+	
+}
+
+void enemy::shoot(std::list<bullet> & bombs){	      //random bomb-dropping	
+		bullet new_bomb(x,y+1,8);
+		bombs.push_back(new_bomb);
+}
+

+ 23 - 0
enemy.hpp

@@ -0,0 +1,23 @@
+#ifndef _enemy_
+#define _enemy_
+
+#include "game_object.hpp"
+#include "bullet.hpp"
+#include "definitions.hpp"
+
+class enemy : public game_object
+{	
+	public:
+	enemy();                    //costruttori:
+	enemy(int X,int Y);		    //id viene automaticamente settato a 4, direction a 0, alive a true
+	~enemy(){}
+	
+	void next_pos();
+	void shoot(std::list<bullet> &);  //genera un nuovo proiettile 
+	
+	bool alive;			         //0: morto, 1: vivo
+	int direction; 	       	//0: si sta muovendo a dx, 1: a sx, 2: verso il basso
+	
+};
+
+#endif

+ 2020 - 0
functions.cpp

@@ -0,0 +1,2020 @@
+#include "functions.hpp"
+#include "definitions.hpp"
+using std::cout;
+using std::cin;
+using std::endl;
+using std::min;
+
+extern std::mutex m_bullets;
+
+//========RECORD'S METHODS===========	
+	
+void record::print()
+{
+	printw("%s\t%i\n",nick.c_str(),score);
+	
+}
+
+void record::printwin(WINDOW* win)
+{
+	wprintw(win,"%s.......%i",nick.c_str(),score);
+	
+}
+
+void record::print(std::ofstream& recordfile)
+{
+	if(!recordfile.is_open())
+	{
+		printw("error: record file is not open ");
+		return;
+	}
+	recordfile << std::setw(6) << std::left << nick << "	" << score << endl;	
+}
+
+	
+
+
+
+
+//=======INDIPENDENT FUNCTIONS=========
+
+
+void print_title()			//CAPITAL LETTERS TITLE!
+{
+	attron(COLOR_PAIR(5));
+	mvprintw(0,0,"    __    _   _   _   _  _                 _      _  _   _      __");
+	mvprintw(1,0,"__//     |_  |_| |_| |  |_    | |\\ | |  | |_| |\\ |_ |_| |_        \\\\__");
+	mvprintw(2,0,"  \\\\__    _| |   | | |_ |_    | | \\|  \\/  | | |/ |_ |\\   _|     __//");
+	attron(COLOR_PAIR(0));
+}
+
+void print_catchphrase(std::string phrase){		
+	static int head=60;
+	static int tail=60;
+
+	phrase.resize(59,' ');
+		
+	attron(COLOR_PAIR(4));
+	if(head<1){
+		head=60;
+	}
+	if(head<tail){
+		move(3,0);
+		clrtoeol();
+		mvprintw(3,head,phrase.c_str());
+		tail=(head+phrase.size()<60?head+phrase.size():60);
+	}
+	else{
+		move(3,0);
+		clrtoeol();
+		for(unsigned int i=0;i<abs(phrase.size()-(60-head));i++)
+			mvaddch(3,i,phrase[60-head+i]);
+		for(unsigned int i=head;i<60;i++)
+			mvaddch(3,i,phrase[i-head]);
+		tail=(phrase.size()-(60-head)>0?phrase.size()-(60-head):60);
+	}
+	head--;
+	
+	
+	
+}
+	
+std::string choose_phrase(){
+	std::string phr;
+	int r=(int)(23*(double)rand()/RAND_MAX);
+	switch(r){
+		case 0:
+			phr="Now with cheats!";
+			break;
+		case 1:
+			phr="20 percent cooler than your 3D-graphics games!";
+			break;
+		case 2:
+			phr="NCurses rulez!";
+			break;
+		case 3:
+			phr="References to people and events are purely random.";
+			break;
+		case 4:
+			phr=">>> Crush <<< Kill >>> Destroy <<< SWAG >>>";
+			break;
+		case 5:
+			phr="Also try Apocalypse 2.0!";
+			break;
+		case 6:
+			phr=")]=>---- #   ASCII IS ART!!!  # ----<=[(";
+			break;
+		case 7:
+			phr="Still a better program than Isgro's ones...";
+			break;
+		case 8:
+			phr="<< Oh, sul serio, minchia raga, ne'? >>";
+			break;
+		case 9:
+			phr="Cool game, bro, but needs more ponies.";
+			break;
+		case 10:
+			phr="Hit R!!!";
+			break;
+		case 11:
+			phr="Konami Code is still fashion.";
+			break;
+		case 12:
+			phr="Almost completely debugged!";
+			break;
+		case 13:
+			phr="(((( Kill them with WUBZ! ))))";
+			break;
+		case 14:
+			phr="choose_phrase() is best function.";
+			break;
+		case 15:
+			phr="zsh: segmentation fault (core dumped)  invaders";
+			break;
+		case 16:
+			phr="Aliens! Aliens everywhere!";
+			break;
+		case 17:
+			phr="Breaks the fourth wall!       Breaks the fourth wall!";
+			break;
+		case 18:
+			phr="Them customizable controls!!!";
+			break;
+		case 19:
+			phr=">~~~~~~~~~~~~~~~~~~~~~< You shall be assimilated into Linux.";
+			break;
+		case 20:
+			phr="Did you try inv_bossrush?";
+			break;
+		case 21:
+			phr="Keep calm and FUCKIN' KILL ALIENS.";
+			break;
+		case 22:
+			phr="Read the fucking `man` page!!!";
+			break;
+	}
+
+	return phr;
+}
+
+void print_info(){
+
+	WINDOW *info;
+	info=newwin(20,80,0,0);
+	box(info,ACS_VLINE,ACS_HLINE);
+	mvwprintw(info,0,1,"Welcome to Space Invaders!");
+	wattron(info,COLOR_PAIR(1));
+	mvwprintw(info,2,1,"About the Game:");
+	wattron(info,COLOR_PAIR(6));
+	mvwprintw(info,3,1,"This is a Terminal-playable game where you control a moving cannon base");
+	mvwprintw(info,4,1,"(");
+	wattron(info,COLOR_PAIR(1));
+	wprintw(info,"========");
+	wattron(info,COLOR_PAIR(6));
+	wprintw(info,") with the aim to destroy all the enemy Space Invaders");
+	mvwprintw(info,5,1,"(");
+	wattron(info,COLOR_PAIR(2));
+	wprintw(info,"#");
+	wattron(info,COLOR_PAIR(6));
+	wprintw(info,") assaulting the Earth. After killing all the Space Invaders, you shall face");
+	mvwprintw(info,6,1,"the Big Alien Boss, the most powerful of all the alien enemies.");
+	mvwprintw(info,7,1,"During the game, mind the Powerups (");
+	wattron(info,COLOR_PAIR(3));
+	wprintw(info,"+");
+	wattron(info,COLOR_PAIR(6));
+	wprintw(info,",");
+	wattron(info,COLOR_PAIR(1));
+	wprintw(info,"-");
+	wattron(info,COLOR_PAIR(6));
+	wprintw(info,",");
+	wattron(info,COLOR_PAIR(4));
+	wprintw(info,"X");
+	wattron(info,COLOR_PAIR(6));
+	wprintw(info,") that will increase");
+	mvwprintw(info,8,1,"your shooting power if you manage to get them.");
+	wattron(info,COLOR_PAIR(1));
+	mvwprintw(info,10,1,"Default Controls: ");
+	wattron(info,COLOR_PAIR(5));
+	mvwprintw(info,11,1,"<- ");
+	wattron(info,COLOR_PAIR(6));
+	wprintw(info," A or Left Arrow");
+	wattron(info,COLOR_PAIR(5));
+	mvwprintw(info,12,1,"-> ");
+	wattron(info,COLOR_PAIR(6));
+	wprintw(info," D or Right Arrow");
+	wattron(info,COLOR_PAIR(5));
+	mvwprintw(info,13,1,"shoot ");
+	wattron(info,COLOR_PAIR(6));
+	wprintw(info," spacebar");
+	wattron(info,COLOR_PAIR(3));
+	mvwprintw(info,15,10,"Game developed by Giacomo Parolini & Enrico Guiraud (v.4.4)");
+	wattron(info,COLOR_PAIR(6));
+	mvwprintw(info,17,14,"Click any key to return to the Start Menu");
+	wattron(info,COLOR_PAIR(0));
+	
+	wrefresh(info);
+	timeout(-1);
+	if(getch()!=ERR){
+		delwin(info);
+		erase();
+		refresh();
+	}
+}
+
+
+int choose_level(double& shootr, int& refresh_t, boss& boss1, char& level,int* commands)	//returns ENEMY_NUM
+{
+	std::string phrase;
+	phrase=choose_phrase();
+	
+	do{
+		print_title();
+		print_catchphrase(phrase);
+		attron(COLOR_PAIR(1));
+		mvprintw(5,0,"Choose difficulty level:");
+		attron(COLOR_PAIR(1));
+		mvprintw(6,0,"1- Easy");
+		attron(COLOR_PAIR(3));
+		mvprintw(7,0,"2- Medium");
+		attron(COLOR_PAIR(2));
+		mvprintw(8,0,"3- Hard");
+		attron(COLOR_PAIR(4));
+		mvprintw(9,0,"4- Impossible");
+		attron(COLOR_PAIR(5));
+		mvprintw(10,0,"i- Info");
+		attron(COLOR_PAIR(6));
+		mvprintw(11,0,"h- Highscores");
+		attron(COLOR_PAIR(1));
+		mvprintw(12,0,"c- Commands");
+		attron(COLOR_PAIR(2));
+		mvprintw(13,0,"q- Quit");
+		
+		refresh();
+
+		timeout(80);
+		
+		level=tolower(getch());
+	
+		if(!(atoi(&level)==1 || atoi(&level)==2 || atoi(&level)==3 || atoi(&level)==4 || level=='i' || level=='h' || level=='r' || level =='q') && level!=ERR){
+			attron(COLOR_PAIR(2));
+			mvprintw(14,0,"Bad input. Please choose a number within 1 and 4.");
+			attron(COLOR_PAIR(0));	
+		}
+		
+		if(level=='i')
+			print_info();
+		
+		if(level=='h')
+			print_scores();
+
+		if(level=='r')
+			phrase=choose_phrase();
+			
+		if(level=='c')
+			change_commands(commands);
+		
+		if(level=='q'){
+			endwin();
+			cout<<lightgreen<<"Game exited correctly."<<none<<endl;
+			exit(1);
+		}
+		
+	}while(!(atoi(&level)==1 || atoi(&level)==2 || atoi(&level)==3 || atoi(&level)==4));
+	
+	refresh_t=0;
+	
+	create_folder(0);
+	
+	switch(atoi(&level))        //setting game parameters
+	{
+		case 1:
+		{
+			shootr = 0.006;
+			refresh_t = (int)(0.09*1E3);
+			boss bosslvl1(1,1,100,9,6,BOSS_FILE1);
+			boss1 = bosslvl1;
+			std::string bossname=getenv("HOME");
+			bossname=bossname+RECORD_DIR+BOSS_FILE1+".dat";
+			boss1.loadpicture(bossname.c_str());
+			ENEMY_NUM=30;
+			return ENEMY_NUM;
+		}
+		case 2:
+		{
+			shootr = 0.009;
+			refresh_t = (int)(0.09*1E3);
+			boss bosslvl2(1,1,200,11,5,BOSS_FILE2);
+			boss1 = bosslvl2;
+			std::string bossname=getenv("HOME");
+			bossname=bossname+RECORD_DIR+BOSS_FILE2+".dat";
+			boss1.loadpicture(bossname.c_str());
+			ENEMY_NUM=40;
+			return ENEMY_NUM;
+		}
+		case 3:
+		{
+			shootr = 0.015;
+			refresh_t = (int)(0.08*1E3);
+			boss bosslvl3(1,1,300,9,6,BOSS_FILE3);
+			boss1 = bosslvl3;
+			std::string bossname=getenv("HOME");
+			bossname=bossname+RECORD_DIR+BOSS_FILE3+".dat";
+			boss1.loadpicture(bossname.c_str());
+			ENEMY_NUM=45;
+			return ENEMY_NUM;
+		}
+		case 4:
+		{
+			shootr = 0.020;
+			refresh_t = (int)(0.07*1E3);
+			boss bosslvl4(1,1,400,11,6,BOSS_FILE4);
+			boss1 = bosslvl4;
+			std::string bossname=getenv("HOME");
+			bossname=bossname+RECORD_DIR+BOSS_FILE4+".dat";
+			boss1.loadpicture(bossname.c_str());
+			ENEMY_NUM=50;
+			return ENEMY_NUM;
+		}
+	}
+
+	return 0;
+	
+}
+
+void change_commands(int* commands){
+	WINDOW *change;
+	int cmd;
+	int line=0;
+	std::string chcommands[CMD_NUM];
+	
+	std::string name[CMD_NUM]={"Key Left","Key Right","Key Up","Key Down","Pause","Shoot 1","Shoot 2","Mute/Unmute","Quit"};
+	change=newwin(CMD_NUM+10,20,0,0);
+	keypad(change,true);
+	box(change,ACS_VLINE,ACS_HLINE);
+	wattron(change,COLOR_PAIR(5));
+	mvwprintw(change,1,2,"CHANGE CONTROLS");
+	mvwprintw(change,3,2,"(X) to exit");
+	
+	do{
+
+		for(int i=0;i<CMD_NUM;i++){
+			if(commands[i]==' ') chcommands[i]="Barra sp.";
+			else chcommands[i]=commands[i];
+			if(i==line) wattron(change,COLOR_PAIR(9));
+			mvwprintw(change,i+5,1,"%s: %s",name[i].c_str(),chcommands[i].c_str());
+			wattron(change,COLOR_PAIR(1));
+		}
+		timeout(0);
+		cmd=wgetch(change);
+		
+		switch(cmd){
+			case KEY_DOWN:
+			case 's':	
+				if(line<CMD_NUM-1) line++;
+				break;
+			case KEY_UP:
+			case 'w':
+				if(line>0) line--;
+				break;
+			case 'X':
+				delwin(change);
+				erase();
+				refresh();
+				return;
+			case '\n':
+				wattron(change,COLOR_PAIR(2));
+				mvwprintw(change,line+5,1,"%s: %s",name[line].c_str(),chcommands[line].c_str());
+				wrefresh(change);
+				timeout(-1);
+				cmd=wgetch(change);
+				commands[line]=tolower(cmd);
+				wmove(change,line+5,0);
+				wclrtoeol(change);
+				box(change,ACS_VLINE,ACS_HLINE);
+				wattron(change,COLOR_PAIR(1));
+				break;
+		}
+		
+		wrefresh(change);
+		
+	}while(cmd!='X');	
+	
+	delwin(change);
+	erase();
+	refresh();
+	return;	
+	
+}
+	
+void load_enemies(e_list& enemies,int enemy_num)
+{
+	for(int i=0; i<enemy_num; ++i)     				//loading enemies
+	{
+		static int c=0, r=0;
+		if(c>C-1)
+		{
+			c=0;
+			r++;
+		 	if(r>R-2) break;
+		}
+		
+		enemy newenemy(c++,r);
+		if(newenemy.y%2!=0) newenemy.direction=1;
+		enemies.push_back(newenemy);
+	}
+}
+		
+bool playagain(WINDOW* replay)     
+{
+	char answer;
+	
+	do
+	{
+		wattron(replay,COLOR_PAIR(2));
+		mvwprintw(replay,1,4,"Play again? [y/n] ");
+		answer=tolower(wgetch(replay));
+		if(answer=='y')
+			return true;
+		if(answer=='n')
+			return false;
+	}while(answer!='y'&&answer!='n');
+	
+	return false;	//just to get rid of the compiler's warning
+}
+
+bool gameover(player& _player,b_list& bombs)		//Checks if a bomb/enemy/boss hit the player.
+{
+	for(b_list::iterator it=bombs.begin(); it!=bombs.end(); ++it)
+		if((it->x>=_player.x && it->x<_player.x+_player.length) && (it->y==_player.y) && !_player.godmode)
+			return true;
+				
+	return false;
+}
+
+
+void reset(player& _player, e_list &enemies, boss& boss1, b_list& bullets, b_list& bombs, w_vec& walls, b_list& powerups, r_list& rockets, char level,int& chflag)
+{
+	
+	_player.x=C/2;				//resetting initial position and stats of player1
+	_player.y=R-1;
+	_player.weaponclass=0;
+	_player.length=8;
+	_player.rocketlauncher=FALSE;
+	
+	int c=0, r=0;
+	e_list::const_iterator e_end = enemies.end();
+	for(e_list::iterator it = enemies.begin(); it!=e_end; ++it)	//resetting all the enemies
+	{	
+		if(c==C) 
+		{
+			c=0;
+			r++;
+		}
+		it->alive = true; 
+		it->x=c++;
+		it->y=r;
+		if(it->y%2==0) it->direction=0;
+		else it->direction=1;
+	}
+	
+	boss1.alive = false;
+	
+	bullets.clear();			//destroying all bullets/bombs/etc
+	bombs.clear();
+	powerups.clear();
+	rockets.clear();
+	chflag=0;
+	
+	WALLS_NUM=2;				//resetting walls
+	
+	if(atoi(&level)==1) WALLS_NUM=3;
+	
+	walls.resize(WALLS_NUM);
+
+	for(int i=0;i<walls.size();i++)
+		walls[i].create((i+1)*(C/(3*walls.size()+1))+i*(2*C/(3*walls.size()+1)),2*R/3,(int)min(6,2*C/(3*(int)(walls.size())+1)),2,5);
+	
+}
+	
+
+bool enemyalive(e_list &enemies)
+{
+	bool isalive = false;
+	e_list::const_iterator end = enemies.end();
+	
+	for(e_list::iterator it=enemies.begin(); it!=end; ++it)
+		if(it->alive==true)
+		{
+			isalive = true;
+			break;
+		}
+	
+	return isalive;
+}
+
+
+bool operator<(record record1, record record2)
+{	
+		if(record1.score<record2.score) return true;
+		else return false;
+}
+
+void pause_game(int& chflag){
+	WINDOW *pause;
+	char c;
+	std::string cheat;
+	char Cheat[7];
+	pause=newwin(5,17,15,15);
+	box(pause,ACS_VLINE,ACS_HLINE);
+	wattron(pause,COLOR_PAIR(5));
+	mvwprintw(pause,1,3,"GAME PAUSED");
+	mvwprintw(pause,3,2,"(P) to resume");
+	do{	
+		c=tolower(wgetch(pause));
+		if(c=='c'){			//cheats!
+			nocbreak();
+			wmove(pause,2,5);
+			echo();
+			wattron(pause,COLOR_PAIR(4));
+			wscanw(pause,"%s",Cheat);
+			cbreak();
+			noecho();
+			if(std::strcmp(Cheat,CHEAT_CODE)==0){
+				if(chflag==0)
+					chflag=1;
+				if(chflag==2)
+					chflag=3;
+				waddch(pause,'\a');
+			}
+			delwin(pause);
+			erase();
+			refresh();
+			return;
+		}
+		else if(c=='p'){
+			delwin(pause);
+			erase();
+			refresh();
+			return;
+		}
+	}while(c!='c' && c!='p');
+}
+
+
+void write_score(WINDOW* Score,int score){
+	wattron(Score,COLOR_PAIR(6));
+	mvwprintw(Score,1,2,"SCORE");
+	wattron(Score,COLOR_PAIR(1));
+	mvwprintw(Score,2,2,"%i",score);
+}
+
+void write_bosshp(WINDOW* BossHP,int hp,int hpmax,std::string name){
+	wattron(BossHP,COLOR_PAIR(3));
+	mvwprintw(BossHP,0,1,"%s",name.c_str());		//writes boss's name
+	
+	wattron(BossHP,COLOR_PAIR(8));
+	int i=0;
+	for(i=0;i<(int)(15*(double)(hp)/hpmax);i++) mvwaddch(BossHP,1,i,' ');	//draws green spaces
+	i++;
+	
+	wattron(BossHP,COLOR_PAIR(7));
+	for(;i<15;i++) mvwaddch(BossHP,1,i,' ');		//draws red spaces (total spaces are 15)
+	
+	if((double)hp/hpmax>.5)
+		wattron(BossHP,COLOR_PAIR(1));
+	else if((double)hp/hpmax>.25)
+		wattron(BossHP,COLOR_PAIR(3));
+	else
+		wattron(BossHP,COLOR_PAIR(2));
+		
+	wmove(BossHP,2,0);
+		wdeleteln(BossHP);
+		mvwprintw(BossHP,2,0,"%i / %i HP",hp,hpmax);	//writes boss's hp / hpmax (color depends on hp/hpmax ratio)
+}
+
+
+
+void Victory(std::string name,int score,char level,int chflag){
+	score+=1500*atoi(&level);
+	WINDOW *victory;
+
+	victory=newwin(19,32,7,17);
+	box(victory,ACS_VLINE,ACS_HLINE);
+	wattron(victory,COLOR_PAIR(1));
+	mvwprintw(victory,2,4,"YOU DEFEATED %s!",name.c_str());
+	wattron(victory,COLOR_PAIR(3));
+	mvwprintw(victory,4,5,"+ %i pts!",atoi(&level)*1500);
+	wattron(victory,COLOR_PAIR(1));
+	mvwprintw(victory,4,5,"YOU WON!");
+	wattron(victory,COLOR_PAIR(3));
+	mvwprintw(victory,4,5,"Your score is: %i",score);
+	wrefresh(victory);
+	
+	if(chflag==0)
+		refreshrecords(score,victory);
+	else{
+		wattron(victory,COLOR_PAIR(4));
+		mvwprintw(victory,7,3,"I think you used cheats...");
+	}
+	
+	wrefresh(victory);
+	
+	delwin(victory);
+
+}
+
+void Defeat(int score){
+	WINDOW *defeat;
+
+	defeat=newwin(10,32,7,17);
+	box(defeat,ACS_VLINE,ACS_HLINE);
+	wattron(defeat,COLOR_PAIR(2));
+	mvwprintw(defeat,3,10,"GAME OVER!");
+	wattron(defeat,COLOR_PAIR(3));
+	mvwprintw(defeat,6,4,"Your score was: %i pts!",score);
+			
+	wrefresh(defeat);
+	delwin(defeat);
+}
+
+
+void get_SpecialMode(int c,int& chflag,boss& boss1,e_list& enemies,b_list& bullets,b_list& bombs,b_list& powerups,r_list& rockets){
+	if(get_KonamiCode(c)){
+		activate_combo(boss1,enemies,bullets,bombs,powerups,rockets);
+		if(chflag==0)
+			chflag=2;
+		if(chflag==1)
+			chflag=3;
+	}
+}
+	
+bool get_KonamiCode(int c){	//UP,UP,DOWN,DOWN,LEFT,RIGHT,LEFT,RIGHT,B,A
+	static int combo=0;
+	switch(combo){
+		case 0:
+		case 1:
+			if(c==KEY_UP) combo++;
+			else if(c!=ERR) combo=0;
+			break;
+		case 2:
+		case 3:
+			if(c==KEY_DOWN) combo++;
+			else if(c!=ERR) combo=0;
+			break;
+		case 4:
+		case 6:
+			if(c==KEY_LEFT) combo++;
+			else if(c!=ERR) combo=0;
+			break;
+		case 5:
+		case 7:
+			if(c==KEY_RIGHT) combo++;
+			else if(c!=ERR) combo=0;
+			break;
+		case 8:
+			if(c=='b') combo++;
+			else if(c!=ERR) combo=0;
+			break;
+		case 9:
+			if(c=='a'){
+				return true;
+			}
+			else if(c!=ERR) combo=0;
+			break;
+	}
+	
+	return false;
+}
+
+void get_cheat(char command,player& player1,e_list& enemies,double& shootrate){
+	switch(command){
+		case '+':
+			if(player1.weaponclass<5) player1.weaponclass++;        //increase weaponclass
+			break;
+		case '\\':
+			if(player1.weaponclass>1) player1.weaponclass--;        //decrease weaponclass
+			break;
+		case '-':
+			if(player1.length>2){                                   //decrease size
+				mvaddch(player1.y,player1.x+player1.length-1,' ');
+				player1.length--;
+			}
+			break;
+		case '*':
+			if(player1.length<MAX_LENGTH) player1.length++;         //increase size
+			break;
+		case 'n':                                                       //nuke enemies
+			for(e_list::iterator it=enemies.begin();it!=enemies.end();it++){
+				it->alive=false;
+				mvaddch(it->y,it->x,' ');
+			}
+			break;
+		case 'r':               //activate rocketlauncher and increase weaponclassrkt
+			if(!(player1.rocketlauncher)) player1.rocketlauncher=TRUE;
+			else if(player1.weaponclassrkt<MAX_WEAPONCLASS) player1.weaponclassrkt++;
+			break;
+		case 'e':               //decrease weaponclassrkt and deactivate rocketlauncher
+			if(player1.weaponclassrkt>0) player1.weaponclassrkt--;
+			else player1.rocketlauncher=FALSE;
+			break;
+		case 'u':                                               //trigger uber mode
+			player1.rocketlauncher=TRUE;
+			player1.weaponclass=MAX_WEAPONCLASS;
+			player1.weaponclassrkt=MAX_WEAPONCLASSRKT;
+			player1.length=MAX_LENGTH;
+			break;
+		case 'g':                                       //trigger/untrigger godmode
+			player1.godmode=!player1.godmode;
+			break;
+		case 'f':                               //freeze: enemies won't shoot.
+			shootrate=0;
+			break;
+	}
+}
+
+void activate_combo(boss& boss1,e_list& enemies,b_list& bullets,b_list& bombs,b_list& powerups,r_list& rockets){		//if the player performs the Konami Code, the normal boss is replaced with BIG_ALIENBOSS
+	boss bossextra(1,1,500,17,5,BOSS_FILE5);
+	boss1 = bossextra;
+	std::string bossname=getenv("HOME");
+	bossname=bossname+RECORD_DIR+BOSS_FILE5+".dat";
+	boss1.loadpicture(bossname.c_str());
+
+	for(int i=0;i<7;){
+		attron(COLOR_PAIR(i++));
+		mvprintw(15,15,"SPECIAL MODE ACTIVATED!!!");
+		refresh();
+		napms(150);
+	}
+	
+	attron(COLOR_PAIR(0));
+	napms(1500);
+	for(e_list::iterator i=enemies.begin();i!=enemies.end();i++)
+		i->alive=false;
+	bullets.clear();
+	bombs.clear();
+	rockets.clear();
+		
+	erase();
+}
+
+//=============BOX'S REPLACEMENT FUNCTIONS============================
+
+void draw(player& player1,b_list& bullets,b_list& bombs,e_list& enemies,w_vec& walls,b_list& powerups,r_list& rockets,boss& boss1, int& refresh_time, bool& keep_drawing,bool& kill_yourself){
+	
+	struct point
+	{
+		point() { x=y=0; }
+		point(int X, int Y) { x=X; y=Y; }
+		int x,y;
+	};
+	
+	std::list<point> bullets_p, enemies_p, bombs_p, powerups_p, rockets_p, walls_p, player_p, boss_p;
+	
+	printw("STARTED");	
+	while(!kill_yourself)
+			if(keep_drawing)
+			{				
+				//REDRAW BULLETS
+				m_bullets.lock();
+				for(auto bullet_p: bullets_p)
+					mvaddch(bullet_p.y,bullet_p.x,' ');
+				bullets_p.clear();
+				
+				attron(COLOR_PAIR(3));
+				for(auto bullet: bullets)
+				{
+					mvaddch(bullet.y,bullet.x,BULLET_SPRITE);
+					bullets_p.push_back(point(bullet.x,bullet.y));
+				}
+				m_bullets.unlock();
+				
+				//REDRAW BOMBS
+				m_bombs.lock();
+				for(auto bomb_p: bombs_p)
+					mvaddch(bomb_p.y,bomb_p.x,' ');
+				bombs_p.clear();
+				
+				attron(COLOR_PAIR(6));
+				for(auto bomb: bombs)
+				{
+				 //if(bomb.y<R)
+					mvaddch(bomb.y,bomb.x,BOMB_SPRITE);
+					bombs_p.push_back(point(bomb.x,bomb.y)); 
+				}
+				m_bombs.unlock();
+				
+				//REDRAW ENEMIES
+				m_enemies.lock();
+				for(auto enemy_p: enemies_p)
+					mvaddch(enemy_p.y,enemy_p.x,' ');
+				enemies_p.clear();
+				
+				attron(COLOR_PAIR(2));
+				for(auto enemy: enemies)
+				{
+					if(enemy.alive==true)
+					{
+						mvaddch(enemy.y,enemy.x,ENEMY_SPRITE);
+						enemies_p.push_back(point(enemy.x,enemy.y));
+					}
+				}
+				m_enemies.unlock();
+				
+				//REDRAW ROCKETS
+				m_rockets.lock();
+				for(auto rocket_p: rockets_p)
+					mvaddch(rocket_p.y,rocket_p.x,' ');
+				rockets_p.clear();
+				
+				attron(COLOR_PAIR(3));
+				for(auto rocket: rockets)
+				{
+					mvaddch(rocket.y,rocket.x,ROCKET_SPRITE);
+					rockets_p.push_back(point(rocket.x,rocket.y));
+				}
+				m_rockets.unlock();
+				
+				
+				//REDRAW POWERUPS
+				m_pow.lock();
+				for(auto powerup_p: powerups_p)
+					mvaddch(powerup_p.y,powerup_p.x,' ');
+				powerups_p.clear();
+				
+				for(auto powerup: powerups){
+					if(powerup.id == 64){
+						attron(COLOR_PAIR(3));
+						mvaddch(powerup.y,powerup.x,POWERUP1_SPRITE);
+					}
+					else if(powerup.id == 128){
+						attron(COLOR_PAIR(1));
+						mvaddch(powerup.y,powerup.x,POWERUP2_SPRITE); 
+					}
+					else{
+						attron(COLOR_PAIR(4));
+						mvaddch(powerup.y,powerup.x,POWERUP3_SPRITE);
+					}
+					powerups_p.push_back(point(powerup.x,powerup.y));
+				}
+				m_pow.unlock();
+				
+				//REDRAW BOSS
+				m_boss.lock();
+				for(auto boss_point: boss_p)
+					mvaddch(boss_point.y,boss_point.x,' ');
+				boss_p.clear();
+				
+				if(boss1.alive)
+					for(int i=boss1.y; i<boss1.y+boss1.height; i++)
+						for(int j=boss1.x; j<boss1.x+boss1.width; j++){
+							if(boss1.health>.5*boss1.healthmax)
+								attron(COLOR_PAIR(5));
+							else if(boss1.health>.25*boss1.healthmax)
+								attron(COLOR_PAIR(3));
+							else
+								attron(COLOR_PAIR(2));
+							mvaddch(i,j,boss1.picture[i-boss1.y][j-boss1.x]);
+							boss_p.push_back(point(j,i));
+						}
+				m_boss.unlock();
+				
+				
+				//REDRAW PLAYER
+				m_player.lock();
+				for(auto play_point: player_p)
+					mvaddch(play_point.y,play_point.x,' ');
+				player_p.clear();
+				
+				if(player1.godmode) attron(COLOR_PAIR(5));
+				else attron(COLOR_PAIR(1));
+				for(int i=player1.x;i<player1.x+player1.length;++i)
+				{
+					mvaddch(player1.y,i,PLAYER_SPRITE);	
+					player_p.push_back(point(i,player1.y));
+				}
+				m_player.unlock();
+				
+				
+				//REDRAW WALLS
+				m_walls.lock();
+				for(auto wall_p: walls_p)
+					mvaddch(wall_p.y,wall_p.x,' ');
+				walls_p.clear();
+				
+				for(int i=0;i<walls.size();i++)
+					for(int k=0;k<walls[i].width;k++)
+						for(int j=0;j<walls[i].height;j++){
+							if(walls[i].health[j][k]==1) attron(COLOR_PAIR(2));
+							else attron(COLOR_PAIR(4));
+							if(walls[i].health[j][k]>0)
+							{
+								mvaddch(j+walls[i].y,k+walls[i].x,WALL_SPRITE);
+								walls_p.push_back(point(k+walls[i].x,j+walls[i].y));
+							}
+						}
+				m_walls.unlock();
+			
+				napms(refresh_time/2);
+			}
+}
+
+
+void drop_powerup(int x,int y,b_list& powerups)
+{
+	if((double)rand()/RAND_MAX<1./POWERUP_RATIO){		//1 powerup out of POWERUP_RATIO is either a "-" (with ID 128 instead of 64) or a "X"
+		if((double)rand()/RAND_MAX<1./ROCKET_RATIO){ 	//1 powerup out of ROCKET_RATIO*POWERUP_RATIO is a "X" (ID 512)
+			powerup newpowerup(x,y,512);	
+			powerups.push_back(newpowerup);
+		}
+		else{
+			powerup newpowerup(x,y,128);		
+			powerups.push_back(newpowerup);
+		}
+	}
+	else{
+		powerup newpowerup(x,y);		//otherwise, it is a "+"
+		powerups.push_back(newpowerup);
+	}		
+}
+
+
+void interactions(player& player1,b_list& bullets,b_list& bombs,e_list& enemies,w_vec& walls,b_list& powerups,r_list& rockets,boss& boss1,int& score){
+	bool should_continue;
+	
+	m_bullets.lock();
+	b_list::iterator it1=bullets.begin();
+	while(it1!=bullets.end())
+	{		 
+		should_continue = false;
+		
+		if(it1->y<=0)	
+		{								//bullet reached the ceiling
+			it1 = bullets.erase(it1);
+			continue;
+		}
+		
+		m_bombs.lock();
+		b_list::iterator it2 = bombs.begin();
+		while(it2!=bombs.end())
+		{
+			if(it1->x==it2->x && (it1->y==it2->y || it1->y==it2->y+1)){		//bullet+bomb
+				it1=bullets.erase(it1);
+				should_continue = true;
+				it2=bombs.erase(it2);
+				score+=50;
+				break;
+			}
+			else
+				++it2;
+		}
+		m_bombs.unlock();
+		if(should_continue) continue;
+		
+		m_enemies.lock();
+		for(e_list::iterator it3=enemies.begin(); it3!=enemies.end(); ++it3)
+			if(it1->x==it3->x && it1->y==it3->y && it3->alive){			//bullet+enemy
+				it1=bullets.erase(it1);
+				should_continue = true;
+				it3->alive=false;
+				if((double)rand()/RAND_MAX<(double)AVERAGE_DROP/ENEMY_NUM)	//a powerup is dropped (AVERAGE_DROP is the mean number of powerups dropped per play in Normal mode)		
+					drop_powerup(it3->x,it3->y+1,powerups);
+				score+=100;
+				break;
+			}
+		m_enemies.unlock();
+		if(should_continue) continue;
+		
+		
+			
+		m_boss.lock();
+		if((it1->x>=boss1.x+boss1.width/2-2 && it1->x<=boss1.x+boss1.width/2+2) && boss1.alive){	//bullet+boss
+				boss1.health--;
+				if(it1->y==boss1.y) it1=bullets.erase(it1);	//bullet gets destroyed only when has reached boss's top
+		        	else
+				{
+					++it1;
+					m_boss.unlock();
+					continue;
+				}
+								//(to make the boss lose life more quickly)
+		}
+		m_boss.unlock();
+		
+		++it1;
+	}
+	m_bullets.unlock();
+    
+   m_rockets.lock();
+   r_list::iterator itr=rockets.begin();   
+	while(itr != rockets.end())
+	{
+		should_continue = false;
+		
+		if(itr->y<=0)						//rocket reached the ceiling
+		{
+			itr=rockets.erase(itr);
+			continue;
+		}
+		
+		m_bombs.lock();
+		b_list::iterator it2=bombs.begin(); //bomb+rocket
+		while(it2!=bombs.end())
+		{
+			if((itr->x==it2->x && itr->y==it2->y) || (itr->v>0 && (itr->x==it2->x-1 && itr->y==it2->y+1)) || (itr->v<0 && (itr->x==it2->x+1 && itr->y==it2->y+1))){	//rocket+bomb
+				itr=rockets.erase(itr);
+				should_continue = true;
+				it2=bombs.erase(it2);
+				score+=50;
+				break;
+			}
+			else
+				++it2;
+		}
+		m_bombs.unlock();
+		if(should_continue) continue;
+		
+		m_enemies.lock();
+		e_list::iterator it3 = enemies.begin();
+		while(it3!=enemies.end())
+		{
+			if(itr->x==it3->x && itr->y==it3->y){				//rocket+enemy
+				itr=rockets.erase(itr);
+				it3=enemies.erase(it3);
+				should_continue = true;
+				break;
+			}
+			else
+				++it3;
+		}
+		m_enemies.unlock();
+		if(should_continue) continue;
+		
+		m_boss.lock();
+		if((itr->x>=boss1.x+boss1.width/2-2 && itr->x<=boss1.x+boss1.width/2+2) && boss1.alive) 	//rocket+boss
+		{
+			boss1.health--;
+			if(itr->y==boss1.y) 
+			{
+				itr=rockets.erase(itr);
+				m_boss.unlock();
+   			continue;
+   		}
+   	}
+	   m_boss.unlock();
+	   
+	   ++itr;
+	}
+	m_rockets.unlock();
+    	
+	m_bombs.lock();
+   b_list::iterator itb=bombs.begin();
+   while(itb!=bombs.end()){
+		if(itb->y>=R)					//bomb reached the floor
+     	{
+     		itb=bombs.erase(itb);
+     		continue;
+     	}
+     		
+		if(itb->x>=player1.x && itb->x<player1.x+player1.length && itb->y>player1.y) //bomb+player
+		{
+				itb=bombs.erase(itb);
+				continue;
+		}
+		
+		++itb;
+	}
+	m_bombs.unlock();
+        
+	m_pow.lock();
+	m_player.lock();
+	b_list::iterator itp=powerups.begin();
+	while( itp!=powerups.end()){
+	  	if(itp->y==player1.y && itp->x>=player1.x && itp->x<player1.x+player1.length){
+	  		switch(itp->id){
+	  			case 64:
+	  				if(player1.weaponclass<MAX_WEAPONCLASS) player1.weaponclass++;
+	  				break;
+	  			case 128:
+	  				if(player1.length>2){
+						mvaddch(player1.y,player1.x+player1.length-1,' ');
+						player1.length--;
+				}
+	  				break;
+	  			case 512:
+	  				if(!(player1.rocketlauncher)) player1.rocketlauncher=TRUE;
+	  				else if(player1.weaponclassrkt<MAX_WEAPONCLASSRKT) player1.weaponclassrkt++;
+	  				break;
+	  		}
+	  		itp=powerups.erase(itp);
+	  		continue;
+	  	}
+		
+		if(itp->y>=R)				//powerup reached the floor
+		{						
+  			itp=powerups.erase(itp);
+  			continue;
+  		}
+	 
+ 		++itp;
+	}
+	m_pow.unlock();
+	m_player.unlock();
+        	
+	m_walls.lock();
+	for(int i=0;i<walls.size();i++)
+	  	for(int j=0;j<walls[i].width;j++)
+	  		for(int k=0;k<walls[i].height;k++)
+	  		{
+	  			if(walls[i].health[k][j]>0)
+	  			{
+	  				m_bullets.lock();
+	  				b_list::iterator it1=bullets.begin();
+					while(it1!=bullets.end())
+					{
+						if(it1->x==walls[i].x+j && it1->y==walls[i].y+k){
+							it1=bullets.erase(it1);
+							walls[i].health[k][j]--;
+						}
+						else
+							++it1;
+					}
+					m_bullets.unlock();
+					
+					m_bombs.lock();
+					b_list::iterator it2=bombs.begin();
+					while(it2!=bombs.end())
+					{
+						if(it2->x==walls[i].x+j && it2->y==walls[i].y+k){
+							it2=bombs.erase(it2);
+							walls[i].health[k][j]--;
+						}
+						else
+							++it2;
+					}
+					m_bombs.unlock();
+					
+					m_rockets.lock();
+					r_list::iterator it3=rockets.begin();
+					while(it3!=rockets.end())
+					{
+						if(it3->x==walls[i].x+j && it3->y==walls[i].y+k){
+							it3=rockets.erase(it3);
+							walls[i].health[k][j]--;
+						}
+						else
+							++it3;
+					}
+					m_rockets.unlock();
+					
+					m_pow.lock();
+					b_list::iterator it4=powerups.begin();
+					while(it4!=powerups.end())
+					{
+						if(it4->x==walls[i].x+j && it4->y==walls[i].y+k){
+							it4=powerups.erase(it4);
+						}
+						else
+							++it4;
+					}
+					m_pow.unlock();
+			}
+		}
+		m_walls.unlock();
+}
+
+
+//********** SAVE FUNCTIONS *****************************
+
+void refreshrecords(int newscore,WINDOW* win)
+{
+	r_vec records;
+	std::string nick;
+	record newrecord;
+	
+	std::string local_recpath;
+	std::string local_dir=getenv("HOME");	//get environment variable $HOME
+	local_dir+=RECORD_DIR;			//we set local_dir and local_recpath: ~/.local/share/invaders/records.dat
+	local_recpath=local_dir;
+	local_recpath+=RECORD_FILE;
+
+	wattron(win,COLOR_PAIR(5));
+	mvwprintw(win,6,5,"Please insert your nick");
+	mvwprintw(win,7,2,"(up to 5 characters): ");
+	wattron(win,COLOR_PAIR(1));
+	echo();
+	char getnick[6];
+	wscanw(win,"%s",getnick);
+	nick=getnick;
+	nick.resize(5,'.');
+	
+	noecho();
+	
+	std::ifstream recordin(local_recpath.c_str());	//first, check if local_recpath exists; if not, create it. 
+	
+	if(recordin)	//note that local_recpath is actually a symlink to global_recpath
+	{
+		recordin >> newrecord.nick;
+		recordin >> newrecord.score;
+		while(!recordin.eof())
+		{
+			records.push_back(newrecord);
+			recordin >> newrecord.nick;
+			recordin >> newrecord.score;
+		}
+		recordin.close();
+		
+		newrecord.score=newscore;
+		newrecord.nick=nick;
+	
+		records.push_back(newrecord);
+		sort(records.rbegin(), records.rend());
+		
+		wattron(win,COLOR_PAIR(6));
+		mvwprintw(win,9,11,"TOP FIVE");
+		wattron(win,COLOR_PAIR(0));
+		int count=0;
+		for(r_vec::iterator it=records.begin(); (it!=records.begin()+5 && it!=records.end()); ++it,++count)
+		{
+			wmove(win,10+count,9);
+			it->printwin(win);
+		}
+		
+		count=0;
+		for(r_vec::iterator it=records.begin(); it!=records.end(); ++it)
+		{
+			count++;
+			if(*it==newrecord)
+			{
+				mvwprintw(win,16,3,"You're number %i out of %i",count,records.size());
+				break;
+			}
+		}
+	
+		std::ofstream recordout(local_recpath.c_str());
+		for(r_vec::iterator it=records.begin(); it!=records.end(); ++it)
+			it->print(recordout);
+		recordout.close();
+	} 
+	else //records.dat not found
+	{
+		//if local_recpath does not exist, then we must create the local_dir.
+		
+		recordin.close();
+		recordin.clear();
+		
+		create_folder(0);
+		
+		//now we check if global_recpath exists.
+		
+		std::string global_recpath=GLOBAL_DIR;		//global_recpath is GLOBAL_DIR/records.dat
+		global_recpath+=RECORD_FILE;
+		
+		//we try to open GLOBAL_DIR/records.dat
+		std::ifstream globalin(global_recpath.c_str());
+		
+		if(!globalin){
+			globalin.close();
+			globalin.clear();
+			create_folder(1);	//try to create global_dir (will fail if already
+			std::ofstream globalout(global_recpath.c_str());		//exists) and save the global_recpath.
+			
+			globalout.close();
+			globalout.clear();
+			
+			chmod(global_recpath.c_str(),S_IRWXG | S_IRWXU | S_IRWXO);
+
+		}
+		
+		else{	
+			//just save to GLOBAL_DIR/records.dat
+			globalin >> newrecord.nick;
+			globalin >> newrecord.score;
+			while(!globalin.eof())
+			{
+				records.push_back(newrecord);
+				globalin >> newrecord.nick;
+				globalin >> newrecord.score;
+			}
+			globalin.close();
+						
+			
+		}
+			
+		//finally, create the symlink to global_recpath
+		
+		symlink(global_recpath.c_str(),local_recpath.c_str());
+		
+		newrecord.score=newscore;
+		newrecord.nick=nick;
+		
+		records.push_back(newrecord);
+		sort(records.rbegin(), records.rend());
+			
+		//and save there the records.
+		
+		std::ofstream recordout(local_recpath.c_str());
+		for(r_vec::iterator it=records.begin(); it!=records.end(); ++it)
+			it->print(recordout);
+		recordout.close();
+	
+	}	
+
+}
+
+
+void print_scores(){
+	r_vec records;
+	std::string recordpath;
+	std::string record_dir=getenv("HOME");
+	record_dir+=RECORD_DIR;
+	recordpath=record_dir;
+	recordpath+=RECORD_FILE;
+	std::ifstream recordin(recordpath.c_str());
+	record newrecord;
+	int i=1;
+	
+	
+	if(recordin){
+		WINDOW *recs;
+		recs=newwin(25,30,0,0);
+		box(recs,ACS_VLINE,ACS_HLINE);
+		wattron(recs,COLOR_PAIR(5));
+		mvwprintw(recs,1,1,"======= HIGHSCORES =======");
+		wattron(recs,COLOR_PAIR(0));
+		recordin >> newrecord.nick;
+		recordin >> newrecord.score;
+		while(!recordin.eof() && i<21)
+		{
+			records.push_back(newrecord);
+			recordin >> newrecord.nick;
+			recordin >> newrecord.score;
+			i++;
+		}
+		recordin.close();
+		
+		i=1;
+		
+		for(r_vec::iterator it=records.begin(); it!=records.end(); ++it){
+			if(i<10)
+				mvwprintw(recs,i+2,1,"0%i- ",i);
+			else
+				mvwprintw(recs,i+2,1,"%i- ",i);
+			it->printwin(recs);
+			i++;
+		}
+		
+		wrefresh(recs);
+		timeout(-1);
+		if(getch()!=ERR){
+			delwin(recs);
+			erase();
+			refresh();
+		}
+	}
+	else{
+		WINDOW *recs;
+		std::string host=getenv("USER");
+		recs=newwin(5,3+host.length()+record_dir.length(),5,5);
+		box(recs,ACS_VLINE,ACS_HLINE);
+		wattron(recs,COLOR_PAIR(5));
+		mvwprintw(recs,1,1,"Save file:"); 
+		mvwprintw(recs,2,1,"%s",record_dir.c_str()); 
+		mvwprintw(recs,3,1,"%s not found.",RECORD_FILE); 
+		//mvwprintw(recs,4,1,"not found."); 
+		wrefresh(recs);
+		timeout(-1);
+		if(getch()!=ERR){
+			delwin(recs);
+			erase();
+			refresh();
+		}
+	}
+}
+
+
+/*//=========== THREADS FUNCTIONS ==============================
+
+void *pmusic(void *arg){
+	while(1){
+		system("beep 330 -l 150 -n -f 1 -l 40 -n -f 494 -l 159 -n -f 1 -l 40 -n -f 660 -l 150 -n -f 1 -l 40 -n -f 590 -l 150 -n -f 660 -l 150 -n -f 494 -l 100 -n -f 494 -l 100 -n -f 523 -l 150 -n -f 1 -l 40 -n -f 440 -l 150 -n -f 1 -l 40 -n -f 494 -l 150 -n -f 1 -l 40 -n -f 392 -l 100 -n -f 392 -l 100 -n -f 440 -l 150 -n -f 370 -l 150 -n -f 1 -l 40 -n -f 392 -l 150 -n -f 1 -l 40 -n -f 330 -l 100 -n -f 330 -l 100 -n -f 370 -l 150 -n -f 1 -l 40 -n -f 294 -l 150 -n -f 1 -l 40 -n -f 330 -l 150 -n -f 247 -l 100 -n -f 247 -l 100 -n -f 261 -l 150 -n -f 1 -l 40 -n -f 311 -l 150 -n -f 1 -l 40 -n -f 330 -l 150 -n -f 1 -l 40 -n -f 247 -l 100 -n -f 247 -l 100 -n -f 262 -l 150 -n -f 1 -l 40 -n -f 370 -l 150 -n -f 1 -l 40 -n -f 330 -l 150 -n -f 1 -l 40 -n -f 494 -l 159 -n -f 1 -l 40 -n -f 660 -l 150 -n -f 1 -l 40 -n -f 590 -l 150 -n -f 660 -l 150 -n -f 494 -l 100 -n -f 494 -l 100 -n -f 523 -l 150 -n -f 1 -l 40 -n -f 440 -l 150 -n -f 1 -l 40 -n -f 494 -l 150 -n -f 1 -l 40 -n -f 392 -l 100 -n -f 392 -l 100 -n -f 440 -l 150 -n -f 370 -l 150 -n -f 1 -l 40 -n -f 392 -l 150 -n -f 1 -l 40 -n -f 330 -l 100 -n -f 330 -l 100 -n -f 370 -l 150 -n -f 1 -l 40 -n -f 294 -l 150 -n -f 1 -l 40 -n -f 330 -l 150 -n -f 247 -l 100 -n -f 247 -l 100 -n -f 261 -l 150 -n -f 1 -l 40 -n -f 311 -l 150 -n -f 1 -l 40 -n -f 330 -l 150 -n -f 1 -l 40 -n -f 247 -l 100 -n -f 247 -l 100 -n -f 262 -l 150 -n -f 1 -l 40 -n -f 370 -l 150 -n -f 1 -l 40 -n -f 330 -l 150 -n -f 1 -l 40 2> /dev/null");
+		napms(2000);
+	}
+}
+
+void *pshoot_sound(void *arg){
+	system("beep -f 1000 -l 30 -n -f 850 -l 30 2> /dev/null");
+}
+
+void *penshoot_sound(void *arg){
+	system("beep -f 1500 -l 30 -n -f 1000 -l 30 2> /dev/null");
+}
+
+void *pwin_theme(void *arg){
+	system("beep -f 1000 -l 150 -n -f 800 -l 150 -n -f 1000 -l 150 -n -f 1500 -l 600 2> /dev/null");
+}
+
+void *plose_theme(void *arg){
+	system("beep -f 700 -l 150 -n -f 585 -l 150 -n -f 550 -l 150 -n -f 520 -l 600 2> /dev/null");
+}
+
+void pkill_music(pthread_t thread){
+	pthread_cancel(thread);
+	system("beep -f 1 2> /dev/null");
+}*/
+
+
+				
+//=========BOSSRUSH FUNCTIONS=======================
+
+void choose_level_bossrush(double& shootr, int& refresh_t, char& level,int* commands)	//returns ENEMY_NUM
+{
+	std::string phrase;
+	phrase=choose_phrase();
+	
+	do{
+		print_title();
+		print_catchphrase(phrase);
+		attron(COLOR_PAIR(1));
+		mvprintw(5,0,"Choose difficulty level:");
+		attron(COLOR_PAIR(1));
+		mvprintw(6,0,"1- Easy");
+		attron(COLOR_PAIR(3));
+		mvprintw(7,0,"2- Medium");
+		attron(COLOR_PAIR(2));
+		mvprintw(8,0,"3- Hard");
+		attron(COLOR_PAIR(4));
+		mvprintw(9,0,"4- Impossible");
+		attron(COLOR_PAIR(5));
+		mvprintw(10,0,"i- Info");
+		attron(COLOR_PAIR(6));
+		mvprintw(11,0,"h- Highscores");
+		attron(COLOR_PAIR(1));
+		mvprintw(12,0,"c- Commands");
+		attron(COLOR_PAIR(2));
+		mvprintw(13,0,"q- Quit");
+		
+		refresh();
+
+		timeout(80);
+		
+		level=tolower(getch());
+	
+		if(!(atoi(&level)==1 || atoi(&level)==2 || atoi(&level)==3 || atoi(&level)==4 || level=='i' || level=='h' || level=='r' || level=='q') && level!=ERR){
+			attron(COLOR_PAIR(2));
+			mvprintw(14,0,"Bad input. Please choose a number within 1 and 4.");
+			attron(COLOR_PAIR(0));	
+		}
+		
+		if(level=='i')
+			print_info();
+		
+		else if(level=='h')
+			print_scores_bossrush();
+		
+		else if(level=='r')
+			phrase=choose_phrase();
+		
+		else if(level=='c')
+			change_commands(commands);
+			
+		else if(level=='q'){
+			endwin();
+			cout<<lightgreen<<"Game exited correctly."<<none<<endl;
+			exit(1);
+		}
+		
+	}while(!(atoi(&level)==1 || atoi(&level)==2 || atoi(&level)==3 || atoi(&level)==4));
+	
+	refresh_t=0;
+	
+	switch(atoi(&level))        //setting game parameters
+	{
+		case 1:
+		{
+			shootr = 0.006;
+			refresh_t = (int)(0.09*1E3);
+		}
+		case 2:
+		{
+			shootr = 0.009;
+			refresh_t = (int)(0.085*1E3);
+		}
+		case 3:
+		{
+			shootr = 0.015;
+			refresh_t = (int)(0.08*1E3);
+		}
+		case 4:
+		{
+			shootr = 0.020;
+			refresh_t = (int)(0.07*1E3);
+		}
+	}
+	
+}
+
+void resetbosses(boss* Bosses,boss& boss1,player& player1){
+	boss* bosses=Bosses;
+
+	bosses->health=bosses->healthmax;
+	bosses++;
+	bosses->health=bosses->healthmax;
+	bosses++;
+	bosses->health=bosses->healthmax;
+	bosses++;
+	bosses->health=bosses->healthmax;
+	bosses++;
+	bosses->health=bosses->healthmax;
+
+	boss1=*Bosses;
+	boss1.alive=true;
+
+	player1.weaponclass=1;
+}
+
+void Victory_bossrush(std::string name,int score,char level,int chflag){
+	score+=1500*atoi(&level);
+	WINDOW *victory;
+
+	victory=newwin(19,32,7,17);
+	box(victory,ACS_VLINE,ACS_HLINE);
+	wattron(victory,COLOR_PAIR(1));
+	mvwprintw(victory,2,5,"YOU DEFEATED %s!",name.c_str());
+	wattron(victory,COLOR_PAIR(3));
+	mvwprintw(victory,4,5,"+ %i pts!",atoi(&level)*1500);
+	wattron(victory,COLOR_PAIR(1));
+	mvwprintw(victory,4,5,"YOU WON!");
+	wattron(victory,COLOR_PAIR(3));
+	mvwprintw(victory,4,5,"Your score is: %i",score);
+	wrefresh(victory);
+	
+	if(chflag==0)
+		refreshrecords_bossrush(score,victory);
+	else{
+		wattron(victory,COLOR_PAIR(4));
+		mvwprintw(victory,7,3,"I think you used cheats...");
+	}
+	
+	wrefresh(victory);
+	
+	delwin(victory);
+
+}
+
+
+
+
+void refreshrecords_bossrush(int newscore,WINDOW* win)
+{
+	r_vec records;
+	std::string nick;
+	record newrecord;
+	std::string local_recpath;
+	std::string local_dir=getenv("HOME");	//get environment variable $HOME
+	local_dir+=RECORD_DIR;			//we set local_dir and local_recpath: ~/.local/share/invaders/records_bossrush.dat
+	local_recpath=local_dir;
+	local_recpath+=RECORD_FILE_BOSSRUSH;
+
+	wattron(win,COLOR_PAIR(5));
+	mvwprintw(win,6,5,"Please insert your nick");
+	mvwprintw(win,7,2,"(up to 5 characters): ");
+	wattron(win,COLOR_PAIR(1));
+	echo();
+	char getnick[6];
+	wscanw(win,"%s",getnick);
+	nick=getnick;
+	nick.resize(5,'.');
+	
+	noecho();
+	
+	std::ifstream recordin(local_recpath.c_str());
+	
+	if(recordin)
+	{
+		recordin >> newrecord.nick;
+		recordin >> newrecord.score;
+		while(!recordin.eof())
+		{
+			records.push_back(newrecord);
+			recordin >> newrecord.nick;
+			recordin >> newrecord.score;
+		}
+		recordin.close();
+		
+		newrecord.score=newscore;
+		newrecord.nick=nick;
+	
+		records.push_back(newrecord);
+		sort(records.rbegin(), records.rend());
+		
+		wattron(win,COLOR_PAIR(6));
+		mvwprintw(win,9,11,"TOP FIVE");
+		wattron(win,COLOR_PAIR(0));
+		int count=0;
+		for(r_vec::iterator it=records.begin(); (it!=records.begin()+5 && it!=records.end()); ++it,++count)
+		{
+			wmove(win,10+count,9);
+			it->printwin(win);
+		}
+		
+		count=0;
+		for(r_vec::iterator it=records.begin(); it!=records.end(); ++it)
+		{
+			count++;
+			if(*it==newrecord)
+			{
+				mvwprintw(win,16,3,"You're number %i out of %i",count,records.size());
+				break;
+			}
+		}
+	
+		std::ofstream recordout(local_recpath.c_str());
+		for(r_vec::iterator it=records.begin(); it!=records.end(); ++it)
+			it->print(recordout);
+		recordout.close();
+	}
+	else //records_bossrush.dat not found
+	{
+		recordin.close();
+		recordin.clear();
+		
+		create_folder(0); //this will fail if local_dir already exists (possible if player played bossrush before).	
+		
+		//now we check if global_recpath exists.
+		
+		std::string global_recpath=GLOBAL_DIR;		//global_recpath is GLOBAL_DIR/records_bossrush.dat
+		global_recpath+=RECORD_FILE_BOSSRUSH;
+		
+		//we try to open GLOBAL_DIR/records.dat
+		std::ifstream globalin(global_recpath.c_str());
+		
+		if(!globalin){
+			globalin.close();
+			globalin.clear();
+			create_folder(1);	//try to create global_dir (will fail if already
+			std::ofstream globalout(global_recpath.c_str());		//exists) and save the global_recpath.
+			
+			globalout.close();
+			globalout.clear();
+			
+			chmod(global_recpath.c_str(),S_IRWXG | S_IRWXU | S_IRWXO);
+
+		}
+		
+		else{	
+			//just save to GLOBAL_DIR/records_bossrush.dat
+			globalin >> newrecord.nick;
+			globalin >> newrecord.score;
+			while(!globalin.eof())
+			{
+				records.push_back(newrecord);
+				globalin >> newrecord.nick;
+				globalin >> newrecord.score;
+			}
+			globalin.close();
+						
+			
+		}
+			
+		//finally, create the symlink to global_recpath
+		
+		symlink(global_recpath.c_str(),local_recpath.c_str());
+		
+		newrecord.score=newscore;
+		newrecord.nick=nick;
+		
+		records.push_back(newrecord);
+		sort(records.rbegin(), records.rend());
+			
+		//and save there the records.
+		
+		std::ofstream recordout(local_recpath.c_str());
+		for(r_vec::iterator it=records.begin(); it!=records.end(); ++it)
+			it->print(recordout);
+		recordout.close();
+	}
+
+}
+
+void print_scores_bossrush(){
+	r_vec records;
+	std::string recordpath;
+	std::string record_dir=getenv("HOME");
+	record_dir+=RECORD_DIR;
+	recordpath=record_dir;
+	recordpath+=RECORD_FILE_BOSSRUSH;
+	std::ifstream recordin(recordpath.c_str());
+	record newrecord;
+	int i=1;
+	
+	
+	if(recordin){
+		WINDOW *recs;
+		recs=newwin(25,30,0,0);
+		box(recs,ACS_VLINE,ACS_HLINE);
+		wattron(recs,COLOR_PAIR(5));
+		mvwprintw(recs,1,1,"======= HIGHSCORES =======");
+		wattron(recs,COLOR_PAIR(0));
+		recordin >> newrecord.nick;
+		recordin >> newrecord.score;
+		while(!recordin.eof() && i<21)
+		{
+			records.push_back(newrecord);
+			recordin >> newrecord.nick;
+			recordin >> newrecord.score;
+			i++;
+		}
+		recordin.close();
+		
+		i=1;
+		
+		for(r_vec::iterator it=records.begin(); it!=records.end(); ++it){
+			if(i<10)
+				mvwprintw(recs,i+2,1,"0%i- ",i);
+			else
+				mvwprintw(recs,i+2,1,"%i- ",i);
+			it->printwin(recs);
+			i++;
+		}
+		
+		wrefresh(recs);
+		timeout(-1);
+		if(getch()!=ERR){
+			delwin(recs);
+			erase();
+			refresh();
+		}
+	}
+	else{
+		WINDOW *recs;
+		std::string host=getenv("USER");
+		recs=newwin(6,25+host.length(),5,5);
+		box(recs,ACS_VLINE,ACS_HLINE);
+		wattron(recs,COLOR_PAIR(5));
+		mvwprintw(recs,1,1,"Save file:"); 
+		mvwprintw(recs,2,1,"%s",record_dir.c_str()); 
+		mvwprintw(recs,3,1,"%s",RECORD_FILE_BOSSRUSH); 
+		mvwprintw(recs,4,1,"not found."); 
+		wrefresh(recs);
+		timeout(-1);
+		if(getch()!=ERR){
+			delwin(recs);
+			erase();
+			refresh();
+		}
+	}
+}
+
+
+void create_readme(){
+
+	std::string recordpath;
+	std::string record_dir=getenv("HOME");
+	record_dir+=RECORD_DIR;
+	recordpath=record_dir;
+	recordpath+="README.txt";
+	std::ifstream checkread(recordpath.c_str());
+	if(!checkread){
+		checkread.close();
+		checkread.clear();
+		std::ofstream readme(recordpath.c_str());
+	
+		readme<<"#==Space Invaders=="<<endl;
+		readme<<"#"<<endl;
+		readme<<"#Original game was created and developed by Giacomo Parolini and Enrico Guiraud (year 2010-2013)"<<endl;
+		readme<<"#License: GNU GPL"<<endl;
+		readme<<"#"<<endl;
+		readme<<"#Game version logs:"<<endl;
+		readme<<"# -invaders2.0"<<endl;
+		readme<<"# -invaders2.1"<<endl;
+		readme<<"# -invaders3.0"<<endl;
+		readme<<"# -invaders3.1"<<endl;
+		readme<<"# -invaders3.2"<<endl;
+		readme<<"# -invaders3.3"<<endl;
+		readme<<"# -invaders3.4"<<endl;
+		readme<<"# -invaders3.5"<<endl;
+		readme<<"# -invaders3.6"<<endl;
+		readme<<"# -invaders4.0"<<endl;
+		readme<<"# -invaders4.1"<<endl;
+		readme<<"# -invaders4.2"<<endl;
+		readme<<"# -invaders4.3"<<endl;
+		readme<<"# -invaders4.3.5"<<endl;
+		readme<<"# -curses_invaders2.0"<<endl;
+		readme<<"# -curses_invaders3.0"<<endl;
+		readme<<"# -curses_invaders3.5"<<endl;
+		readme<<"# -curses_invaders4.0"<<endl;
+		readme<<"# -curses_invaders4.1"<<endl;
+		readme<<"# -curses_invaders4.2"<<endl;
+		readme<<"# -curses_invaders4.3"<<endl;
+		readme<<"# -curses_invaders4.4"<<endl;
+		readme<<"# -GL_invaders"<<endl;
+		readme<<"#"<<endl;
+		readme<<"#All versions are written in C++. "<<endl;
+		readme<<"#"<<endl;
+		readme<<"#curses_invaders versions were developed by Giacomo Parolini and differ from the previous ones for exploiting library <ncurses.h> for graphic terminal management."<<endl;
+		readme<<"#GL_invaders versions were developed by Enrico Guiraud and exploit GL libraries such as <glutm/window.h> and <glt/project.h> for graphics."<<endl;
+		readme<<"#"<<endl;
+		readme<<"#System Requirements:"<<endl;
+		readme<<"#All versions are Linux x-executable files, so will only run within Linux environment."<<endl;
+		readme<<"#However, files CAN be compiled also in MacOS environment."<<endl;
+		readme<<"#"<<endl;
+		readme<<"#curses_invaders versions require the library <ncurses.h> and may not work correctly on some terminals. Versions 3.0 and following also contain executable \"bossrush\"."<<endl;
+		readme<<"#"<<endl;
+		readme<<"#since v.4.3, game controls are customizable at the beginning of the game."<<endl;
+		readme<<"#v.4.4 implements shared highscores."<<endl;
+		readme<<"#"<<endl;
+		readme<<"#"<<endl;
+		readme<<"#CREATING AND EDITING BOSSES (at the moment unavailable: the game doesn't create the scripts automatically)"<<endl;
+		readme<<"#curses_invaders4.0 and following also come with the scripts checkboss.sh and setboss.sh, written by Enrico Guiraud. These scripts are used to edit the five game bosses, allowing the player to create his custom bosses. "<<endl;
+		readme<<"#In order to create a boss, follow these steps:"<<endl;
+		readme<<"# *1: create a file named <custom_boss_name>.dat and open it with any text editor (like Gedit, Vim or Notepad)."<<endl;
+		readme<<"# *2: \"draw\" your boss in ASCII-style. You don't have to pay attention of the rows' lengths, as checkboss.sh will fix them automatically. Just be sure the lines and the columns fit the game board (game board's dimensions are written in definitions.hpp as \"R\" and \"C\")."<<endl;
+		readme<<"# *3: save your file.dat and launch either checkboss.sh (if you just want to adjust your boss's dimensions) or directly setboss.sh (to add the boss to the game). Syntax of checkboss.sh is \"./checkboss.sh <bossname.dat>\" or \"./checkboss <bossname>\". Syntax of setboss.sh is \"./setboss.sh <bossname> <level>\"; the script will substitute the boss of the <level>-th game level (1=easy, 2=medium, 3=hard, 4=impossible, 5=special boss) with your custom boss. Notice that setboss.sh needs you to pass the argument WITHOUT the \".dat\"."<<endl;
+		readme<<"# *4: play to test your new boss! If you want to restore the original boss, just run setboss.sh once again passing the original boss as argument."<<endl;
+		readme<<"#"<<endl;
+		readme<<"#...and yes: cheats ARE available, just try and find them ;)"<<endl;
+	
+		readme.close();
+	}
+}
+
+void create_std_bosses(){
+	std::string bosspath;
+	std::string boss_dir=getenv("HOME");
+	boss_dir+=RECORD_DIR;
+	bosspath=boss_dir;
+	std::string bosspath1=bosspath+BOSS_FILE1+".dat";
+	std::ifstream checkread(bosspath1.c_str());
+	if(!checkread){
+	
+		std::string newrecordpath=boss_dir+RECORD_FILE;	//check if .invaders/records.dat exists
+		std::ifstream tryrecord(newrecordpath.c_str());
+		
+		if(!tryrecord){		//.invaders/records.dat does not exist, so create the .invaders directory
+			tryrecord.close();
+			tryrecord.clear();
+			
+			std::string newrecordpath2=boss_dir+RECORD_FILE_BOSSRUSH;	//check if .invaders/records_bossrush.dat exists
+			std::ifstream tryrecord2(newrecordpath2.c_str());
+		
+			if(!tryrecord2){		
+				tryrecord2.close();
+				tryrecord2.clear();
+				mkdir(boss_dir.c_str(),S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
+				create_readme();
+				//create_setsize();
+				//std::string setsizepath=boss_dir+"setsize.sh";
+				//chmod(setsizepath.c_str(),S_IRWXU);
+			}	
+		}
+		
+		checkread.close();
+		checkread.clear();
+		std::ofstream boss1(bosspath1.c_str());
+		
+		boss1<<"  _____  "<<endl;
+		boss1<<"//     \\\\"<<endl;
+		boss1<<"|  0 0  |"<<endl;
+		boss1<<"c   L   P"<<endl;
+		boss1<<"\\  MMM  /"<<endl;
+		boss1<<" \\_____/ "<<endl;
+		
+		boss1.close();
+		boss1.clear();
+		
+		std::string bosspath2=bosspath+BOSS_FILE2+".dat";
+		std::ofstream boss2(bosspath2.c_str());
+		
+		boss2<<"  _______  "<<endl;
+		boss2<<" W _ _ _ W "<<endl;
+		boss2<<"|_|o| |o|_|"<<endl;
+		boss2<<"c    c    P"<<endl;
+		boss2<<" \\__NNN__/ "<<endl;
+		
+		boss2.close();
+		boss2.clear();
+		
+		std::string bosspath3=bosspath+BOSS_FILE3+".dat";
+		std::ofstream boss3(bosspath3.c_str());
+		
+		boss3<<"  99999  "<<endl;
+		boss3<<" C \\ / D "<<endl;
+		boss3<<"C  0 0  D"<<endl;
+		boss3<<"C_  ^  _D"<<endl;
+		boss3<<"  | J |  "<<endl;
+		boss3<<"   \\_/   "<<endl;
+		
+		boss3.close();
+		boss3.clear();
+		
+		std::string bosspath4=bosspath+BOSS_FILE4+".dat";
+		std::ofstream boss4(bosspath4.c_str());
+		
+		boss4<<"  MMMMMMM  "<<endl;
+		boss4<<" M       M "<<endl;
+		boss4<<"|  == ==  |"<<endl;
+		boss4<<"c    L    D"<<endl;
+		boss4<<" MMM   MMM "<<endl;
+		boss4<<"  MMMMMMM  "<<endl;
+		
+		boss4.close();
+		boss4.clear();
+		
+		std::string bosspath5=bosspath+BOSS_FILE5+".dat";
+		std::ofstream boss5(bosspath5.c_str());
+		
+		boss5<<" \\__ ______ __/  "<<endl;
+		boss5<<"\\___  =  =  ___/ "<<endl;
+		boss5<<" |  | =  = |  |  "<<endl;
+		boss5<<"     \\_  _/      "<<endl;
+		boss5<<"    /  ||  \\     "<<endl;
+		
+		boss5.close();
+		boss5.clear();
+		
+	}
+}
+
+/*void create_setsize(){
+
+	std::string recordpath;
+	std::string record_dir=getenv("HOME");
+	record_dir+=RECORD_DIR;
+	recordpath=record_dir;
+	recordpath+="setsize.sh";
+	std::ifstream checkread(recordpath.c_str());
+	if(!checkread){
+		checkread.close();
+		checkread.clear();
+		std::ofstream setsize(recordpath.c_str());
+	
+		setsize<<"#!/bin/bash"<<endl;
+
+		setsize<<"DEFAULT_R=30"<<endl;
+		setsize<<"DEFAULT_C=60"<<endl;
+		setsize<<"R=0"<<endl;
+		setsize<<"C=0"<<endl;
+		setsize<<"INPUT_FILE=definitions.hpp"<<endl;
+
+		setsize<<"trap \"rm $INPUT_FILE.tmp 2> /dev/null; exit -1\" SIGINT SIGTERM"<<endl;
+
+		setsize<<"if [[ $1 == \"default\" ]]; then"<<endl;
+		setsize<<"sed s/\"#define R [0-9]*\"/\"#define R $DEFAULT_R\"/ <$INPUT_FILE >$INPUT_FILE.tmp"<<endl;
+		setsize<<"sed s/\"#define C [0-9]*\"/\"#define C $DEFAULT_C\"/ <$INPUT_FILE.tmp >$INPUT_FILE"<<endl;
+		setsize<<"rm $INPUT_FILE.tmp"<<endl;
+		setsize<<"make clean"<<endl;
+		setsize<<"make -j4"<<endl;
+		setsize<<"exit 0"<<endl;
+		setsize<<"elif [[ $# -gt 0 ]]; then echo Usage: $0 \"[default]\"; exit 1"<<endl;
+		setsize<<"else"<<endl;
+
+		setsize<<"echo Insert new Row number \\(5-120\\)"<<endl;
+		setsize<<"until [[ $R -ge 5 && $R -le 120 ]]; do"<<endl;
+		setsize<<"	read R"<<endl;
+		setsize<<"if [[ $R -lt 5 || $R -gt 120 ]]; then echo Invalid size.; fi"<<endl;
+		setsize<<"echo New R will be $R"<<endl;
+		setsize<<"done"<<endl;
+
+		setsize<<"echo Insert new Column number \\(5-120\\)"<<endl;
+		setsize<<"until [[ $C -ge 5 && $C -le 120 ]]; do"<<endl;
+		setsize<<"	read C"<<endl;
+		setsize<<"if [[ $C -lt 5 || $C -gt 120 ]]; then echo Invalid size.; fi"<<endl;
+		setsize<<"echo New C will be $C"<<endl;
+		setsize<<"done"<<endl;
+
+		setsize<<"sed s/\"#define R [0-9]*\"/\"#define R $R\"/ <$INPUT_FILE >$INPUT_FILE.tmp"<<endl;
+		setsize<<"sed s/\"#define C [0-9]*\"/\"#define C $C\"/ <$INPUT_FILE.tmp >$INPUT_FILE"<<endl;
+
+		setsize<<"rm $INPUT_FILE.tmp"<<endl;
+
+		setsize<<"make clean"<<endl;
+		setsize<<"make -j4"<<endl;
+
+		setsize<<"fi"<<endl;
+		
+		setsize.close();
+	}
+}*/
+
+void create_folder(int flag){	//0: local, 1: global
+	switch(flag){
+		case 1:
+			if(mkdir(GLOBAL_DIR,S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)==0){	//this will fail if local_dir already 
+				create_readme();							//exists (possible if player played
+				create_std_bosses();							//bossrush before).
+				//create_setsize();		
+			}
+			break;
+		default:
+		{
+			std::string local_dir=getenv("HOME");
+			local_dir+=RECORD_DIR;
+			if(mkdir(local_dir.c_str(),S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)==0){	//this will fail if local_dir already 
+				create_readme();							//exists (possible if player played
+				create_std_bosses();							//bossrush before).
+				//create_setsize();		
+			}
+		}
+	}
+}
+

+ 129 - 0
functions.hpp

@@ -0,0 +1,129 @@
+#ifndef _functions_
+#define _functions_
+
+//#includes here
+#include "definitions.hpp"
+#include "box.hpp"
+#include "player.hpp"
+#include "bullet.hpp"
+#include "enemy.hpp"
+#include "wall.hpp"
+#include "boss.hpp"
+
+class record
+{
+	public:
+	int score;
+	std::string nick;
+
+
+	bool operator==(record& record2)
+	{
+		if(score==record2.score && nick==record2.nick)
+			return true;
+		else return false;		
+	}
+	
+	
+	void print();
+	
+	void printwin(WINDOW*);
+
+	void print(std::ofstream& record);
+	
+};
+
+
+typedef std::list<bullet> b_list;
+typedef std::list<enemy> e_list;
+typedef std::vector<record> r_vec;
+typedef std::vector<wall> w_vec;
+
+void print_title();
+
+void print_catchphrase(std::string phrase);
+
+std::string choose_phrase();
+
+void print_info();
+
+void print_scores();
+
+int choose_level(double& shootr, int& refresh_t, boss &boss1, char& level,int* commands);
+
+void change_commands(int* commands);
+
+void load_enemies(e_list& enemies,int enemy_num);
+
+bool playagain(WINDOW*);
+
+bool gameover(player&,b_list&);
+
+void reset(player&, e_list &, boss&, b_list& bullets, b_list& bombs, w_vec& walls, b_list &powerups,r_list&,char level,int& chflag);
+
+bool enemyalive(e_list &);
+
+void refreshrecords(int,WINDOW*);
+
+void write_score(WINDOW*,int);
+
+void write_bosshp(WINDOW*,int,int,std::string);
+
+void pause_game(int&);
+
+void Victory(std::string,int,char,int);
+
+void Defeat(int);
+
+void choose_level_bossrush(double& shootr,int& refresh_t,char& level,int* commands);
+
+void resetbosses(boss* Bosses,boss& boss1,player& player1);
+
+void Victory_bossrush(std::string,int,char,int);
+
+void refreshrecords_bossrush(int,WINDOW*);
+
+void print_scores_bossrush();
+
+void get_SpecialMode(int,int&,boss&,e_list&,b_list&,b_list&,b_list&,r_list&);
+
+bool get_KonamiCode(int);
+
+void get_cheat(char,player&,e_list&,double&);
+
+void activate_combo(boss&,e_list&,b_list&,b_list&,b_list&,r_list&);
+
+void drop_powerup(int x,int y,b_list& powerups);
+
+void interactions(player& player1,b_list& bullets,b_list& bombs,e_list& enemies,w_vec& walls,b_list& powerups,r_list& rockets,boss& boss1,int& score);
+
+void draw(player& player1,b_list& bullets,b_list& bombs,e_list& enemies,w_vec& walls,b_list& powerups,r_list& rockets,boss& boss1, int& refresh_time, bool& keep_drawing,bool& kill_yourself);
+
+void create_readme();
+
+void create_std_bosses();
+
+//void create_setsize();
+
+void create_folder(int);
+
+// FORK FUNCTIONS (unused)
+/*void music();
+
+void kill_music(int);*/
+
+/*//PTHREAD FUNCTIONS
+void *pmusic(void *arg);
+
+void *pshoot_sound(void* arg);
+
+void *penshoot_sound(void* arg);
+
+void *pwin_theme(void *arg);
+
+void *plose_theme(void* arg);
+
+void pkill_music(pthread_t);*/
+
+
+#endif

+ 9 - 0
game_object.cpp

@@ -0,0 +1,9 @@
+#include "game_object.hpp"
+
+game_object::game_object(int X,int Y,int ID){
+	
+	x=X,
+	y=Y;
+	id=ID;
+
+}

+ 14 - 0
game_object.hpp

@@ -0,0 +1,14 @@
+#ifndef _gameobject_
+#define _gameobject_
+
+class game_object{
+	
+	public:
+	game_object() {}
+	game_object(int X, int Y, int ID);
+	
+	int x,y,id;
+
+};
+
+#endif

+ 344 - 0
invaders.cpp

@@ -0,0 +1,344 @@
+#include "bullet.hpp"
+#include "enemy.hpp"
+#include "player.hpp"
+#include "boss.hpp"
+#include "powerup.hpp"
+#include "definitions.hpp"
+#include "functions.hpp"
+#include "wall.hpp"
+#include <thread>
+
+std::mutex m_player;
+std::mutex m_enemies;
+std::mutex m_bombs;
+std::mutex m_bullets;
+std::mutex m_rockets;
+std::mutex m_pow;
+std::mutex m_boss;
+std::mutex m_walls;
+
+using std::cout;
+using std::endl; 
+using std::min;
+
+int main(int argc,char** argv)
+{
+	if(argc>1){
+		if(strcmp(argv[1],"--uber-debug")!=0 && strcmp(argv[1],"--info")!=0 && strcmp(argv[1],"--autowin")!=0){
+			cout<<"Usage: "<<argv[0]<<" [--info]"<<endl;
+			return 1;
+		}
+	
+		if(strcmp(argv[1],"--info")==0){
+			cout<<endl<<"Curses Invaders 4.4"<<endl;
+			cout<<endl<<"Game developed by Giacomo Parolini (jp) and Enrico Guiraud (blue) in years 2010-2013."<<endl;
+			cout<<"Source code is available under request to jp@lcm.mi.infn.it (it's quite ugly, I warn you ;-) )"<<endl;
+			cout<<"Report any bug to the same mail address."<<endl<<endl;
+			return 1;
+		}
+	}
+	
+  	typedef std::list<bullet> b_list;
+  	typedef std::list<enemy> e_list;
+  	typedef std::vector<wall> w_vec;
+  	typedef std::list<rocket> r_list;
+	srand(time(NULL));
+	
+	//OBJECTS INIZIALIZATION
+
+	player player1;						//player is automatically created in [C/2][R]
+	e_list enemies;						//vector of enemies
+	b_list bullets;                				//list of player's bullets
+	b_list bombs;						//list of enemies' bombs
+	b_list powerups;					//list of powerups
+	r_list rockets;						//list of rockets
+	int refresh_time;         				//how long the program waits before refreshing the screen
+	int chflag=0;						//cheat flag: 0=normal, 1=cheats allowed, 2=special mode activated, 3=both special mode and cheats.
+	boss boss1;
+	WINDOW *Score,*BossHP;
+	int commands[CMD_NUM]={'a','d','w','s','p',' ','l','m','q'};	//0:left,1:right,2:up,3:down,4:pause,5:shoot1,6:shoot2,7:mute,8:quit
+	
+	//PARAMETERS/UTILITIES
+	double shootrate;				  	//probability of an enemy shooting a bomb 
+	int command;						//keyboard input
+	int score=0;					   	//score: gain +100 when an enemy is destroyed and +50 when a bomb is destroyed
+	char level='1';						//difficulty level
+	//bool sound=false;					
+	
+	/*//PTHREAD STUFF
+	pthread_t thread[THREADS_NUM];
+	int bkgd_music;			//#0
+	int enshoot_sound;		//#1
+	int win_theme;			//#2
+	int lose_theme;			//#3
+	int shoot_sound;		//#4
+	
+	if(argc>1){		//./invaders -m/m/mute -> the game starts with no sounds.
+		if(strcmp(argv[1],"-s")==0 || strcmp(argv[1],"s")==0 || strcmp(argv[1],"sound")==0)
+			sound=true;
+		else{
+			cout<<"usage: "<<argv[0]<<" [-s]/[s]/[sound]"<<endl;
+			return -1;
+		}
+	}*/
+	
+	//NCURSES STUFF
+	initscr();
+	curs_set(0);
+	noecho();	
+	cbreak();
+	keypad(stdscr,TRUE);
+	start_color();
+	init_pair(0,COLOR_WHITE,COLOR_BLACK);
+	init_pair(1,COLOR_GREEN,COLOR_BLACK);	//PLAYER
+	init_pair(2,COLOR_RED,COLOR_BLACK);	//ENEMY
+	init_pair(3,COLOR_YELLOW,COLOR_BLACK);	//BULLETS-POWERUPS
+	init_pair(4,COLOR_MAGENTA,COLOR_BLACK);	//WALLS
+	init_pair(5,COLOR_CYAN,COLOR_BLACK);	//BOSS
+	init_pair(6,COLOR_BLUE,COLOR_BLACK);	//BOMBS
+	init_pair(7,COLOR_RED,COLOR_RED);	
+	init_pair(8,COLOR_GREEN,COLOR_GREEN);
+	init_pair(9,COLOR_BLACK,COLOR_GREEN);
+	
+	//////////PROGRAM START: creation of game objects and set of parameters
+	
+	WALLS_NUM=2;
+	
+	ENEMY_NUM=choose_level(shootrate, refresh_time, boss1, level, commands);     	//choose difficulty level and set game parameters and boss
+	player1.set_commands(commands);
+	erase();
+	
+	if(atoi(&level)==1) WALLS_NUM=3;
+	
+	
+	w_vec walls(WALLS_NUM);
+	
+	Score=newwin(3,10,R/3,C+3);
+	BossHP=newwin(3,15,R/3-3,C+3);
+	load_enemies(enemies,ENEMY_NUM);
+	
+	int i=0;
+	for(w_vec::iterator it=walls.begin(); it!=walls.end(); ++it, ++i)				//creating walls (in a quite symmetric pattern)
+		it->create((i+1)*(C/(3*walls.size()+1))+i*(2*C/(3*walls.size()+1)),2*R/3,(int)min(6,2*C/(3*(int)(walls.size())+1)),2,3);
+
+	bool kill_yourself = false;
+	bool keep_drawing = true;
+	std::thread t_draw(draw,std::ref(player1),std::ref(bullets),std::ref(bombs),std::ref(enemies),std::ref(walls),std::ref(powerups),std::ref(rockets),std::ref(boss1),std::ref(refresh_time),std::ref(keep_drawing),std::ref(kill_yourself));
+	
+	/////////ENTERING MAIN LOOP
+	
+	/*if(sound)
+		bkgd_music = pthread_create(&thread[0],NULL,pmusic,NULL); 	//executing background music in parallel thread*/
+	
+	if(argc>1){
+		if(strcmp(argv[1],"--uber-debug")==0){ player1.weaponclass=5; player1.weaponclassrkt=5; player1.rocketlauncher=true; player1.length=MAX_LENGTH; }
+		else if(strcmp(argv[1],"--autowin")==0){ Victory(boss1.name,score,level,0); endwin(); return 1; } 
+	}
+	
+	while(1)
+	{
+		napms(refresh_time);					//ncurses sleep function (ms)
+		timeout(0);
+	    	command = getch();
+	    	              
+	    	if(command!=ERR)                        		//READING INPUT
+	    		command = tolower(command);     
+		    		           
+	    	if(command == commands[8]){ 						//q = exit game
+	    		kill_yourself = true;
+	    		t_draw.join();
+	    		endwin();
+	    		//pkill_music(thread[0]);
+	    		cout<<lightgreen<<"Game exited correctly."<<none<<endl;
+	    		return 1;
+	    	}  
+
+	    	if(command == commands[4])
+	    		pause_game(chflag);							//p = pause game
+
+		//=====CHEATS================================================
+		
+	    	if(chflag==1 || chflag==3)
+			get_cheat(command,player1,enemies,shootrate);
+	    	if(chflag!=2 && chflag!=3)
+			get_SpecialMode(command,chflag,boss1,enemies,bullets,bombs,powerups,rockets);
+			
+		//======END CHEATS===============================================
+			    
+	    	if(command == commands[0] || command == KEY_LEFT || command == commands[1] || command == KEY_RIGHT ||
+		((chflag==1 || chflag==3) && (command == commands[2]|| command == KEY_UP || command == commands[3] || command == KEY_DOWN))){   		//a or d = move player (if cheats are triggered, also w and s)
+	    		//for(int i=player1.x;i<player1.x+player1.length;i++) //mvaddch(player1.y,i,' ');	
+	    		player1.next_pos(command);	
+	    	}	    
+		    		
+		if(command==commands[5] || command==commands[6]){                		//spacebar = shoot!
+			//if(sound) shoot_sound = pthread_create(&thread[4],NULL,pshoot_sound,NULL);
+			player1.shoot(bullets);
+			if(player1.rocketlauncher) player1.shootrkt(rockets);
+		}
+		
+		/*if(command==commands[7]){				//mute/unmute
+			if(sound) pkill_music(thread[0]);
+			else	bkgd_music = pthread_create(&thread[0],NULL,pmusic,NULL); 
+			sound=!sound;
+		}*/
+		
+		if(enemyalive(enemies))					//if there's at least one enemy alive:
+		{
+			int n_enemies=0;
+			e_list::const_iterator e_end = enemies.end();
+			
+			for(e_list::iterator it=enemies.begin(); it!=e_end; ++it)
+				if(it->alive) n_enemies++;				//counts alive enemies
+		
+			for(e_list::iterator it=enemies.begin(); it!=e_end; ++it)         
+			{
+				//mvaddch(it->y,it->x,' ');
+				it->next_pos();                                        //evaluate new positions
+				if(it->alive && (double)rand()/RAND_MAX<(shootrate*ENEMY_NUM/n_enemies)){     //try a bomb-dropping
+						//if(sound) shoot_sound = pthread_create(&thread[1],NULL,penshoot_sound,NULL);
+						it->shoot(bombs);
+				}
+			}
+		}
+		else boss1.alive = true;					//if no enemy is alive, boss spawns
+				
+		if(boss1.alive)							//if boss is alive, moves and shoots
+		{
+			for(int i=0;i<boss1.width;i++) //mvaddch(boss1.y,boss1.x+i,' ');
+			for(int j=0;j<boss1.height;j++){
+				//mvaddch(boss1.y+j,boss1.x,' ');
+				//mvaddch(boss1.y+j,boss1.x+boss1.width-1,' ');
+			}
+			boss1.next_pos();
+			if((double)rand()/RAND_MAX<shootrate*25.){		//boss's shootrate is 25 times the one of normal enemies
+				//if(sound) shoot_sound = pthread_create(&thread[1],NULL,penshoot_sound,NULL);
+				boss1.shoot(bombs);	
+			}
+		}
+		
+		if(!bullets.empty())						//evaluate new bullets' positions
+			for(b_list::iterator it=bullets.begin(); it!=bullets.end(); ++it){
+				//mvaddch(it->y,it->x,' ');
+				it->next_pos();
+			}
+				
+		bullets.unique();      					//remove duplicates of bullets (i.e. player can't shoot enemies)
+
+
+		if(!rockets.empty())						//evaluate new rockets' positions
+			for(r_list::iterator it=rockets.begin(); it!=rockets.end(); ++it){
+				//mvaddch(it->y,it->x,' ');
+				it->next_pos();
+			}
+
+		rockets.unique();
+
+		if(!bombs.empty())						//evaluate new bombs' positions
+			for(b_list::iterator it=bombs.begin(); it!=bombs.end(); ++it){
+				//mvaddch(it->y,it->x,' ');
+				it->next_pos();
+			}
+				  	
+		bombs.unique();						//remove duplicates of bombs
+
+		if(!powerups.empty())						//new powerups' positions
+			for(b_list::iterator it=powerups.begin(); it!=powerups.end(); ++it){
+				//mvaddch(it->y,it->x,' ');
+				it->next_pos();
+			}
+				
+		powerups.unique(); 	 //FIXME: THIS ONLY WORKS ON CONSECUTIVE ELEMENTS OF THE LIST!! we should at least sort powerups before calling unique()
+		
+		interactions(player1,bullets,bombs,enemies,walls,powerups,rockets,boss1,score);
+
+		///////ENDGAME CHECKS               
+		if(boss1.health<1)  					//YOU WON!!
+		{
+			/*if(sound){
+				pkill_music(thread[0]);	
+				win_theme = pthread_create(&thread[2],NULL,pwin_theme,NULL);
+			}*/
+				
+			Victory(boss1.name,score,level,chflag);
+			
+			WINDOW *replay;
+			
+			replay=newwin(3,25,26,20);
+			box(replay,ACS_VLINE,ACS_HLINE);
+		
+			if(playagain(replay))                           //playagain() returns true if player wants to play again, false otherwise
+			{
+				delwin(replay);
+				timeout(500);
+				score=0;
+				erase();
+				refresh();
+				choose_level(shootrate, refresh_time, boss1, level, commands);
+				reset(player1, enemies, boss1, bullets, bombs, walls, powerups,rockets, level,chflag); // reset box, player, enemy and deletes all bullets and bombs
+				erase();
+				refresh();
+				continue;  
+			}
+			else { 
+				kill_yourself = true;
+				t_draw.join();
+				endwin();
+				cout<<lightgreen<<"Game exited correctly."<<none<<endl;
+				return 0;
+			}	
+		}
+				
+			
+		if(gameover(player1,bombs))
+		{
+			keep_drawing = false;
+				
+			Defeat(score);
+			
+			WINDOW* replay;
+		
+			replay=newwin(3,25,17,20);
+			box(replay,ACS_VLINE,ACS_HLINE);
+			
+			if(playagain(replay))                                        //playagain() returns true if player wants to play again, false otherwise
+			{
+				delwin(replay);
+				timeout(500);
+				score=0;
+				erase();
+				refresh();
+				choose_level(shootrate, refresh_time, boss1, level, commands);
+				reset(player1, enemies, boss1, bullets, bombs, walls, powerups,rockets,level,chflag);       // reset box, player, enemy and delete all bullets and bombs
+				keep_drawing = true;
+				erase();
+				refresh();
+				continue;  
+			}
+			else {
+				kill_yourself = true;
+				t_draw.join();
+				endwin();
+				cout<<lightgreen<<"Game exited correctly."<<none<<endl;
+				return 0;
+			}
+		}
+		
+		write_score(Score,score);
+	
+		if(boss1.alive){
+			write_bosshp(BossHP,boss1.health,boss1.healthmax,boss1.name);
+			wrefresh(BossHP);
+		}
+		
+		wrefresh(Score);
+		refresh();
+	}  
+////////END OF MAIN LOOP
+
+	endwin();
+	
+	return -1;  //program never really reaches here, but compiler is happy
+}
+
+

+ 324 - 0
invaders_fork.cpp

@@ -0,0 +1,324 @@
+#include "bullet.hpp"
+#include "enemy.hpp"
+#include "player.hpp"
+#include "box.hpp"
+#include "boss.hpp"
+#include "powerup.hpp"
+#include "definitions.hpp"
+#include "functions.hpp"
+#include "wall.hpp"
+
+using std::cout;
+using std::endl; 
+using std::min;
+
+int main()
+{
+	
+  	typedef std::list<bullet> b_list;
+  	typedef std::list<enemy> e_list;
+  	typedef std::vector<wall> w_vec;
+	srand(time(NULL));
+	
+	//OBJECTS INIZIALIZATION
+	Box box1;
+	player player1;						//player is automatically created in [C/2][R]
+	e_list enemies;						//vector of enemies
+	b_list bullets;                				//list of player's bullets
+	b_list bombs;						//list of enemies' bombs
+	b_list powerups;					//list of powerups
+	int refresh_time;          				//how long the program waits before refreshing the screen
+	int chflag=0;						//cheat flag: 0=normal, 1=cheats allowed, 2=special mode activated, 3=both special mode and cheats.
+	boss boss1;
+	WINDOW *Score,*BossHP;
+	
+	//PARAMETERS/UTILITIES
+	double shootrate;				  	//probability of an enemy shooting a bomb 
+	int command;						//keyboard input
+	int score=0;					   	//score: gain +100 when an enemy is destroyed and +50 when a bomb is destroyed
+	char level='1';	
+	bool sound=true;					//difficulty level
+
+
+	//NCURSES STUFF
+	initscr();
+	curs_set(0);
+	noecho();	
+	cbreak();
+	keypad(stdscr,TRUE);
+	start_color();
+	init_pair(0,COLOR_WHITE,COLOR_BLACK);
+	init_pair(1,COLOR_GREEN,COLOR_BLACK);	//PLAYER
+	init_pair(2,COLOR_RED,COLOR_BLACK);	//ENEMY
+	init_pair(3,COLOR_YELLOW,COLOR_BLACK);	//BULLETS-POWERUPS
+	init_pair(4,COLOR_MAGENTA,COLOR_BLACK);	//WALLS
+	init_pair(5,COLOR_CYAN,COLOR_BLACK);	//BOSS
+	init_pair(6,COLOR_BLUE,COLOR_BLACK);	//BOMBS
+	init_pair(7,COLOR_RED,COLOR_RED);
+	init_pair(8,COLOR_GREEN,COLOR_GREEN);
+	
+	//////////PROGRAM START: creation of game objects and set of parameters
+		
+	WALLS_NUM=2;
+	
+	ENEMY_NUM=choose_level(shootrate, refresh_time, boss1, level);     	//choose difficulty level and set game parameters and boss
+	
+	erase();
+	
+	if(atoi(&level)==1) WALLS_NUM=3;
+	
+	w_vec walls(WALLS_NUM);
+	
+	Score=newwin(3,10,R/3,C+3);
+	BossHP=newwin(3,15,R/3-3,C+3);
+	load_enemies(enemies,ENEMY_NUM);
+	
+	int i=0;
+	for(w_vec::iterator it=walls.begin(); it!=walls.end(); ++it, ++i)				//creating walls (in a quite symmetric pattern)
+		it->create((i+1)*(C/(3*WALLS_NUM+1))+i*(2*C/(3*WALLS_NUM+1)),2*R/3,(int)min(6,2*C/(3*WALLS_NUM+1)),2,3);
+
+	box1.refresh(bullets, bombs, enemies, player1, score, boss1, walls, powerups);   //matrix is loaded for the first time
+
+	
+	/////////ENTERING MAIN LOOP
+	
+	int childPID0=fork();
+	if(childPID0==0 && sound){
+		music();
+		return 0;
+	}
+	while(1)
+	{
+		napms(refresh_time);					//ncurses sleep function (ms)
+		timeout(0);
+	    	command = getch();
+	    	              
+	    	if(command!=ERR)                        		//READING INPUT
+	    		command = tolower(command);     
+		    		           
+	    	if(command == 'q'){ 						//q = exit game
+	    		endwin();
+	    		kill_music(childPID0);
+	    		cout<<lightgreen<<"Game exited correctly."<<none<<endl;
+	    		return 1;
+	    	}  
+
+	    	if(command == 'p')
+	    		pause_game(chflag);						//p = pause game
+
+	    	if(chflag==1 || chflag==3){								//cheats
+	    		if(command == '+' && player1.weaponclass<5) player1.weaponclass++;	//increase weaponclass
+	    		if(command == '\\' && player1.weaponclass>1) player1.weaponclass--;	//decrease weaponclass
+	    		if(command == '-' && player1.length>2){					//decrease size
+				mvaddch(player1.y,player1.x+player1.length-1,' ');
+	    			player1.length--;
+	    		}
+	    		if(command == '\'' && player1.length<20) player1.length++;		//increase size
+			if(command == 'n')							//nuke enemies
+				for(e_list::iterator it=enemies.begin();it!=enemies.end();it++){
+					it->alive=false;
+					mvaddch(it->y,it->x,' ');
+				}
+	    	}
+
+	    	if(chflag!=2 && chflag!=3)
+			get_KonamiCode(command,chflag,boss1,enemies,bullets,bombs,powerups,box1);
+			    
+	    	if(command == 'a' || command == KEY_LEFT || command == 'd' || command == KEY_RIGHT ||
+		((command == 'w'|| command == KEY_UP || command == 's' || command == KEY_DOWN) &&
+		(chflag==1 || chflag==3))){   	//a or d = move player (if cheats are triggered, also w and s)
+	    		for(int i=player1.x;i<player1.x+player1.length;i++) mvaddch(player1.y,i,' ');	
+	    		player1.next_pos(command);	
+	    	}	    
+		    		
+		if(command==' '){                		//spacebar = shoot!
+			if(sound){
+				int childPID=fork();
+				if(childPID==0){
+					system("beep -f 1000 -l 30 -n -f 850 -l 30");
+					return 0;
+				}
+			}
+			player1.shoot(bullets);
+		}
+		
+		if(command=='m'){				//mute/unmute
+			if(sound) kill_music(childPID0);
+			else{
+				childPID0=fork();
+				if(childPID0==0){
+					music();
+					return 0;
+				}
+			}
+			sound=!sound;
+		}
+		
+		if(enemyalive(enemies))					//if there's at least one enemy alive:
+		{
+			int n_enemies=0;
+			e_list::const_iterator e_end = enemies.end();
+			
+			for(e_list::iterator it=enemies.begin(); it!=e_end; ++it)
+				if(it->alive) n_enemies++;				//counts alive enemies
+		
+			for(e_list::iterator it=enemies.begin(); it!=e_end; ++it)         
+			{
+				mvaddch(it->y,it->x,' ');
+				it->next_pos();                                        //evaluate new positions
+				if(it->alive && (double)rand()/RAND_MAX<(shootrate*ENEMY_NUM/n_enemies)){     //try a bomb-dropping
+						if(sound){
+							int childPID=fork();
+							if(childPID==0){
+								system("beep -f 1500 -l 30 -n -f 1000 -l 30");
+								return 0;
+							}
+						}
+						it->shoot(bombs);
+				}
+			}
+		}
+		else boss1.alive = true;					//if no enemy is alive, boss spawns
+				
+		if(boss1.alive)							//if boss is alive, moves and shoots
+		{
+			for(int i=0;i<boss1.width;i++) mvaddch(boss1.y,boss1.x+i,' ');
+			for(int j=0;j<boss1.height;j++){
+				mvaddch(boss1.y+j,boss1.x,' ');
+				mvaddch(boss1.y+j,boss1.x+boss1.width-1,' ');
+			}
+			boss1.next_pos();
+			if((double)rand()/RAND_MAX<shootrate*25.){		//boss's shootrate is 25 times the one of normal enemies
+				if(sound){
+					int childPID=fork();
+					if(childPID==0){
+						system("beep -f 1500 -l 30 -n -f 1000 -l 30");
+						return 0;
+					}
+				}
+				boss1.shoot(bombs);	
+			}
+		}
+		
+		if(!bullets.empty())						//evaluate new bullets' positions
+			for(b_list::iterator it=bullets.begin(); it!=bullets.end(); ++it){
+				mvaddch(it->y,it->x,' ');
+				it->next_pos();
+			}
+				
+		bullets.unique();      					//remove duplicates of bullets (i.e. player can't shoot enemies)
+
+		if(!bombs.empty())						//evaluate new bombs' positions
+			for(b_list::iterator it=bombs.begin(); it!=bombs.end(); ++it){
+				mvaddch(it->y,it->x,' ');
+				it->next_pos();
+			}
+				  	
+		bombs.unique();						//remove duplicates of bombs
+
+		if(!powerups.empty())						//new powerups' positions
+			for(b_list::iterator it=powerups.begin(); it!=powerups.end(); ++it){
+				mvaddch(it->y,it->x,' ');
+				it->next_pos();
+			}
+				
+		powerups.unique(); 	 //FIXME: THIS ONLY WORKS ON CONSECUTIVE ELEMENTS OF THE LIST!! we should at least sort powerups before calling unique()
+		
+		box1.refresh(bullets, bombs, enemies, player1, score, boss1, walls, powerups);		
+
+		///////ENDGAME CHECKS               
+		if(boss1.health<1)  					//YOU WON!!
+		{
+			if(sound){
+				kill_music(childPID0);
+				int childPID=fork();
+				if(childPID==0){
+					system("beep -f 1000 -l 150 -n -f 800 -l 150 -n -f 1000 -l 150 -n -f 1500 -l 600");
+					return 0;
+				}
+			}
+				
+			Victory(boss1.name,score,level,chflag);
+			
+			WINDOW *replay;
+			
+			replay=newwin(3,25,26,20);
+			box(replay,ACS_VLINE,ACS_HLINE);
+		
+			if(playagain(replay))                           //playagain() returns true if player wants to play again, false otherwise
+			{
+				delwin(replay);
+				timeout(500);
+				score=0;
+				erase();
+				refresh();
+				choose_level(shootrate, refresh_time, boss1, level);
+				reset(box1, player1, enemies, boss1, bullets, bombs, walls, powerups, level,chflag); // reset box, player, enemy and deletes all bullets and bombs
+				erase();
+				refresh();
+				continue;  
+			}
+			else { 
+				endwin();
+				cout<<lightgreen<<"Game exited correctly."<<none<<endl;
+				return 0;
+			}	
+		}
+				
+			
+		if(gameover(box1,player1))
+		{	
+			if(sound){	
+				kill_music(childPID0);
+				int childPID=fork();
+				if(childPID==0){
+					system("beep -f 700 -l 150 -n -f 585 -l 150 -n -f 550 -l 150 -n -f 520 -l 600");
+					return 0;
+				}
+			}
+				
+			Defeat(score);
+			
+			WINDOW* replay;
+		
+			replay=newwin(3,25,17,20);
+			box(replay,ACS_VLINE,ACS_HLINE);
+			
+			if(playagain(replay))                                        //playagain() returns true if player wants to play again, false otherwise
+			{
+				delwin(replay);
+				timeout(500);
+				score=0;
+				erase();
+				refresh();
+				choose_level(shootrate, refresh_time, boss1, level);
+				reset(box1, player1, enemies, boss1, bullets, bombs, walls, powerups, level,chflag);       // reset box, player, enemy and delete all bullets and bombs
+				erase();
+				refresh();
+				continue;  
+			}
+			else { 
+				endwin();
+				cout<<lightgreen<<"Game exited correctly."<<none<<endl;
+				return 0;
+			}		
+		}
+		
+		write_score(Score,score);
+	
+		if(boss1.alive){
+			write_bosshp(BossHP,boss1.health,boss1.healthmax,boss1.name);
+			wrefresh(BossHP);
+		}
+		
+		wrefresh(Score);
+		refresh();
+	}  
+////////END OF MAIN LOOP
+
+	endwin();
+	
+	return -1;  //program never really reaches here, but compiler is happy
+}
+
+

+ 10 - 0
latest.dat

@@ -0,0 +1,10 @@
+- fixato un errore in interactions che freezava il gioco (colpa mia!)
+- finito il makeover di draw...il risultato è da brivido. gelido. lungo la schiena.
+- aggiunto napms alla fine del ciclo di draw..la situazione è decisamente migliore
+- il giocatore continua a muoversi in modo incomprensibile anche resettando command a ogni ciclo
+- incluso ncurses in player.cpp nella speranza di debuggarne i movimenti inconsulti
+- riga 170 di invaders.cpp -.-" (fixatI i movimenti inconsulti)
+
+BUG:
+- dopo aver sconfitto il boss, non viene pulito lo schermo prima di sovrascrivere il main menu
+- c'è qualche problema con i rocket, fanno freezare il gioco quando colpiscono un boss (dovrebbe essere fixato)

+ 6 - 0
maderna.dat

@@ -0,0 +1,6 @@
+  99999  
+ C \ / D 
+C  0 0  D
+C_  ^  _D
+  | J |  
+   \_/   

+ 6 - 0
maero.dat

@@ -0,0 +1,6 @@
+  MMMMMMM  
+ M       M 
+|  == ==  |
+c    L    D
+ MMM   MMM 
+  MMMMMMM  

+ 91 - 0
makefile

@@ -0,0 +1,91 @@
+#MACROS
+
+OPT := -O3
+
+DEBUG := -ggdb
+
+CC := g++ -std=c++0x
+
+WARNINGS := -Wall
+
+EDITOR := gedit
+
+CURSES := -lncurses
+
+THREADS := -pthread
+
+OPTIONS := $(CURSES) $(THREADS)
+
+
+.PHONY: open, opencpp, openhpp, clean, cleanall, remake
+
+#TARGETS
+
+all: invaders bossrush
+
+invaders: game_object.o bullet.o enemy.o player.o functions.o pic.o body.o boss.o wall.o powerup.o rocket.o invaders.o
+	$(CC) $(DEBUG) $^ -o $@ $(OPTIONS)
+bossrush: game_object.o bullet.o enemy.o player.o functions.o pic.o body.o boss.o wall.o powerup.o rocket.o bossrush.o
+	$(CC) $(DEBUG) $^ -o $@ $(OPTIONS) 
+
+invaders.o: invaders.cpp bullet.hpp enemy.hpp player.hpp box.hpp rocket.hpp definitions.hpp functions.hpp
+	$(CC) $(DEBUG) -c $<
+	
+bossrush.o: bossrush.cpp bullet.hpp enemy.hpp player.hpp box.hpp rocket.hpp definitions.hpp functions.hpp
+	$(CC) $(DEBUG) -c $<
+
+#box.o: box.cpp box.hpp definitions.hpp player.hpp rocket.hpp bullet.hpp enemy.hpp boss.hpp
+#	$(CC) $(DEBUG) -c $<
+
+game_object.o: game_object.cpp game_object.hpp
+	$(CC) $(DEBUG) -c $<
+
+bullet.o: bullet.cpp bullet.hpp game_object.hpp
+	$(CC) $(DEBUG) -c $<
+	
+enemy.o: enemy.cpp enemy.hpp game_object.hpp bullet.hpp definitions.hpp
+	$(CC) $(DEBUG) -c $<
+	
+player.o: player.cpp player.hpp game_object.hpp bullet.hpp rocket.hpp definitions.hpp
+	$(CC) $(DEBUG) -c $<
+
+functions.o: functions.cpp functions.hpp definitions.hpp box.hpp player.hpp bullet.hpp enemy.hpp wall.hpp boss.hpp
+	$(CC) $(DEBUG) -c $<
+
+body.o: body.cpp body.hpp
+	$(CC) $(DEBUG) -c $<
+	
+pic.o: pic.cpp body.hpp pic.hpp definitions.hpp
+	$(CC) $(DEBUG) -c $<
+
+boss.o: boss.cpp boss.hpp pic.hpp
+	$(CC) $(DEBUG) -c $<
+
+wall.o: wall.cpp wall.hpp game_object.hpp
+	$(CC) $(DEBUG) -c $<
+	
+powerup.o: powerup.cpp powerup.hpp bullet.hpp
+	$(CC) $(DEBUG) -c $<
+
+rocket.o: rocket.cpp rocket.hpp bullet.hpp definitions.hpp
+	$(CC) $(DEBUG) -c $<
+
+#UTILITIES
+
+open:  
+	$(EDITOR) *.cpp *.hpp makefile &
+
+openhpp:
+	$(EDITOR) *.hpp&
+
+opencpp:
+	$(EDITOR) *.cpp&
+
+clean:
+	rm -f *~ *.o
+
+cleanall: clean
+	rm -f invaders
+	rm -f bossrush
+
+remake: clean invaders bossrush

+ 8 - 0
myboss.dat.old

@@ -0,0 +1,8 @@
+ertyuertyu
+ertyuertyu
+ertyuertyu
+ertyuertyu
+ertyuertyu
+ertyuertyu
+ertyuertyu
+ertyuertyu

+ 44 - 0
notes.dat

@@ -0,0 +1,44 @@
+THINGS TO LEARN:
+- is there a better way to implement kbhit()?
+- is there a way to flush the input stream at the beginning of every cycle? (at present player keeps moving even if keys are not pressed)
+
+##################################################################################################
+
+IDEAS AND DOUBTS:
+- what if we gave int speed to every game_object?
+- what if position (and speed) was not an integer but a double? (we could cast it to int when we upload the matrix)
+- we could keep the same refreshing rate and change the speed of enemies and bullets instead...low refresh_rate makes it horrible to play
+- bomb_list still to be implemented...
+- if picture was a std::vector<std::vector<char>> we would not have to delete it!
+- why does box destroy things? it's not its job! destroy() should be independent
+- some methods, some data members should be made private or protected..maybe..
+- we could remove dead enemies from the list so that boss appears if enemies.empty()==true ( no need to use enemyalive() ) <- tried and re-tried with remove_if but just failed and re-failed...
+- box::draw() should not have arguments. everything it needs should be passed through box::refresh()
+- dead enemies should not move
+- box.draw() should be called when new positions have been evaluated and before bullets and bombs are killed. this way players 
+  can see when they're hit or hit something. we could draw an "*" where explosions take place
+- capitals should be allowed, it's really bad when you hit caps lock while playing and player stops moving...
+- toupper(command) and fflush(stdin) could be solutions to bugs 1 and 4 
+- shots are not centered!! (because player is now 8 spaces long)
+- why is choose_level()'s variable "level" a char? why not just an integer?
+
+##################################################################################################
+
+KNOWN BUGS:
+- keeping the same command pressed for some time makes it impossible to use commands for a while
+  (maybe fflush() can solve this????)
+- box's boundaries shift left when several objects are drawn in the same spot
+
+-MADERNA DOES NOT BEHAVE CORRECTLY! There is a fatal bug when she spawns that makes all the boundaries to shift! (only the first line of the boss actually moves, the rest remains stuck)!
+
+##################################################################################################
+
+PROBLEMS/BUGS FIXED IN V 4.1:
+
+- answering choose_level() with a character instead of a number makes it so that boss does not reset
+  (every input should be checked!!)  <- solved with a simple input check.
+- if caps lock is on, player cannot move (maybe toupper() can solve this???)  <- solved with tolower().
+- really long nicknames can be entered  <- solved with string::resize().
+- shootrate should increase as enemies die, otherwise there's very small chance that a single enemy will shoot. <- solved by substituting "rand()/RAND_MAX < shootrate" with "rand()/RAND_MAX < shootrate*ENEMY_NUM/n_alive_enemies", which grants that at every loop the amount of bullets shot remains constant and equal to shootrate*ENEMY_NUM.
+
+Here a brief explanation: if B is the amount of bombs we want the enemies to shoot per loop (and it is constant), B = p*n, where p is the probability of a single (alive) enemy to shoot a bomb and n is the number of living enemies. Since we want B to dipend from ENEMY_NUM (more enemies initially = more bombs are shot) B shall be also B = N*c, where N is ENEMY_NUM and c is a percentage (0<=c<=1); for example, if c=0.25, one quarter of the initial enemies will shoot at every loop. By imposing B=constant, p becomes N*c/n, therefore when n decreases (enemies die), p increases so that B remains the same (more than 1/4 of alive enemies will shoot, providing always B bombs per loop).

+ 12 - 0
objectsIDs.txt

@@ -0,0 +1,12 @@
+Lest we forget:
+
+1   = PLAYER
+2   = BULLET
+4   = ENEMY
+8   = BOMB
+16  = BOSS
+32  = WALL
+64  = POWERUP+
+128 = POWERUP-
+256 = ROCKET
+512 = POWERUPX

+ 0 - 0
palombo


+ 5 - 0
palombo.dat

@@ -0,0 +1,5 @@
+  _______  
+ W _ _ _ W 
+|_|o| |o|_|
+c    c    P
+ \__NNN__/ 

+ 5 - 0
palombo.dat.old

@@ -0,0 +1,5 @@
+  _______  
+ W _ _ _ W 
+|_|o| |o|_|
+c    c    P
+ \__NNN__/ 

+ 58 - 0
pic.cpp

@@ -0,0 +1,58 @@
+#include "pic.hpp"
+
+//char** picture;
+
+pic::pic(int w, int h) : body(w,h){ 
+	picture = new char* [height];
+	for(int i=0; i<height; ++i)
+		picture[i] = new char[w];
+	clear();
+} 
+
+
+pic::~pic()
+{
+	delete [] picture;
+}
+
+
+
+void pic::loadpicture(const char* nome)
+{
+	ifstream input(nome);
+	char c;
+	if(!nome){
+		input.close();
+	}
+	else{
+		for(int i=0; i<height; i++)			//rows
+			for(int j=0; j<width; j++){    		//columns
+	 				c = input.get();       // get character from file
+	 				if(c!='\n') picture[i][j]=c;
+	 				if(c=='\n') j--;
+	 		}
+				
+		input.close();
+	}
+	
+}
+
+
+void pic::clear(){
+	for(int i=0; i<height; i++)
+		for(int j=0; j<width; j++)
+			picture[i][j]=' ';
+}
+
+void pic::set_values(int W, int H){
+	width=W;
+	height=H;
+}
+
+void pic::print(){
+	for(int i=0; i<height; i++){
+		for(int j=0; j<width; j++)
+			cout << picture[i][j];
+		cout << endl;
+	}
+}

+ 25 - 0
pic.hpp

@@ -0,0 +1,25 @@
+#ifndef _pic_hpp
+#define _pic_hpp
+
+#include "body.hpp"
+#include <fstream>
+#include <iostream>
+
+using std::ifstream; using std::ios;
+using std::cout; using std::endl;
+
+class pic : public body
+{
+	public:
+	pic() : body() { clear(); }  //carica picture piena di spazi (??????? crea un body di dimensioni indefinite!!)
+	pic(int w,int h);
+	~pic();
+	
+	char** picture;		
+	void loadpicture(const char*);	//loads picture from a file
+	void clear();		               //deletes picture
+	void set_values(int W, int H);	//sets coordinates of body
+	void print();
+};
+
+#endif

+ 213 - 0
player.cpp

@@ -0,0 +1,213 @@
+#include "player.hpp"
+
+
+player::player() : game_object(C/2, R-1, 1)
+{ 
+	length=8;
+	weaponclass=0; 
+	weaponclassrkt=0;
+	rocketlauncher=FALSE;
+	commands[0]='a';	//left
+	commands[1]='d';	//right
+	commands[2]='w';	//up
+	commands[3]='s';	//down
+	godmode=false;
+}
+
+player::player(int Length) : game_object(C/2, R, 1)
+{
+	length=(Length<2?2:(Length>20?20:Length));
+	weaponclass=0;
+	weaponclassrkt=0;
+	rocketlauncher=FALSE;
+	commands[0]='a';	//left
+	commands[1]='d';	//right
+	commands[2]='w';	//up
+	commands[3]='s';	//down
+	godmode=false;
+}
+
+void player::set_commands(int* _commands){
+	for(int i=0;i<4;i++)
+		commands[i]=_commands[i];
+}
+
+void player::next_pos(int command)  
+{
+	if((command==commands[0] || command==KEY_LEFT) && x>0) x-=2;
+	if((command==commands[1] || command==KEY_RIGHT) && x<C-length) x+=2;
+	if((command==commands[2] || command==KEY_UP) && y>0) y--;		
+	if((command==commands[3] || command==KEY_DOWN) && y<R-1) y++;
+}
+
+void player::shoot(std::list<bullet> & bullets)  
+{
+	static int thiscannon=0;
+	
+		if(weaponclass==0){
+			if(thiscannon)
+			{
+				bullet new_bullet(x+(int)(length/2.),y,2);
+				bullets.push_back(new_bullet);
+			}
+			else
+			{
+				bullet new_bullet(x+(int)(length/2.)-1,y,2);
+				bullets.push_back(new_bullet);
+			}
+			thiscannon= ~thiscannon;
+		}
+		
+		else if(weaponclass==1){
+			bullet new_bullet1(x+(int)(length/2.),y,2);
+			bullets.push_back(new_bullet1);
+			bullet new_bullet2(x+(int)(length/2.)-1,y,2);
+			bullets.push_back(new_bullet2);
+		}
+		
+		else if(weaponclass==2){
+			if(thiscannon)
+			{
+				bullet new_bullet(x+(int)(length/2.),y,2);
+				bullets.push_back(new_bullet);
+			}
+			else
+			{
+				bullet new_bullet(x+(int)(length/2.)-1,y,2);
+				bullets.push_back(new_bullet);
+			}
+			thiscannon= ~thiscannon;
+			if(length>2){
+				bullet new_bullet1(x+1,y,2);
+				bullets.push_back(new_bullet1);
+				bullet new_bullet3(x+(length-2>(int)(length/2.)?length-2:((int)(length/2.)+1>length?length-1:(int)(length/2.)+1)),y,2);
+				bullets.push_back(new_bullet3);
+			}
+		}
+		
+		else if(weaponclass==3){
+			bullet new_bullet(x+(int)(length/2.),y,2);
+			bullets.push_back(new_bullet);
+			bullet new_bullet2(x+(int)(length/2.)-1,y,2);
+			bullets.push_back(new_bullet2);
+			if(length>2){
+				bullet new_bullet1(x+1,y,2);
+				bullets.push_back(new_bullet1);
+				bullet new_bullet3(x+(length-2>(int)(length/2.)?length-2:((int)(length/2.)+1>length?length-1:(int)(length/2.)+1)),y,2);
+				bullets.push_back(new_bullet3);
+			}
+		}
+		
+		else if(weaponclass==4){
+			bullet new_bullet4(x+(int)(length/2.)-1,y,2);
+			bullets.push_back(new_bullet4);
+			bullet new_bullet5(x+(int)(length/2.),y,2);
+			bullets.push_back(new_bullet5);
+			if(length>2){
+				bullet new_bullet6(x+(int)(length/2.)+1,y,2);
+				bullets.push_back(new_bullet6);
+				bullet new_bullet2(x+(length-2>(int)(length/2.)+1?length-2:length-1),y,2);
+				bullets.push_back(new_bullet2);
+				bullet new_bullet3(x+(1<(int)(length/2.)-2?1:0),y,2);
+				bullets.push_back(new_bullet3);
+			}
+			if(length>4){
+				bullet new_bullet7(x+(int)(length/2.)-2,y,2);
+				bullets.push_back(new_bullet7);
+			}
+		}
+		
+		else if(weaponclass==5){
+			for(int i=0;i<length;i++){
+				bullet new_bullet(x+i,y,2);
+				bullets.push_back(new_bullet);
+			}
+		}
+
+
+}
+
+void player::shootrkt(std::list<rocket>& rockets)
+{
+	static int thiscannon=0;
+	
+		if(weaponclassrkt==0){
+			if(thiscannon)
+			{
+				rocket new_rocket(x+(int)(length/2.),y,1);
+				rockets.push_back(new_rocket);
+			}
+			else
+			{
+				rocket new_rocket(x+(int)(length/2.)-1,y,-1);
+				rockets.push_back(new_rocket);
+			}
+			thiscannon= ~thiscannon;
+		}
+		
+		else if(weaponclassrkt==1){
+			rocket new_rocket1(x+(int)(length/2.),y,1);
+			rockets.push_back(new_rocket1);
+			rocket new_rocket2(x+(int)(length/2.)-1,y,-1);
+			rockets.push_back(new_rocket2);
+		}
+		
+		else if(weaponclassrkt==2){
+			if(thiscannon)
+			{
+				rocket new_rocket(x+(int)(length/2.),y,1);
+				rockets.push_back(new_rocket);
+			}
+			else
+			{
+				rocket new_rocket(x+(int)(length/2.)-1,y,-1);
+				rockets.push_back(new_rocket);
+			}
+			thiscannon= ~thiscannon;
+			if(length>2){
+				rocket new_rocket1(x+1,y,1);
+				rockets.push_back(new_rocket1);
+				rocket new_rocket3(x+(length-2>(int)(length/2.)?length-2:((int)(length/2.)+1>length?length-1:(int)(length/2.)+1)),y,-1);
+				rockets.push_back(new_rocket3);
+			}
+		}
+		
+		else if(weaponclassrkt==3){
+			rocket new_rocket(x+(int)(length/2.),y,1);
+			rockets.push_back(new_rocket);
+			rocket new_rocket2(x+(int)(length/2.)-1,y,-1);
+			rockets.push_back(new_rocket2);
+			if(length>2){
+				rocket new_rocket1(x+1,y,1);
+				rockets.push_back(new_rocket1);
+				rocket new_rocket3(x+(length-2>(int)(length/2.)?length-2:((int)(length/2.)+1>length?length-1:(int)(length/2.)+1)),y,-1);
+				rockets.push_back(new_rocket3);
+			}
+		}
+		
+		else if(weaponclassrkt==4){
+			rocket new_rocket4(x+(int)(length/2.)-1,y,1);
+			rockets.push_back(new_rocket4);
+			rocket new_rocket5(x+(int)(length/2.),y,-1);
+			rockets.push_back(new_rocket5);
+			if(length>2){
+				rocket new_rocket6(x+(int)(length/2.)+1,y,1);
+				rockets.push_back(new_rocket6);
+				rocket new_rocket2(x+(length-2>(int)(length/2.)+1?length-2:length-1),y,-1);
+				rockets.push_back(new_rocket2);
+				rocket new_rocket3(x+(1<(int)(length/2.)-2?1:0),y,1);
+				rockets.push_back(new_rocket3);
+			}
+			if(length>4){
+				rocket new_rocket7(x+(int)(length/2.)-2,y,-1);
+				rockets.push_back(new_rocket7);
+			}
+		}
+		
+		else if(weaponclassrkt==5){
+			for(int i=0;i<length;i++){
+				rocket new_rocket(x+i,y,pow(-1.,(double)i));
+				rockets.push_back(new_rocket);
+			}
+		}
+}

+ 29 - 0
player.hpp

@@ -0,0 +1,29 @@
+#ifndef _player_
+#define _player_
+
+#include "game_object.hpp"
+#include "rocket.hpp"
+#include "definitions.hpp"
+#include <list>
+
+class player : public game_object
+{	
+	public:
+	player();					 //default constructor: creates a 8-long player in C/2,R
+	player(int);		        		//user-defined length constructor
+	~player() {}
+	
+	void next_pos(int command);   		//moves player according to command (WASD or arrow keys)
+	void shoot(std::list<bullet> &);           	//adds a new bullet to the list
+	void shootrkt(std::list<rocket> &);
+	void set_commands(int* _commands);
+	int weaponclass;
+	int weaponclassrkt;
+	int length;
+	bool rocketlauncher;		//when rocketlauncher is TRUE, player can shoot rockets.
+	int commands[4];
+	bool godmode;
+
+};
+
+#endif

+ 5 - 0
powerup.cpp

@@ -0,0 +1,5 @@
+#include "powerup.hpp"
+
+powerup::powerup(int x,int y):bullet(x,y,64){}
+
+powerup::powerup(int x,int y,int ID):bullet(x,y,ID){}

+ 12 - 0
powerup.hpp

@@ -0,0 +1,12 @@
+#ifndef _powerup_
+#define _powerup_
+
+#include "bullet.hpp"
+
+class powerup:public bullet{
+	public:
+	powerup(int x,int y);
+	powerup(int x,int y,int ID);
+};
+
+#endif

+ 45 - 0
records.dat

@@ -0,0 +1,45 @@
+erc.. 	26400
+jack. 	25150
+jack. 	24650
+blue. 	19900
+blue. 	19500
+jack. 	18400
+jack. 	18300
+lupy. 	18250
+jack. 	17800
+i.... 	17000
+jack. 	16200
+jack. 	15250
+ano.. 	14300
+blue. 	13800
+jack. 	13800
+jack. 	13600
+lupy. 	13500
+jack. 	13350
+lupy. 	13000
+jack. 	12700
+lupy. 	12650
+jack. 	12600
+jack. 	12100
+jack. 	12050
+jack. 	11950
+blue. 	11300
+jack. 	11300
+jack. 	11150
+erc.. 	11100
+jack. 	10950
+jack. 	10950
+jack. 	9800
+blue. 	9700
+blue. 	9700
+blue. 	9400
+jack. 	8750
+jackù 	8250
+jack. 	6000
+jack. 	5800
+jack. 	5400
+jack. 	5350
+lol.. 	5100
+jack. 	4850
+jack. 	4750
+a.... 	1700

+ 2 - 0
records_bossrush.dat

@@ -0,0 +1,2 @@
+jack. 	6650
+jack. 	6600

+ 18 - 0
rocket.cpp

@@ -0,0 +1,18 @@
+#include "rocket.hpp"
+
+rocket::rocket(int X,int Y,int V) : bullet(X,Y,256){
+	v=(V>=0?1:-1);
+}
+
+void rocket::next_pos(){
+	y--;
+	if(x==C-1 || x==0) v*=-1;
+	switch(v){
+		case 1:
+			x++;
+			break;
+		case -1:
+			x--;
+			break;
+	}
+}

+ 19 - 0
rocket.hpp

@@ -0,0 +1,19 @@
+#ifndef _rocket_
+#define _rocket_
+
+#include "bullet.hpp"
+#include "definitions.hpp"
+
+class rocket : public bullet
+{
+	public:
+	rocket(int X,int Y,int V);
+	~rocket() {}
+
+	void next_pos();
+
+	int v;
+
+};
+	
+#endif

+ 66 - 0
setboss.sh

@@ -0,0 +1,66 @@
+#!/bin/bash
+
+# Usage: ./setboss.sh <boss_name> <n>
+# This script modifies invaders' source code so that
+# the boss depicted in boss_name.dat be the boss for the n-th level
+# WHAT'S ACTUALLY DONE: (using command line setboss myboss.dat 2)
+# in file "definitions.hpp", line
+# #define BOSS_FILE2 "palombo"
+# becomes
+# #define BOSS_FILE2 "myboss"
+
+
+# Just to be on the safe side, the script also creates a backup copy
+# of definitions.hpp called definitions.hpp.bu
+
+MAX_LVL=3
+MIN_LVL=1
+
+if [ $# -ne 2 ]; then
+	echo Usage: $0 \<bossname\> \(must be a .dat, but DON\'T specify the extension when passing it\) \<level\>
+	echo Now leaving
+	exit 1
+fi
+
+NEW_BOSS_NAME=$1
+NEW_BOSS_FILE="$NEW_BOSS_NAME.dat"
+if [ ! -e $NEW_BOSS_FILE -o ! -f $NEW_BOSS_FILE ]; then
+	echo Could not find specified file $1
+	echo Now leaving
+	exit 2
+elif [[ ! "$NEW_BOSS_FILE" =~ dat$  ]]; then
+	echo This does not look like a text file
+	echo Now leaving
+	exit 3
+fi
+
+LEVEL=$2
+# This works too for some reason
+# if ! [ $2 -eq $2 ] &> /dev/null; then
+# 	echo Second argument $2 should be numeric!
+# 	echo Now leaving
+# 	exit 4
+# fi
+if [ $LEVEL -eq $LEVEL ] &> /dev/null; then
+	if [ $LEVEL -lt $MIN_LVL ]; then
+		LEVEL=$MIN_LVL
+	elif [ $LEVEL -gt $MAX_LVL ]; then
+		LEVEL=$MAX_LVL
+	fi
+else
+	echo Second argument should be numeric!
+	echo Now leaving
+	exit 4
+fi
+
+
+./checkboss.sh $NEW_BOSS_FILE
+
+# Everything has been checked, file exists and has .dat extension, second argument is an integer
+# with value between $MIN_LVL and $MAX_LVL
+# Now for the easy part:
+
+cp definitions.hpp definitions.hpp.bu
+sed s/"BOSS_FILE$LEVEL \".*\""/"BOSS_FILE$LEVEL \"$NEW_BOSS_NAME\""/ definitions.hpp > outputsed.tmp
+mv outputsed.tmp definitions.hpp
+echo "boss lv $LEVEL  successfully set."

+ 43 - 0
setsize.sh

@@ -0,0 +1,43 @@
+#!/bin/bash
+
+DEFAULT_R=30
+DEFAULT_C=60
+R=0
+C=0
+INPUT_FILE=definitions.hpp
+
+trap "rm $INPUT_FILE.tmp 2> /dev/null; exit -1" SIGINT SIGTERM
+
+if [[ $1 == "default" ]]; then
+	sed s/"#define R [0-9]*"/"#define R $DEFAULT_R"/ <$INPUT_FILE >$INPUT_FILE.tmp
+	sed s/"#define C [0-9]*"/"#define C $DEFAULT_C"/ <$INPUT_FILE.tmp >$INPUT_FILE
+	rm $INPUT_FILE.tmp
+	make clean
+	make -j4
+	exit 0
+elif [[ $# -gt 0 ]]; then echo Usage: $0 "[default]"; exit 1
+else
+
+echo Insert new Row number \(5-120\)
+until [[ $R -ge 5 && $R -le 120 ]]; do
+	read R
+	if [[ $R -lt 5 || $R -gt 120 ]]; then echo Invalid size.; fi
+	echo New R will be $R
+done
+
+echo Insert new Column number \(5-120\)
+until [[ $C -ge 5 && $C -le 120 ]]; do
+	read C
+	if [[ $C -lt 5 || $C -gt 120 ]]; then echo Invalid size.; fi
+	echo New C will be $C
+done
+
+sed s/"#define R [0-9]*"/"#define R $R"/ <$INPUT_FILE >$INPUT_FILE.tmp
+sed s/"#define C [0-9]*"/"#define C $C"/ <$INPUT_FILE.tmp >$INPUT_FILE
+
+rm $INPUT_FILE.tmp
+
+make clean
+make -j4
+
+fi

+ 6 - 0
spoletini.dat

@@ -0,0 +1,6 @@
+  _____  
+//     \\
+|  0 0  |
+c   L   P
+\  MMM  /
+ \_____/ 

+ 6 - 0
spoletini.dat.old

@@ -0,0 +1,6 @@
+  _____  
+//     \\
+|  0 0  |
+c   L   P
+\  MMM  /
+ \_____/ 

+ 44 - 0
wall.cpp

@@ -0,0 +1,44 @@
+#include "wall.hpp"
+
+wall::wall():game_object(0,0,32) , body(0,0){}		//default constructor
+
+wall::wall(int x,int y,int w,int h,int life) : game_object(x,y,32) , body(w,h){ 
+	/*health = new int* [height];
+	for(int i=0; i<height; ++i)
+		health[i] = new int[w];*/
+	set_life(life);	
+} 
+
+
+wall::~wall()
+{
+	//delete [] health;		if this line is commented, the program won't receive SIGSEGV after calling the destructor while creating walls' vector.
+}
+
+
+void wall::set_life(int Life){
+	for(int i=0;i<width;i++)
+		for(int j=0;j<height;j++)
+			health[j][i]=Life;
+	
+}
+
+void wall::create(int X,int Y,int W, int H,int life){ 
+	x=X;
+	y=Y;
+	width=W;
+	height=H;
+	/*health = new int* [height];
+	for(int i=0; i<height; ++i)
+		health[i] = new int[width];*/
+	set_life(life);	
+} 
+
+void wall::printlife(){
+	for(int i=0;i<height;i++){
+		for(int j=0;j<width;j++)
+			std::cout<<health[i][j];
+		std::cout<<std::endl;
+	}
+	std::cout<<std::endl;
+}

+ 20 - 0
wall.hpp

@@ -0,0 +1,20 @@
+#ifndef _wall_
+#define _wall_
+
+#include "game_object.hpp"
+#include "body.hpp"
+#include <iostream>
+
+class wall:public game_object, public body{
+	public:
+	wall();
+	wall(int x,int y,int w,int h,int life);
+	~ wall();
+	//int** health;
+	int health[MAX_WIDTH][MAX_HEIGHT];
+	void set_life(int life);
+	void create(int x,int y,int w,int h,int life);	//re-initializes parameters of a pre-existent wall
+	void printlife();					//prints health matrix
+};
+
+#endif