📄 robotrole.cpp
字号:
/****************************************************************************************************
robotrole.cpp 艾数机器人角色源文件
Purpose:
角色可以使用的动作
author:
yy_cn
Created Time:
2006-5-9
****************************************************************************************************/
#include "area.h"
#include "action.h"
#include "robotrole.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// 角色管理
//
// public
RoleManager::RoleManager (void)
: _roles ()
{
addRole (new RoleGoalkeeper ()); // RT_GOALKEEPER - 守门员角色
addRole (new RoleAttack ()); // PT_ATTACK - 助攻
addRole (new RoleVanguardTop ()); // PT_VANGUARD_TOP - 进攻上前锋
addRole (new RoleVanguardBottom ()); // PT_VANGUARD_BOTTOM - 进攻下前锋
addRole (new RoleAttackDefend ()); // PT_ATTACK_DEFEND - 下护卫
addRole (new RoleLeftTopDefend ()); // PT_DEFEND_LEFT_TOP 左上角的后卫
addRole (new RoleLeftBotDefend ()); // PT_DEFEND_LEFT_BOT 左下角的后卫
addRole (new RoleRightTopDefend ()); // PT_DEFEND_RIGHT_TOP 右上角的后卫
addRole (new RoleRightBotDefend ()); // PF_DEFEND_RIGHT_BOT 右下角的后卫
}
// public
RoleManager::~RoleManager (void)
{
for_each (_roles.begin (), _roles.end (), delete_t <RobotRole> ());
}
// public
void
RoleManager::addRole (RobotRole *role)
{
if (role == 0) {
ASSERT (false);
return;
}
_roles.push_back (role);
}
// public
RobotRole *
RoleManager::getRole (RoleType type)
{
RobotRole *role = _roles[(int) type];
if (role == 0 || type != role->getType () || type == RT_UNKNOWN) {
ASSERT (false);
}
return role;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// 守门员角色
//
// public virtual
long
RoleGoalkeeper::assignRobots (const Robot *robots,
const vector <long> &robotIndexs,
const LastRole &lastRole)
{
return 0;
}
// public virtual
void
RoleGoalkeeper::strategy (Robot &robot,
const AreaInfo *areaInfo,
BallSpeed speed,
BallDirection direction,
BallPower power,
GuardLeak leak,
const Environment *env)
{
//
// 守门员守门策略
//
/*
A -> B -> C -> .... 优先级最高的为 A
A. 球在守门员比较近的距离,将球推出保证安全
条件:
1. 守门员与球的距离只有半个机器人宽
使劲向非球门方向推球
B. 不需要防守,守门员退回到球门前的 GOAL_CENTER_X, GOAL_CENTER_Y 位置 - 以垂直的方式移动
条件:
1. 球未在 1, 6, 7, 11, 12, 16 区域内
2. 球的速度小于等于 BS_LOW 中低速
3. 球的速度大于等于 BS_MIDDLE_LOW 中高速
4. 球的控制权在敌方处
5. 球的方向为我方球门方向
1 & (2 || (3 & 4 & 5))
C. 需要防守,守门员的 x 轴保持在球门前的 GOAL_CENTER_X
1. 如果球在 3, 8, 13, 18, 向我方方向运动,则以球的上次位置,现在位置,算出守门员 Y 轴上对应的点
机器人移动到此点
2. 机器人的 Y 轴跟着球的 Y 轴移动,并且不超出球门的上下 Y 值
Y 轴跟着球的 Y 轴移动,并且不超出球门的上下 Y 值
如果球在 1, 16 区域则守门员站在对应的两个球门角上
条件:
1. A, B, 条件都不满足时
*/
//
// 策略 A
//
if (getDistance (robot.pos.x, robot.pos.y, env->predictedBall.pos.x, env->predictedBall.pos.y) <= ROBOT_DIAMETER / 2) {
//
// 将球踢出会不精确,造成守门员跑开岗位 - 先分析一下其它队的策略
//
////
//// 救球
////
//if (canShoot (robot.pos.x, robot.pos.y, env->currentBall.pos.x, env->currentBall.pos.y) == true) {
// actShoot (robot, *env);
// return;
//}
}
//
// 策略 B
//
BallArea area = areaInfo->getArea ();
bool term1 = false;
if (area != BA_1 && area != BA_6 && area != BA_7 && area != BA_11 && area != BA_12 && area != BA_16)
term1 = true;
bool term2 = false;
if (speed <= BS_LOW)
term2 = true;
bool term3 = false;
if (speed >= BS_MIDDLE_LOW)
term3 = true;
bool term4 = false;
if (power == BP_OPPONENT)
term4 = true;
bool term5 = false;
if (direction != BD_LEFT_TOP && direction != BD_LEFT && direction != BD_LEFT_BOTTOM)
term5 = true;
//
// 1 & (2 || (3 & 4 & 5))
//
if (term1 && (term2 || (term3 && term4 && term5))) {
//
// 允许守门员站立的位置有半个机器人的偏差
//
double x = GOAL_CENTER_X;
double y = GOAL_CENTER_Y;
////
//// 如果守门员当前在 点 (X, Y) 的 1/4 个机器人的范围内则不需要移动
////
//double pointX1 = x - ROBOT_DIAMETER / 4;
//double pointY1 = y + ROBOT_DIAMETER / 4;
//double pointX2 = x + ROBOT_DIAMETER / 4;
//double pointY2 = y - ROBOT_DIAMETER / 4;
//transform (pointX1, pointY1);
//transform (pointX2, pointY2);
//
//if (robot.pos.x > pointX1 && robot.pos.x < pointX2 &&
// robot.pos.y < pointY1 && robot.pos.y > pointY2) {
// //
// // 将机器人面向对方球门的角度
// // TODO:actTrun 方法不精确,有问题
// //
// return;
//}
//
// 移动到中点位置 - 以垂直的方式移动
//
double targetX = GOAL_CENTER_X;
double targetY = GOAL_CENTER_Y;
transform (targetX, targetY);
//if (robot.pos.x > targetX + 1 || robot.pos.x < targetX - 1) {
//actToPosition (robot, targetX, robot.pos.y);
// return;
//}
//if (robot.pos.y > targetY + 1 || robot.pos.y < targetY - 1) {
actToPosition (robot, targetX, targetY);
// return;
//}
//transform (x, y);
//actToPosition (robot, x, y);
return;
}
//
// 策略 C
//
double targetX = GOAL_CENTER_X,
targetY = 0;
transform (targetX, targetY);
if ((area == BA_3 || area == BA_8 || area == BA_13 || area == BA_18) &&
(direction == BD_LEFT_TOP || direction == BD_LEFT || direction == BD_LEFT_BOTTOM)) {
targetY = getMappedTargetY (env->lastBall.pos.x,
env->lastBall.pos.y,
env->currentBall.pos.x,
env->currentBall.pos.y,
targetX);
}
else {
targetY = env->predictedBall.pos.y;
}
// 移动到的 Y 坐标超出球门的 Y 坐标时将 Y 坐标改为球门的 Y 坐标
//
if (targetY > GTOPY + ROBOT_DIAMETER / 2)
targetY = GTOPY + ROBOT_DIAMETER / 2;
if (targetY < GBOTY - ROBOT_DIAMETER / 2)
targetY = GBOTY - ROBOT_DIAMETER / 2;
actToPosition (robot, targetX, targetY);
}
//
// 从还未分配的机器人中找出离指定点最近的机器人
//
#define FIND_ROBOT(pointX, pointY) \
do { \
long index = robotIndexs[0]; \
double distance = 9999; /* 保存上次选择的最短距离机器人的距离 */ \
\
double goalX = pointX; /* 球场的右边界 */ \
double goalY = pointY; /* 场地上边界 */ \
/**/ \
/* 此坐标以我方在左边情况时考虑的,需要转换 */ \
/**/ \
transform (goalX, goalY); \
\
/**/ \
/* 从未分配的机器中找出最合适的机器人 */ \
/**/ \
typedef vector <long>::const_iterator iterator; \
iterator itend = robotIndexs.end (); \
for (iterator it = robotIndexs.begin (); it != itend; ++it) { \
if (lastRole.role[(*it)] == getType ()) { \
/**/ \
/* 上一次分配的角色中包含当前需要分配的角色 */ \
/* 为了保证角色执行任务的连续性,使用同样的机器人来当任此角色 */ \
/**/ \
index = *it; \
break; \
} \
\
/**/ \
/* 获得当前机器人与球场右上角的距离 */ \
/**/ \
double tempDe = getDistance (robots[(*it)].pos.x, robots[(*it)].pos.y, goalX, goalY); \
if (tempDe < distance) { \
index = *it; \
distance = tempDe; \
} \
} \
\
return index; \
} \
while (0) \
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// 上前锋角色
//
// 负责 3, 4, 5, 8, 9, 10 区域,在此区域内将球向敌方球场方向踢
// 尽量将球踢给中间的助攻队员
//
// public
long
RoleVanguardTop::assignRobots (const Robot *robots,
const vector <long> &robotIndexs,
const LastRole &lastRole)
{
//
// 因当前角色为进攻队形的上前锋角色
// 因此选择一个在离 球场右上角 最近的机器人但任此角色
//
FIND_ROBOT (FRIGHTX, FTOP);
}
// public
void
RoleVanguardTop::strategy (Robot &robot,
const AreaInfo *areaInfo,
BallSpeed speed,
BallDirection direction,
BallPower power,
GuardLeak leak,
const Environment *env)
{
/*
上前锋角色进攻
负责区域为 3, 4, 5, 8, 9, 10
1. 当球在其它区域时以球的 X 轴移动, Y 轴为上半场的中间位置
2. 球一旦进入所负责的区域则执行踢球任务 不执行射门任务
射门由助功角色完成
*/
BallArea area = areaInfo->getArea ();
if (area == BA_3 ||
area == BA_4 ||
area == BA_5 ||
area == BA_8 ||
area == BA_9 ||
area == BA_10) {
//if (actKickBall (robot, *env) == false)
actShoot (robot, *env);
return;
}
//
// 跟着球的 X 轴移动, Y 轴为上半场的中间位置
//
double x = 0,
y = FIELD_CENTER_Y + FIELD_HEIGHT / 4;
transform (x, y);
x = env->predictedBall.pos.x;
//
// 如果 X 超过对方小禁区 X 轴,则停留在 对方小禁区 X 轴上
//
double oppSmallForbidX = OPP_SMALL_FORBID_ZONE_X;
BallField fieldInfo = analyseFieldInfo ();
if ((x > oppSmallForbidX && fieldInfo == BF_IS_LEFT) || (x < oppSmallForbidX && fieldInfo == BF_IS_RIGHT)) {
double tempY = 0;
transform (oppSmallForbidX, tempY);
x = oppSmallForbidX;
}
actToPosition (robot, x, y);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// 下前锋角色
//
// public
long
RoleVanguardBottom::assignRobots (const Robot *robots,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -