/* 
    TowBowlTactics: Adaptation of the tabletop game Blood Bowl

    Copyright (C) 2001-2003 Pascal Bourut (toweld@rocketmail.com)

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "Team.h"

Team::Team(char* n,char* c,char* a, int t,int cl,int h,int r,int p,int rc,char*e,int i){
	set_name(n);
	set_coach(c);
	set_race(a);
	set_emblem(e);
	formations_file = NULL;
	treasury=t;
	cheer_leaders=cl;
	assistant=h;
	reroll=r;
	id=i;
	fan_factor=p;
	players = new map<int,Player*>;
	formations = new map<int,Formation*>;
	score = 0;
	turn = 0;
	complain_ok = true;
	reroll_init = r;
	referee_intimidated = false;
	free_turn = false;
	reroll_cost = rc;
	blitz_done = false;
	aggress_done = false;
	throw_done = false;
	throw_team_mate_done = false;
	transmit_done = false;
	ejected = 0;
	out = 0;
	reserve = 0;
	ko = 0;
	free_turn = false;
	placed = false;
	reroll_used = false;

	d6 = new Dice(D6);
	d8 = new Dice(D8);
	d16 = new Dice(D16);
}

Team::~Team(){
	DEBUG ( printf("-> Team::~Team() %d %s\n",id,name); );

	std::map<int,Player*> ::iterator itp;
    
	for(itp=players->begin();itp!=players->end();itp++){
		if( (*itp).second ) {
			delete ((*itp).second);
		}
	}
	delete players;
	
	std::map<int,Formation*> ::iterator itf;
    
	for(itf=formations->begin();itf!=formations->end();itf++){
		if( (*itf).second ) {
			delete ((*itf).second);
		}
	}
	delete formations;

	delete d6;
	delete d8;
	delete d16;
	free(name);
	free(coach);
	free(race);
	free(emblem);
	free(formations_file);
	DEBUG ( printf("<- Team::~Team() %d\n",id,name); );
}

void Team::set_team_id(int i){ id = i; }

void Team::set_name(char* n){
	if(n){
		name = (char*)malloc( CHAR_64 );
		sprintf(name,"%s",n);
	}
	else {
		name = NULL;
	}
}

void Team::set_coach(char* c){
	if(c){
  		coach = (char*)malloc( CHAR_64 );
		sprintf(coach,"%s",c);	
	}
	else {
		coach = NULL;
	}
}
  
void Team::set_race(char* r){
	if(r){
  		race = (char*)malloc( CHAR_64 );
		sprintf(race,"%s",r);	
	}
	else {
		race = NULL;
	}
}


void Team::set_emblem(char* e){
	if(e){
		emblem = (char*)malloc( CHAR_64 );
		sprintf(emblem,"%s",e);
	}
	else {
		emblem = NULL;
	}
}

void Team::set_formations_file(char *f){
	if(f){
		formations_file = (char*)malloc( CHAR_128 );
		sprintf(formations_file,"%s",f);
	}
	else {
		formations_file = NULL;
	}
}

char* Team::get_emblem(void){ return emblem; }
char* Team::get_name(){	return name; }
char* Team::get_race(){	return race; }
char* Team::get_coach(){ return coach; }
char* Team::get_formations_file(){ return formations_file; }
  
void Team::set_id(int i){ id=i; }  
int Team::get_id(){	return id; }
  
void Team::set_reroll_cost(int rc){	reroll_cost=rc; }
int Team::get_reroll_cost(){ return reroll_cost; }
  

void Team::set_apothecary(int a){ apothecary=a; }
int Team::get_apothecary(){ return apothecary; }

void Team::set_wizard(int w){ wizard=w; }
int Team::get_wizard(){	return wizard; }
 
void Team::set_treasury(int t){	treasury=t; }
int Team::get_treasury(){ return treasury; }
  
void Team::set_rating(int r){ rating=r; }
int Team::get_rating(){ return rating; }
  
void Team::set_cheer_leaders(int cl){ cheer_leaders=cl; }
int Team::get_cheer_leaders(){ return cheer_leaders; }

void Team::set_assistant(int h){ assistant=h; }
int Team::get_assistant(){ return assistant; }

void Team::set_reroll(int r){ reroll=r;	reroll_init=r; }
void Team::set_reroll_init(int ri){	reroll_init=ri; }
int Team::get_reroll(){ return reroll; }

void Team::set_score(int s){ score=s; }
int Team::get_score(){ return score; }

void Team::set_fan_factor(int p){ fan_factor=p; }
int Team::get_fan_factor(){	return fan_factor; }

void Team::set_turn(int t){	turn=t; }
int Team::get_turn(){ return turn; }

bool Team::is_reroll_used(){ return reroll_used; }

void Team::add_player(Player *player){
	players->insert(make_pair(player->get_number(),player));
	player->set_team(get_id());
	player->place_in_reserve();
}
 
void Team::add_player(Player *player, int i){
	players->insert(make_pair(i,player));
}

bool Team::can_complain(){return complain_ok;}
void Team::set_can_complain(bool b){complain_ok = b;}

void Team::set_blitz_done(bool b){blitz_done=b;}
bool Team::is_blitz_done(){return blitz_done;}
 
void Team::set_aggress_done(bool b){aggress_done=b;}
bool Team::is_aggress_done(){return aggress_done;}
  
void Team::set_throw_done(bool b){throw_done=b;}
bool Team::is_throw_done(){return throw_done;}
 
void Team::set_throw_team_mate_done(bool b){throw_team_mate_done=b;}
bool Team::is_throw_team_mate_done(){return throw_team_mate_done;}
 
void Team::set_transmit_done(bool b){transmit_done=b;}
bool Team::is_transmit_done(){return transmit_done;}

void Team::inc_turn(void){turn++;}
void Team::inc_score(void) {score++;}

void Team::set_referee_intimidated(bool b){referee_intimidated = b;}
bool Team::has_intimidated_referee(void){return referee_intimidated;}

void Team::set_has_free_turn(bool b){free_turn = b;}
bool Team::has_free_turn(void){return free_turn;}

void Team::set_ejected(int e){ejected=e;}
int Team::get_ejected(){return ejected;}

void Team::set_ko(int k){ko=k;}
int Team::get_ko(){return ko;}

void Team::set_out(int o){out=o;}
int Team::get_out(){return out;}

void Team::set_reserve(int r){reserve=r;}
int Team::get_reserve(){return reserve;}

void Team::inc_ejected(void){ejected++;}
void Team::inc_ko(void){ko++;}
void Team::inc_out(void){out++;}
void Team::inc_reserve(void){reserve++;}

void Team::inc_reroll(void){reroll++;}
void Team::decr_reroll(void){reroll--;}
 
void Team::reset_reroll(void){reroll = reroll_init;}

void Team::set_reroll_used(bool r){
    reroll_used=r;
    if(r) decr_reroll();
	std::map<int,Player*> ::iterator it;
    for(it=players->begin();it!=players->end();it++){
		((*it).second)->set_team_reroll_used(true);
    }
}
  
int Team::on_playground_player_count(void){
    int n = 0;
	std::map<int,Player*> ::iterator it;
    for(it=players->begin();it!=players->end();it++){
		if (((*it).second)->get_square()) n++;
    }
    return n;
}

void Team::transfer_players_to_reserve(void){
	std::map<int,Player*> ::iterator it;
    for(it=players->begin();it!=players->end();it++){
		if ( ((*it).second) && ((*it).second)->get_square() && ((*it).second)->get_status()<KO )
			((*it).second)->place_in_reserve();
    }
}

bool Team::is_placed(void){ return placed; }

void Team::set_placed(bool b){ placed = b; }

void Team::save_state(FILE *fd, int depth){  
	char format[10];
	memset(format,0,10);
	
	for(int i=0;i<depth;i++)
		format[i] = ' ';
		format[depth-1] = '\0';
		fprintf(fd,"%s<name>%s</name>\n",format,name);
		fprintf(fd,"%s<coach>%s</coach>\n",format,coach);
		fprintf(fd,"%s<formation>%s</formation>\n",format,(formations_file)?formations_file:"default.xml");
		fprintf(fd,"%s<race>%s</race>\n",format,race);
		fprintf(fd,"%s<emblem>%s</emblem>\n",format,emblem);
		fprintf(fd,"%s<treasury>%i</treasury>\n",format,treasury);
		fprintf(fd,"%s<cheerleaders>%i</cheerleaders>\n",format,cheer_leaders);
		fprintf(fd,"%s<assistant>%i</assistant>\n",format,assistant);
		fprintf(fd,"%s<reroll>%i</reroll>\n",format,reroll);
		fprintf(fd,"%s<reroll_cost>%i</reroll_cost>\n",format,reroll_cost);
		fprintf(fd,"%s<score>%i</score>\n",format,score);
		fprintf(fd,"%s<turn>%i</turn>\n",format,turn);
		if(players){
			fprintf(fd,"%s<players>\n",format);
			std::map<int,Player*> ::iterator it;
			for(it=players->begin();it!=players->end();it++)
				if((*it).second) ((*it).second)->save_state(fd, depth+1);
					fprintf(fd,"%s</players>\n",format);
		}

		fprintf(fd,"%s<reroll_used>%i</reroll_used>\n",format,reroll_used);
		fprintf(fd,"%s<id>%i</id>\n",format,id);
		fprintf(fd,"%s<blitz_done>%i</blitz_done>\n",format,blitz_done);
		fprintf(fd,"%s<aggress_done>%i</aggress_done>\n",format,aggress_done);
		fprintf(fd,"%s<throw_done>%i</throw_done>\n",format,throw_done);
		fprintf(fd,"%s<throw_team_mate_done>%i</throw_team_mate_done>\n",format,throw_team_mate_done);
		fprintf(fd,"%s<transmit_done>%i</transmit_done>\n",format,transmit_done);
		fprintf(fd,"%s<ejected>%i</ejected>\n",format,ejected);
		fprintf(fd,"%s<out>%i</out>\n",format,out);
		fprintf(fd,"%s<reserve>%i</reserve>\n",format,reserve);
		fprintf(fd,"%s<ko>%i</ko>\n",format,ko);
		fprintf(fd,"%s<complain_ok>%i</complain_ok>\n",format,complain_ok);
		fprintf(fd,"%s<fan_factor>%i</fan_factor>\n",format,fan_factor);
		fprintf(fd,"%s<reroll_init>%i</reroll_init>\n",format,reroll_init);
		fprintf(fd,"%s<referee_intimidated>%i</referee_intimidated>\n",format,referee_intimidated);
		fprintf(fd,"%s<free_turn>%i</free_turn>\n",format,free_turn);
		fprintf(fd,"%s<apothecary>%i</apothecary>\n",format,apothecary);
		fprintf(fd,"%s<wizard>%i</wizard>\n",format,wizard);
		fprintf(fd,"%s<rating>%i</rating>\n",format,rating);	
		fprintf(fd,"%s<placed>%i</placed>\n",format,placed);	
  }



void Team::set_players(map<int,Player*> *players_p){
	this->players=players_p;
}

map<int,Player*>* Team::get_players(){
	return players;
}

void Team::remove_player(int i){
	if(contain_player_num(i)){
		get_player(i)->set_team(NONE);
		players->erase(i);
	}
}

Player* Team::get_player(int i){
	if(contain_player_num(i))
		return (*players)[i];
	return NULL;
}

void Team::add_formation(Formation *formation){
	formations->insert(make_pair(formation->get_id(),formation));
}

void Team::remove_formation(int i){
	formations->erase(i);
}

Formation* Team::get_formation(int i){
	return (*formations)[i];
}

void Team::adopt_formation(int i){
	Formation *f = get_formation(i);
	if(f) adopt_formation(f);
	else transfer_players_to_reserve();
}

void Team::adopt_formation(Formation *f){
	int number;
	Square* s;
	Player* p;
	transfer_players_to_reserve();
	map<int,Square*> *placement = f->get_placement();
	std::map<int,Square*> ::iterator it;
	for(it=placement->begin();it!=placement->end();it++){
		number = (*it).first;
		s = (*it).second;
	
		p = get_player(number);
		if (p && s && p->get_status()==RESERVE ){
			if(id==HOME)
				p->place(s);
			else {
				//placement en mode mirroir...
				int center_diff = (PLAYGROUND_HEIGHT/2) - 1 - s->get_y();
				p->place(s->get_x(),(PLAYGROUND_HEIGHT/2)+center_diff);
			}
		}
	}	
}

int Team::get_kick_off_result(){
	return d6->roll(2);
}

int Team::get_kick_off_distance(){
	return d6->roll();
}

int Team::get_kick_off_direction(){
	return d8->roll();
}

Player* Team::get_random_player(){
	int num;
	do{
		num = d16->roll();
	}while( !(contain_player_num(num) && get_player(num)->get_square()) );
	return get_player(num);
}

int Team::get_random_player_num(){
	int num;
	do{
		num = d16->roll();
	}while( !(contain_player_num(num) && get_player(num)->get_square()) );
	return num;
}

bool Team::contain_player_num(int i){
	std::map<int,Player*> ::iterator it;
	for(it=players->begin();it!=players->end();it++)
		if ( (*it).first == i ) 
			return true;
	return false;
}

int Team::buy_referee(){
	switch( d6->roll() ){
		case 1: return TOOBAD;
		case 6: return SUCCESS;
		default: return FAIL;
	}
}

bool Team::can_reroll(){
	if( reroll>0 && !reroll_used)return true;
	return false;
}

void Team::prepare_for_next_turn(){
	std::map<int,Player*> ::iterator it;
	for(it=players->begin();it!=players->end();it++){
		((*it).second)->set_has_played(false);
		((*it).second)->reset_move_count();
		((*it).second)->reset_overmove_count();
		((*it).second)->set_gather_done(false);
		((*it).second)->set_receive_done(false);
		((*it).second)->set_block_done(false);
		((*it).second)->set_throw_done(false);
		((*it).second)->set_throw_team_mate_done(false);
		((*it).second)->set_aggress_done(false);
		((*it).second)->set_blitz_done(false);
		((*it).second)->set_team_reroll_used(false);
		((*it).second)->set_team_blitz_done(false);
		((*it).second)->set_team_aggress_done(false);
		((*it).second)->set_team_throw_done(false);
		((*it).second)->set_move_reroll_used(false);
		///////////////////////////
		// Ragnar Modif2
		((*it).second)->set_get_up_done(false);
		///////////////////////////
		// Ragnar Modif3
		((*it).second)->set_mighty_blow_used(false);
		((*it).second)->set_dirty_player_used(false);
		((*it).second)->set_pilling_on_used(false);
		// Ragnar Modif4
		((*it).second)->set_frenzy_block_done(false);
		///////////////////////////
		// Ragnar Modif6 : nouvelles méthodes dans Team
		((*it).second)->set_bone_head_tested(false);
		((*it).second)->set_really_stupid_tested(false);
		///////////////////////////
	}
	set_reroll_used(false);
	set_blitz_done(false);
	set_aggress_done(false);
	set_throw_done(false);
	set_throw_team_mate_done(false);
	set_transmit_done(false);
}



//////////////////////////////////////////
// Ragnar Modif : pour savoir si un joueur est correctement
// placé lors du coup d'envoi pour utiliser la compétence
// frappe précise (kick)
bool Team::can_use_kick_skill(){
	std::map<int,Player*> ::iterator it;
	map<int,Player*> *players = get_players();
    
	bool can_kick = false;

	for(it=players->begin();it!=players->end();it++){
		if( ((*it).second)->get_square() && ((*it).second)->has_got_skill(KICK) ) {
		  int x_s = ((*it).second)->get_square()->get_x();
		  int y_s = ((*it).second)->get_square()->get_y();
		  
		  if ( x_s >= (CORRIDOR_WIDTH) && x_s <= (PLAYGROUND_WIDTH-CORRIDOR_WIDTH-1)
			  && y_s != (PLAYGROUND_HEIGHT/2-1) && y_s != (PLAYGROUND_HEIGHT/2)){
			can_kick = true;
		  }
		}
	}

	return can_kick;
}
