Created
July 16, 2014 12:53
-
-
Save thuzhf/6b79554d243228e0d437 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using xna = Microsoft.Xna.Framework; | |
using URWPGSim2D.Common; | |
using URWPGSim2D.StrategyLoader; | |
using URWPGSim2D.Core; | |
namespace URWPGSim2D.Strategy | |
{ | |
public class Strategy : MarshalByRefObject, IStrategy | |
{ | |
#region reserved code never be changed or removed | |
/// <summary> | |
/// override the InitializeLifetimeService to return null instead of a valid ILease implementation | |
/// to ensure this type of remote object never dies | |
/// </summary> | |
/// <returns>null</returns> | |
public override object InitializeLifetimeService() | |
{ | |
//return base.InitializeLifetimeService(); | |
return null; // makes the object live indefinitely | |
} | |
#endregion | |
/// <summary> | |
/// 决策类当前对象对应的仿真使命参与队伍的决策数组引用 第一次调用GetDecision时分配空间 | |
/// </summary> | |
private Decision[] decisions = null; | |
private int[] times = null; | |
private xna.Vector3[] corner = null; | |
private int onArea; | |
private float offenceLine; | |
private float defenceLine; | |
private bool debug = true; | |
private float R = 0f; | |
private bool dribble(Mission mission, int teamId, int fishId, xna.Vector3 targetPoint, float targetTangle, xna.Vector3 tempTarget, int v1, int v2) | |
{ | |
xna.Vector3 fishHeadPosion = mission.TeamsRef[teamId].Fishes[fishId].PolygonVertices[0]; | |
xna.Vector3 ballPosition = mission.EnvRef.Balls[0].PositionMm; | |
if (xna.Vector3.Distance(targetPoint, fishHeadPosion) >= 1.8 * R) | |
{ | |
//StrategyHelper.Helpers.PoseToPose(ref decisions[fishId], mission.TeamsRef[teamId].Fishes[fishId], targetPoint, targetTangle, 20.0f, 1.5f * R, mission.CommonPara.MsPerCycle, ref times[fishId]); | |
//StrategyHelper.Helpers.PoseToPose(ref decisions[i], mission.TeamsRef[teamId].Fishes[i], targetPoint, targetDirection, 30.0f, 8 * b.RadiusMm, mission.CommonPara.MsPerCycle, ref times) | |
StrategyHelper.Helpers.Dribble(ref decisions[fishId], mission.TeamsRef[teamId].Fishes[fishId], targetPoint, targetTangle, 10, 15, 100, 14, 12, 10, mission.CommonPara.MsPerCycle, true); ; | |
} | |
else | |
{ | |
times[fishId] = 0; | |
StrategyHelper.Helpers.Dribble(ref decisions[fishId], mission.TeamsRef[teamId].Fishes[fishId], targetPoint, targetTangle, 5, 10, 100, v1, v2, 10, mission.CommonPara.MsPerCycle, false); | |
} | |
if (xna.Vector3.Distance(tempTarget, ballPosition) <= 50f) | |
{ | |
return true; | |
} | |
return false; | |
} | |
private bool run(Mission mission, int teamID, int fishID, xna.Vector3 targetPoint, float targetTangle) | |
{ | |
xna.Vector3 fishPosition = mission.TeamsRef[teamID].Fishes[fishID].PositionMm; | |
//Console.WriteLine("run target: " + targetPoint.ToString() + " " + (targetTangle / Math.PI * 180).ToString()); | |
StrategyHelper.Helpers.Dribble(ref decisions[fishID], mission.TeamsRef[teamID].Fishes[fishID], targetPoint, targetTangle, 5, 10, 150, 14, 12, 10, mission.CommonPara.MsPerCycle, false); | |
if (xna.Vector3.Distance(targetPoint, fishPosition) <= 50f) | |
{ | |
return true; | |
} | |
return false; | |
} | |
private int getId(int myId) | |
{ | |
if (myId != 0) return myId + 1; | |
else return 0; | |
} | |
private void motionless(int fishId) | |
{ | |
decisions[fishId].VCode = 0; | |
decisions[fishId].TCode = 7; | |
} | |
private void assert(bool condtion, String info) | |
{ | |
if (!condtion) | |
{ | |
Console.WriteLine("assert fail: " + info); | |
if (debug) Environment.Exit(-1); | |
} | |
} | |
private float getAngle(xna.Vector3 v) | |
{ | |
return xna.MathHelper.ToRadians(StrategyHelper.Helpers.GetAngleDegree(v)); | |
} | |
private bool atLeft(xna.Vector3 v, xna.Vector3 p) | |
{ | |
float av = getAngle(v); | |
float ap = getAngle(p); | |
if (av * ap < 0) return !(atLeft(v, -p)); | |
else if (av - ap >= 0) return true; | |
else return false; | |
} | |
private xna.Vector3 getUnit(float angle) | |
{ | |
return (new xna.Vector3(Convert.ToSingle(Math.Cos(angle)), 0f, Convert.ToSingle(Math.Sin(angle)))); | |
} | |
private int getAngleLoc(Mission mission, int teamId, int fishId, float e) | |
{ | |
xna.Vector3 ballPosition = mission.EnvRef.Balls[0].PositionMm; | |
xna.Vector3[] fishHeadPosition = new xna.Vector3[3]; | |
fishHeadPosition[0] = mission.TeamsRef[teamId].Fishes[getId(0)].PositionMm; | |
fishHeadPosition[1] = mission.TeamsRef[teamId].Fishes[getId(1)].PositionMm; | |
fishHeadPosition[2] = mission.TeamsRef[teamId].Fishes[getId(2)].PositionMm; | |
int num = 0; | |
if (xna.Vector3.Distance(fishHeadPosition[fishId], ballPosition) > e) return -1; | |
for (int i = 0; i < 3; i++) | |
{ | |
if (i == fishId) continue; | |
if (atLeft(fishHeadPosition[fishId] - ballPosition, fishHeadPosition[i] - ballPosition) && (xna.Vector3.Distance(fishHeadPosition[i], ballPosition) <= e)) | |
{ | |
num++; | |
} | |
} | |
return num; | |
} | |
private int getNearNum(Mission mission, int teamId, float e) | |
{ | |
xna.Vector3 ballPosition = mission.EnvRef.Balls[0].PositionMm; | |
xna.Vector3[] fishHeadPosition = new xna.Vector3[3]; | |
fishHeadPosition[0] = mission.TeamsRef[teamId].Fishes[getId(0)].PositionMm; | |
fishHeadPosition[1] = mission.TeamsRef[teamId].Fishes[getId(1)].PositionMm; | |
fishHeadPosition[2] = mission.TeamsRef[teamId].Fishes[getId(2)].PositionMm; | |
int num = 0; | |
for (int i = 0; i < 3; i++) | |
{ | |
if (xna.Vector3.Distance(fishHeadPosition[i], ballPosition) <= e) num++; | |
} | |
return num; | |
} | |
private int getArea(xna.Vector3 v, int onArea) | |
{ | |
/* | |
* 1 ------------------------7 | |
* 2 ---- 4 ---5---6---------8 | |
* 3-------------------------9 | |
*/ | |
if (onArea == 0) | |
{ | |
if (v.X <= -1700f) | |
{ | |
if (v.Z <= -500f) return 1; | |
else if (v.Z <= 500f) return 2; | |
else return 3; | |
} | |
else if (v.X <= -500f) return 4; | |
else if (v.X <= 500f) return 5; | |
else if (v.X <= 1700f) return 6; | |
else | |
{ | |
if (v.Z <= -500f) return 7; | |
else if (v.Z <= 500f) return 8; | |
else return 9; | |
} | |
} | |
else return 10 - getArea(v, 1 - onArea); | |
} | |
private xna.Vector3 getNearestCorner(xna.Vector3 v) | |
{ | |
float dis = 1e8f; | |
int index = 0; | |
for (int i = 0; i < 4; i++) | |
{ | |
if (xna.Vector3.Distance(v, corner[i]) < dis) | |
{ | |
dis = xna.Vector3.Distance(v, corner[i]); | |
index = i; | |
} | |
} | |
return corner[index]; | |
} | |
/// <summary> | |
/// 获取队伍名称 在此处设置参赛队伍的名称 | |
/// </summary> | |
/// <returns>队伍名称字符串</returns> | |
public string GetTeamName() | |
{ | |
return "THU"; | |
} | |
/// <summary> | |
/// 获取当前仿真使命(比赛项目)当前队伍所有仿真机器鱼的决策数据构成的数组 | |
/// </summary> | |
/// <param name="mission">服务端当前运行着的仿真使命Mission对象</param> | |
/// <param name="teamId">当前队伍在服务端运行着的仿真使命中所处的编号 | |
/// 用于作为索引访问Mission对象的TeamsRef队伍列表中代表当前队伍的元素</param> | |
/// <returns>当前队伍所有仿真机器鱼的决策数据构成的Decision数组对象</returns> | |
public Decision[] GetDecision(Mission mission, int teamId) | |
{ | |
// 决策类当前对象第一次调用GetDecision时Decision数组引用为null | |
if (decisions == null) | |
{// 根据决策类当前对象对应的仿真使命参与队伍仿真机器鱼的数量分配决策数组空间 | |
decisions = new Decision[mission.CommonPara.FishCntPerTeam]; | |
times = new int[mission.CommonPara.FishCntPerTeam]; | |
for (int i = 0; i < mission.CommonPara.FishCntPerTeam; i++) | |
{ | |
times[i] = 0; | |
} | |
corner = new xna.Vector3[4]; | |
corner[0] = new xna.Vector3(-2100f, 0f, -1500f); | |
corner[1] = new xna.Vector3(-2100f, 0f, 1500f); | |
corner[2] = new xna.Vector3(2100f, 0f, -1500f); | |
corner[3] = new xna.Vector3(2100f, 0f, 1500f); | |
R = mission.EnvRef.Balls[0].RadiusMm; | |
} | |
#region 决策计算过程 需要各参赛队伍实现的部分 | |
#region 策略编写帮助信息 | |
//====================我是华丽的分割线====================// | |
//======================策略编写指南======================// | |
//1.策略编写工作直接目标是给当前队伍决策数组decisions各元素填充决策值 | |
//2.决策数据类型包括两个int成员,VCode为速度档位值,TCode为转弯档位值 | |
//3.VCode取值范围0-14共15个整数值,每个整数对应一个速度值,速度值整体但非严格递增 | |
//有个别档位值对应的速度值低于比它小的档位值对应的速度值,速度值数据来源于实验 | |
//4.TCode取值范围0-14共15个整数值,每个整数对应一个角速度值 | |
//整数7对应直游,角速度值为0,整数6-0,8-14分别对应左转和右转,偏离7越远,角度速度值越大 | |
//5.任意两个速度/转弯档位之间切换,都需要若干个仿真周期,才能达到稳态速度/角速度值 | |
//目前运动学计算过程决定稳态速度/角速度值接近但小于目标档位对应的速度/角速度值 | |
//6.决策类Strategy的实例在加载完毕后一直存在于内存中,可以自定义私有成员变量保存必要信息 | |
//但需要注意的是,保存的信息在中途更换策略时将会丢失 | |
//====================我是华丽的分割线====================// | |
//=======策略中可以使用的比赛环境信息和过程信息说明=======// | |
//场地坐标系: 以毫米为单位,矩形场地中心为原点,向右为正X,向下为正Z | |
// 负X轴顺时针转回负X轴角度范围为(-PI,PI)的坐标系,也称为世界坐标系 | |
//mission.CommonPara: 当前仿真使命公共参数 | |
//mission.CommonPara.FishCntPerTeam: 每支队伍仿真机器鱼数量 | |
//mission.CommonPara.MsPerCycle: 仿真周期毫秒数 | |
//mission.CommonPara.RemainingCycles: 当前剩余仿真周期数 | |
//mission.CommonPara.TeamCount: 当前仿真使命参与队伍数量 | |
//mission.CommonPara.TotalSeconds: 当前仿真使命运行时间秒数 | |
//mission.EnvRef.Balls: | |
//当前仿真使命涉及到的仿真水球列表,列表元素的成员意义参见URWPGSim2D.Common.Ball类定义中的注释 | |
//mission.EnvRef.FieldInfo: | |
//当前仿真使命涉及到的仿真场地,各成员意义参见URWPGSim2D.Common.Field类定义中的注释 | |
//mission.EnvRef.ObstaclesRect: | |
//当前仿真使命涉及到的方形障碍物列表,列表元素的成员意义参见URWPGSim2D.Common.RectangularObstacle类定义中的注释 | |
//mission.EnvRef.ObstaclesRound: | |
//当前仿真使命涉及到的圆形障碍物列表,列表元素的成员意义参见URWPGSim2D.Common.RoundedObstacle类定义中的注释 | |
//mission.TeamsRef[teamId]: | |
//决策类当前对象对应的仿真使命参与队伍(当前队伍) | |
//mission.TeamsRef[teamId].Para: | |
//当前队伍公共参数,各成员意义参见URWPGSim2D.Common.TeamCommonPara类定义中的注释 | |
//mission.TeamsRef[teamId].Fishes: | |
//当前队伍仿真机器鱼列表,列表元素的成员意义参见URWPGSim2D.Common.RoboFish类定义中的注释 | |
//mission.TeamsRef[teamId].Fishes[i].PositionMm和PolygonVertices[0],BodyDirectionRad,VelocityMmPs, | |
// AngularVelocityRadPs,Tactic: | |
//当前队伍第i条仿真机器鱼鱼体矩形中心和鱼头顶点在场地坐标系中的位置(用到X坐标和Z坐标),鱼体方向,速度值, | |
// 角速度值,决策值 | |
//====================我是华丽的分割线====================// | |
//========================典型循环========================// | |
//for (int i = 0; i < mission.CommonPara.FishCntPerTeam; i++) | |
//{ | |
// decisions[i].VCode = 0; // 静止 | |
// decisions[i].TCode = 7; // 直游 | |
//} | |
//====================我是华丽的分割线====================// | |
#endregion | |
//请从这里开始编写代码 | |
xna.Vector3 fishPosition; | |
xna.Vector3 fishHeadPosition; | |
xna.Vector3 ballPosition = mission.EnvRef.Balls[0].PositionMm; | |
float fishDir; | |
int ballArea; | |
xna.Vector3 targetPoint, tempTarget, direct; | |
float targetTangle; | |
int id; | |
xna.Vector3 goal; | |
float nearThreshold = 300f; | |
if (mission.TeamsRef[teamId].Para.MyHalfCourt == HalfCourt.LEFT) onArea = 0; | |
else onArea = 1; | |
if (onArea == 0) | |
{ | |
offenceLine = 500f; | |
defenceLine = -500f; | |
goal = new xna.Vector3(2250f, 0f, 0f); | |
} | |
else | |
{ | |
offenceLine = -500f; | |
defenceLine = 500f; | |
goal = new xna.Vector3(-2250f, 0f, 0f); | |
} | |
assert(onArea == teamId, "onArea == teamId"); | |
ballArea = getArea(ballPosition, onArea); | |
for (int i = 0; i < 3; i++) | |
{ | |
id = getId(i); | |
fishDir = mission.TeamsRef[teamId].Fishes[id].BodyDirectionRad; | |
fishPosition = mission.TeamsRef[teamId].Fishes[id].PositionMm; | |
fishHeadPosition = mission.TeamsRef[teamId].Fishes[id].PolygonVertices[0]; | |
if (ballArea == 1 || ballArea == 3) | |
{ | |
tempTarget = getNearestCorner(ballPosition); | |
Console.WriteLine("go to Corner " + tempTarget.ToString()); | |
direct = tempTarget - ballPosition; | |
direct = direct / xna.Vector3.Distance(tempTarget, ballPosition); | |
targetPoint = ballPosition - direct * 0.9f * R; | |
targetTangle = getAngle(tempTarget - targetPoint); | |
dribble(mission, teamId, id, targetPoint, targetTangle, tempTarget, 12, 10); | |
} | |
else | |
{ | |
tempTarget = goal; | |
direct = tempTarget - ballPosition; | |
direct = direct / xna.Vector3.Distance(tempTarget, ballPosition); | |
//Console.WriteLine("direct " + direct+" "+getAngle(direct).ToString() + " " + getUnit(getAngle(direct)).ToString() + " " + (getAngle(direct) + xna.MathHelper.ToRadians(30f)).ToString() + " " + getUnit(getAngle(direct) + xna.MathHelper.ToRadians(30f)).ToString()); | |
if (getNearNum(mission, teamId, nearThreshold) == 3 && getAngleLoc(mission, teamId, i, nearThreshold) == 2) | |
{ | |
direct = getUnit(getAngle(direct) + xna.MathHelper.ToRadians(30f)); | |
} | |
if (getNearNum(mission, teamId, nearThreshold) == 2 && getAngleLoc(mission, teamId, i, nearThreshold) == 1) | |
{ | |
direct = getUnit(getAngle(direct) + xna.MathHelper.ToRadians(20f)); | |
} | |
if (getNearNum(mission, teamId, nearThreshold) == 3 && getAngleLoc(mission, teamId, i, nearThreshold) == 0) | |
{ | |
direct = getUnit(getAngle(direct) + xna.MathHelper.ToRadians(-30f)); | |
} | |
if (getNearNum(mission, teamId, nearThreshold) == 2 && getAngleLoc(mission, teamId, i, nearThreshold) == 0) | |
{ | |
direct = getUnit(getAngle(direct) + xna.MathHelper.ToRadians(-20f)); | |
} | |
Console.WriteLine("near " + getNearNum(mission, teamId, nearThreshold).ToString() + " " + getAngleLoc(mission, teamId, i, nearThreshold).ToString()); | |
targetPoint = ballPosition - direct * 0.9f * R; | |
targetTangle = getAngle(tempTarget - targetPoint); | |
Console.WriteLine("fish " + i.ToString() + " " + targetTangle.ToString() + " " + targetPoint.ToString()); | |
dribble(mission, teamId, id, targetPoint, targetTangle, tempTarget, 12, 10); | |
} | |
if (i == 1) //防守鱼 | |
{ | |
if (ballArea > 5) | |
{ | |
targetPoint = new xna.Vector3(offenceLine * 2 / 3, 0f, ballPosition.Z); | |
targetTangle = getAngle(targetPoint - fishHeadPosition); | |
run(mission, teamId, id, targetPoint, targetTangle); | |
} | |
} | |
else if (i == 2) //进攻鱼 | |
{ | |
if (ballArea < 5) | |
{ | |
targetPoint = new xna.Vector3(defenceLine * 2 / 3, 0f, ballPosition.Z); | |
targetTangle = getAngle(targetPoint - fishHeadPosition); | |
run(mission, teamId, id, targetPoint, targetTangle); | |
} | |
} | |
} | |
Console.WriteLine("onArea " + onArea.ToString() + " " + ballArea.ToString()); | |
//Console.WriteLine("AnglLoc " + getAngleLoc(mission, teamId, 0, nearThreshold).ToString() + " " + getAngleLoc(mission, teamId, 1, nearThreshold).ToString() + " " + getAngleLoc(mission, teamId, 2, nearThreshold).ToString()); | |
#endregion | |
motionless(1); | |
motionless(4); | |
return decisions; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment