⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 player.cpp

📁 2002年
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "player.h"
#include "worldmodel.h"
#include "perceptron.h"
#include "skill.h"
#include "log.h"
#include "agent.h"


PlayerType::PlayerType(){
	SetDefaultType();
}

void PlayerType::SetDefaultType(){
	player_speed_max = ServerParam::player_speed_max;	
	stamina_inc_max = ServerParam::stamina_inc;
	player_decay = ServerParam::player_decay;
	inertia_moment = ServerParam::inertia_moment;
	dash_power_rate = ServerParam::dash_power_rate;
	player_size = ServerParam::player_size;
	kickable_margin= ServerParam::kickable_margin;
	kick_rand = ServerParam::player_rand;
	extra_stamina = 0;
	effort_max = 1.0f;
	effort_min = ServerParam::effort_min;
	
	kickable_area = player_size + kickable_margin + ServerParam::ball_size;
	player_speed_max = Min(player_speed_max, ServerParam::max_power*dash_power_rate / ( 1-player_decay)); 
}

void PlayerType::CopyType(int i){
	if(i<0 || i>=SP_player_types) return;
	
	player_speed_max = playertypes[i].player_speed_max;
	stamina_inc_max = playertypes[i].stamina_inc_max;
	player_decay = playertypes[i].player_decay;
	inertia_moment = playertypes[i].inertia_moment;
	dash_power_rate = playertypes[i].dash_power_rate;
	player_size = playertypes[i].player_size;
	kickable_margin = playertypes[i].kickable_margin;
	kick_rand = playertypes[i].kick_rand;
	extra_stamina = playertypes[i].extra_stamina;
	effort_max = playertypes[i].effort_max;
	effort_min = playertypes[i].effort_min;

	kickable_area = player_size + kickable_margin + ServerParam::ball_size;
	player_speed_max = Min(player_speed_max, ServerParam::max_power*dash_power_rate / ( 1-player_decay)); 
}

/***************    Role   ******************/
Role::Role(float attackness, float leftness, float aggressiveness, float creative){
	SetRole(attackness, leftness, aggressiveness, creative);
}

void Role::SetRole(float attackness, float leftness, float aggressiveness, float creative){
	this->attackness = attackness;
	this->leftness = leftness;
	this->aggressiveness = aggressiveness;
	this->creativeness = creativeness;
}

bool Role::RoleMatched(Role& role){
	return bool(attackness == role.attackness && leftness == role.leftness);
}
/**************************   Player    ******************************/
Player::Player(){
	MobileObject::MobileObject();
	InsideNO = -1;
	headfacing = 0;
	bodyfacing = 0;
	IT_inf.IT_cycles = InfCycles;
	Is_goalie = false;
	side = Side_Unknown;
	Iscontrolball = false;
	original_postime = 0;
	original_veltime = 0;

	//only useful for dynamic constructed player
	set_conf_param(ClientParam::conf_max, ClientParam::conf_decay, ClientParam::min_valid_conf);
	set_objtype(OBJ_Player);
	ChangeType(0);
}

void Player::Reset(Time time){
	vel_time = time - 1;
	gvel.Setdata(0, time -1);
	speed_conf = 0;
	update_seen_time = Max(time - 1, 0);

	pos_time = time -1;
	gpos.Setdata(0, pos_time);

	seenposinfo.TimedData(time - 1).time = -1;
	seenchinfo.TimedData(time -1).time = -1;
}

// to decide whether consistent with unknown player in sight info.
// original pos and delta is taken as reliable knowledge
bool Player::IsSamePlayer(VisualUnkPlayer& newp){
	float dist, delta;
	int timegap;

	if(gpos.IsDataKnown(original_postime)){ 
		dist = Pos(original_postime).dist(newp.pos);
		delta = pos_deltas.Data(original_postime);
		timegap = abs(newp.t - original_postime);
	}else{
		dist = pos.dist(newp.pos);
		delta = dist * 0.5f * ServerParam::dist_qstep;
		timegap = 8;
	}

	if(dist > ClientParam::too_different_distance) return false;
	float allowdis = newp.seen_distance() * ServerParam::dist_qstep + timegap * max_speed + delta + Self.SummarizePosGap(original_postime, newp.t).mod();
	if(Self.SelfColl(original_postime, newp.t)){
		allowdis += 1.0f;
	}
	if(dist < allowdis)
		return true;
	else
		return false;
}


void Player::estimate_domain(Time time){
	if(domain_time >= time) return;
	if(!domain.IsDataKnown(domain_time) || !domain.Data(domain_time).IsValid()) return;

	if(sensory.NewSight && !seen && domain_time == sensory.LastSightTime){
#ifdef _WINDOWS
		domain.Data(domain_time).MinusAngle(NoiseData(Self.Headfacing(domain_time),
					0.5f*Self.MyViewWidth(Self.viewwidth.Data(domain_time))));
#else // _LINUX
		NoiseData tmpnoise = NoiseData(Self.Headfacing(domain_time),
                                        0.5f*Self.MyViewWidth(Self.viewwidth.Data(domain_time)));
		domain.Data(domain_time).MinusAngle(tmpnoise);
#endif
		domain.Data(domain_time).MinusRadius(ServerParam::feel_distance);
	}
	while(domain_time < time){
		domain_time ++;
		domain.Data(domain_time) = domain.Data(domain_time-1);
		domain.TimedData(domain_time).time = domain_time;
		domain.Data(domain_time).Diffuse(1,max_speed);
		domain.Data(domain_time).ShiftCenter(Self.Pos(domain_time) - Self.Pos(domain_time-1));
		if(sensory.rec_sight_info.ChkData(domain_time)){
			if(seenposinfo.IsDataKnown(domain_time)){
			//注意,如果这周期有被看到, 就不应该进入估计模式, 
				DoLog("Error estimate Domain");				
				domain.Data(domain_time).Set(seen_distance(domain_time), 
					0.5f*seen_distance(domain_time)*ServerParam::dist_qstep,
					seen_rel_angle(domain_time)+Self.Headfacing(domain_time), 
					Rad2Deg(0.5f*ServerParam::dir_qstep));
			}else{	
			//所以假设他没被看到
#ifdef _WINDOWS
				domain.Data(domain_time).MinusAngle(NoiseData(Self.Headfacing(domain_time),
					0.5f*Self.MyViewWidth(Self.viewwidth.Data(domain_time))));
#else // _LINUX
				NoiseData  tmpnoise;
				tmpnoise = NoiseData(Self.Headfacing(domain_time),
                                        0.5f*Self.MyViewWidth(Self.viewwidth.Data(domain_time)));
				domain.Data(domain_time).MinusAngle(tmpnoise);
#endif
				domain.Data(domain_time).MinusRadius(ServerParam::feel_distance);
			}
		}
	}
}

void Player::update(Time time){
	if(InsideNO == Agent::MyNumber) return;

	MobileObject::update(time);
#ifdef	_Up_FState
	Iscontrolball = Pos(time).dist2(ball.Pos(time)) < Sqr(kickable_area);
#else
	if(ball.updated_holder) return;
	//check if it control the ball
	if (ball.IsSeen() && IsValidObject()){
	//see ball
		Iscontrolball = (Pos(ball.seen_time()).dist2(ball.Pos(ball.seen_time())) < Sqr(kickable_area));
	}else if(!ball.IsSeen() && IsSeen()){//(IsSeen(time)){
		//Iscontrolball = false;	//只看见人,没看见球
		if(Iscontrolball){
			int t = seen_time();
			float edge_gap = Self.MyViewWidth(Self.viewwidth.Data(t))/2 - (float)fabs(seen_rel_angle());
			float allow_diff = ASin(kickable_area / (seen_distance()+ 0.5f));
			if(edge_gap > 2.9f || (allow_diff - edge_gap) < 0.5f 
				|| (seen_distance() <= ServerParam::feel_distance && !seenchinfo.IsDataKnown(t))){
				Iscontrolball = false;
				DoLog("controlball fix, %d (%.1f, %.1f, %.1f)", InsideNO, edge_gap, allow_diff, edge_gap - allow_diff);
			}else{
				DoLog("controlball bug see player %d withou ball(%.1f, %.1f, %.1f), how can he control ball?", InsideNO, edge_gap, allow_diff, edge_gap - allow_diff);
			}
		}
	}
#endif
}

void Player::update_seen(Time time){
	MobileObject::update_seen(time);
	/*******domain - 队员的活动范围**********/
	int t = update_seen_time;//
	if(seen){
		domain.Data(t).Set(seen_distance(t), 0.5f*seen_distance(t)*ServerParam::dist_qstep,
			seen_rel_angle(t)+Self.Headfacing(t), Rad2Deg(0.5f*ServerParam::dir_qstep));
		domain.TimedData(t).time = t;
		domain_time = t;
	}
}

void Player::update_heard(Time time){
	MobileObject::update_heard(time);

	if(isupdateheard){
		//Update a player's domain according to heard info which is a circle.
		estimate_domain(heardpos_info.time);
		Vector relpos = heardpos_info.data.mean - Self.Pos(heardpos_info.time);

		NoiseData radius(relpos.mod(), heardpos_info.data.delta);
		NoiseData angle;
		angle.mean = relpos.Angle();
		if(heardpos_info.data.delta >= radius.mean){
			//when the circle covers myself
			angle.delta = 180.0f;
		}else{
			angle.delta = ASin(heardpos_info.data.delta / radius.mean);
		}
		if(domain.IsDataKnown(heardpos_info.time) && domain.Data(heardpos_info.time).IsValid() ){
			domain.Data(heardpos_info.time).Intersect(radius, angle);
		}else{
			domain.Data(heardpos_info.time).Set(radius.mean, radius.delta,
				angle.mean, angle.delta);
			domain.TimedData(heardpos_info.time).time = heardpos_info.time;
		}
		domain_time = heardpos_info.time;
		DoLog(LOG_HEAR, "heard%d at %d(%.1f,%.1f) delta %.1f", InsideNO, heardpos_info.time, heardpos_info.data.mean.x, 
			heardpos_info.data.mean.y, heardpos_info.data.delta);
	}
}

void Player::update_end(){
	//update bodyfacing, headfc
	if(InsideNO != Agent::MyNumber){
#ifdef _Up_FState
		if(sensory.HasFullState()){
			if(acc_bodyangle.IsDataKnown(situation.CurrentTime)){
				bodyfc.Setdata(acc_bodyangle.Data(situation.CurrentTime), situation.CurrentTime);
				if(acc_neckangle.IsDataKnown(situation.CurrentTime)){
					headfc.Setdata(NormalizeAngle(acc_neckangle.Data(situation.CurrentTime)
						+ bodyfc.Data(situation.CurrentTime)), situation.CurrentTime);
				}
				bodyfc_guessed = false;
			}
		}
#else
		//估计
		if(newpos){
			bodyfc_guessed = false;
			if(fcinfo.time == situation.CurrentTime){
				bodyfc.Setdata(NormalizeAngle(Self.headfacing+fcinfo.data.x), situation.CurrentTime);
				headfc.Setdata(NormalizeAngle(Self.headfacing+fcinfo.data.y), situation.CurrentTime);
			}else if(IsSeenMoving(situation.CurrentTime)){
				//当观察到球员的运动速度<0.1f时, 认为他的身体朝向难以判断	
				bodyfc.Setdata(Vel(situation.CurrentTime).Angle(), situation.CurrentTime); 
				if(Vel(situation.CurrentTime).mod() < 0.1f){
					bodyfc_guessed = true;			
				}
			}else if(seenposinfo.IsDataKnown(situation.CurrentTime - 1) && distance < 5.0){
				//根据位置差估计位置
				Vector vel = Pos(situation.CurrentTime) - Pos(situation.CurrentTime -1);
				vel -= Self.SummarizePosGap(situation.CurrentTime-1, situation.CurrentTime);				
				bodyfc.Setdata(vel.Angle(), situation.CurrentTime);
				
				if (vel.mod() > max_speed){
					vel = vel / vel.mod() * max_speed;
				}
				if(vel.mod() <  (distance * 0.05f + 0.15f)){
					//当根据位置估计出运动速度<0.2f时, 认为他的身体朝向难以判断	
					bodyfc_guessed = true;
				}
				vel *= speed_decay;
				gvel.Setdata(vel, situation.CurrentTime);
				vel_time = situation.CurrentTime;
				original_veltime = vel_time;
				speed_conf = max_conf;				
			}else{
				bodyfc_guessed = true;
				if(gpos.IsDataKnown(situation.CurrentTime - 1)){
					Vector vel = Pos(situation.CurrentTime) - Pos(situation.CurrentTime -1);					
					bodyfc.Setdata(vel.Angle(), situation.CurrentTime);
				}
			}
		}else{
			bodyfc_guessed = true;
		}
		estimate_domain(situation.CurrentTime);
		pos_delta_valid = domain.IsDataKnown(situation.CurrentTime) && domain.Data(situation.CurrentTime).IsValid();
		estimate_pos_delta(situation.CurrentTime);
#endif
	}else{
		pos_delta_valid = true;
		pos_deltas.Setdata(0, situation.CurrentTime);  
	}

	MobileObject::update_end();

	rel_pos_2_ball = pos - ball.pos;
	balldist = rel_pos_2_ball.mod();
	ballangle = (ball.pos - pos).Angle();

	if(!IsValidObject()) return;

	Vector domain_pos = domain.Data(situation.CurrentTime).GetCenterPos(); 
	DoLog(LOG_UPDATE, "No%d, pos(%.1f, %.1f), domain_pos(%.1f, %.1f), delta%.1f, conf%.2f",
		InsideNO, pos.x, pos.y, domain_pos.x, domain_pos.y, pos_delta, pos_conf);
	if(bodyfc.IsDataKnown(situation.CurrentTime)){
		bodyfacing = bodyfc.Data(situation.CurrentTime);
		if(!bodyfc_guessed){
			DoLog(LOG_UPDATE, "NO %d, bodyfacing%.2f, speed%.2f, Angle%.2f", InsideNO, bodyfacing,
				speed, vel_angle);
		}else{
			DoLog(LOG_UPDATE, "NO %d, bodyfacing%.2f(guess), speed%.2f, Angle%.2f", InsideNO, bodyfacing,
				speed, vel_angle);
		}
	}
}

//decide whether hear info is useful for me.
bool Player::Isupdate_heard(){	
	//no hear info
	if(!heard_pos) return false;
	
	if(IsValidObject()){
		if(pos.dist(heardpos_info.data.mean) > heardpos_info.data.delta + pos_delta + 1.0f){
			DoLog(LOG_HEAR, "Hearbug %d known pos(%.1f, %.1f), delta%.1f while hearing pos(%.1f, %.1f), delta%.1f",
				heardpos_info.time, pos.x, pos.y, pos_delta,
				heardpos_info.data.mean.x, heardpos_info.data.mean.y, heardpos_info.data.delta);
		}
	}
	DoLog(LOG_HEAR, "%d (%.1f, %.1f, delta%.1f), delay%d, old_delta%.1f",InsideNO, 
		heardpos_info.data.mean.x, heardpos_info.data.mean.y, heardpos_info.data.delta,
		situation.CurrentTime - heardpos_info.time, pos_deltas.Data(pos_delta_time));
	//old info is not valid
	if(!pos_valid() || !IsValidObject() || Isforgot()) return true;

	float guess_delta;
	estimate_pos_delta(situation.CurrentTime);
	guess_delta = heardpos_info.data.delta + (situation.CurrentTime 
		- heardpos_info.time) * max_speed + CP_coordinate_gap_between_agents;


	if(guess_delta < pos_deltas.Data(pos_delta_time)){
		return true;
	}else{
		return false;
	}
}

AngleDeg Player::Bodyfacing(Time time){
	return bodyfc.IsDataKnown(time) ? bodyfc.Data(time) : bodyfacing;
}

AngleDeg Player::Headfacing(Time time){
	return headfc.IsDataKnown(time) ? headfc.Data(time) : headfacing;
}

AngleDeg Player::Headangle(Time time){
	return headang.IsDataKnown(time) ? headang.Data(time) : head_angle;
}

void Player::set_fcinfo(float facedir, float neckdir, Time time){
	fcinfo = TimedData<Vector>(Vector(facedir, neckdir), time);
}

void Player::set_arm_tackle(float armdir, bool Istackle, Time time){
	seenarm.Setdata(armdir, time);
	seentackle.Setdata(Istackle, time);
}

void Player::set_inside_no(UNum No){
	this->InsideNO = No;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -