📄 player.cpp
字号:
#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 + -