开发代码过程累积的一点经验
救援仿真的项目代码主要分为rcrs-adf-core-master、rcrs-adf-sample-master、rcrs-server三部分,我们的任务就是看懂以及学会使用里面提供的方法,例如worldinf面的getFireBuildingIDs、getDistance等等。然后,我们便可以去开发自己的代码,将自己的策略实现。
在代码开发方面,我主要针对消防员的行为firefighting和策略buildingdetector。firefighting是消防员的灭火行为策略,主要考虑消防员在灭火过程中出现的问题。Buildingdetector主要是从大局上,让消防员学会怎么选择目标(着火建筑),并能够将火势控制下来,尽可能慢地扩散,并且,不要让火势到达一些危险区域,比如加油站。下面我简单说一下自己对于该份代码的理解和认识。
行为firefighting方面,我们主要实现的是怎么解决关于消防员在灭火过程中的出现的问题,例如:
1、当前消防员正在灭火,可是水箱里水用完了,此时怎么办?注:消防栓只能补水,且补水效率不高;避难所既可以补水,且补水效率高,还可以回复生命值。
①直接到最近的补水点补水即可,不论是避难所还是消防栓。
根据当前生命值做出不同的判断,生命值高就在最近的消防栓或避难所补水,生命值低就在最近的避难所补水。(实现)
因为补水效率不一样,所以可能去最近的消防栓比去避难所补水还慢一点,可以通过比较两个可能的花费周期来选择。(没有实现)
2、当前消防员被卡住,他可以怎么做?
①可能他后面没有障碍,可以向后走。
②可能他周围有着火的建筑,而且在他的灭火范围里,他可以不管当前目标,将最近的着火建筑当做目标,然后灭火。
3、当前消防员的状态不好,怎么办?
①找最近避难所休息。
策略buildingdetector方面,我们主要考虑消防员的分配问题,即消防员怎么找目标。因为该项目机制里有火势过大时,周围建筑会收到火辐射出的能量,当能量到达一定的阀值,便会起火;同时,大火也像现实里一样,很难被扑灭,花费较大,所以为了控制火势,往往会将周围建筑加入考虑范围。目前,针对火势的控制,普遍使用的是凸包算法,即将包围着火建筑的周围一些建筑纳入考虑,这个周围即是凸包包围的范围。
上面就是我对于消防员代码方面的一些思考,当然这只是我们的一些策略,希望大家都能积极思考,想出一些不错的策略。当然,也不要一味地只追求新策略,不看实际的代码,策略的终极目标是代码,如果很难实现代码,一方面可以去提高终极代码能力,另一方面,可以将之前的已经能够运行的代码进行优化。
下面,我根据自己开发代码过程中遇到的一些问题,简单叙述一下一些经验吧。
for (CommunicationMessage message : messageManager.getReceivedMessageList(MessageBuilding.class))//加载信息
{
MessageBuilding mb = (MessageBuilding) message;
Building building = MessageUtil.reflectMessage(this.worldInfo, mb);
if (building.isOnFire())
{
this.targetBuildings.add(building.getID());
}
else
{
this.priorityBuildings.remove(mb.getBuildingID());
this.targetBuildings.remove(mb.getBuildingID());
}
}
for (CommunicationMessage message : messageManager.getReceivedMessageList(MessageFireBrigade.class))//加载信息
{
MessageFireBrigade mfb = (MessageFireBrigade) message;
MessageUtil.reflectMessage(this.worldInfo, mfb);
FireBrigadeInfo info = this.agentInfoMap.get(mfb.getAgentID());
if (info == null)
{
info = new FireBrigadeInfo(mfb.getAgentID());
}
if (currentTime >= info.commandTime + 2)
{
this.agentInfoMap.put(mfb.getAgentID(), this.update(info, mfb));
}
}
for (CommunicationMessage message : messageManager.getReceivedMessageList(CommandFire.class))//消防队得到消息,并将消息的目的地设在priorityBuildings或targetBuildings。
{
CommandFire command = (CommandFire) message;
if (command.getAction() == CommandFire.ACTION_EXTINGUISH && command.isBroadcast())
{
this.priorityBuildings.add(command.getTargetID());
this.targetBuildings.add(command.getTargetID());
}
}
for (CommunicationMessage message : messageManager.getReceivedMessageList(MessageReport.class))//当消息处理后,清除记录
{
MessageReport report = (MessageReport) message;
FireBrigadeInfo info = this.agentInfoMap.get(report.getSenderID());
if (info != null && report.isDone())
{
info.canNewAction = true;
this.priorityBuildings.remove(info.target);
this.targetBuildings.remove(info.target);
info.target = null;
this.agentInfoMap.put(report.getSenderID(), info);
}
}
因为worldinfo里面的getFireBuildingIDs只能得到当前智能体“看到”的世界模型中的着火建筑,通过上面代码,别人可以将自己“看到”的着火建筑发给你,从而你的世界模型中也就有了那个着火建筑。这个对于消防员来说,这样可以更好得到地图上的着火建筑,从而有便于后续策略。
2、要熟悉StandardEntity、EntityID、Entity、StandardEntityURN各自的含义及相应的关系。