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

📄 robotrole.cpp

📁 robot fira SimuroSot 5vs5 (仿真)
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************************************
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 + -