//AIInfo.h
#include "Tank.h"
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include <math.h>
#include<vector>
#include <string.h>
extern Order TankDir[5];
extern Point NextStep[5];
extern short mymap[5][21+2][21+2];
extern short Distance(short row1,short col1,short row2,short col2);
extern short Distance(Point &point1,Point &point2); //返回两点间的距离
extern short WhoNearMe(DataForAI &data); //返回视野内敌方生命值最少的AI的ID号
extern short FoeNum(void); //返回视野内敌方AI数目
extern Point * GetRoute(short sourcerow,short sourcecol,short goalrow,short goalcol,
MapCell (*map)[21+2],short &stepnum);
extern bool GetResource(MapCell (*map)[MAP_HEIGHT+2],Point *source,short &ResourceRow,short &ResourceCol,
short my_row,short my_col,short my_flag);
extern short Jook(MapCell (*map)[MAP_HEIGHT+2],short my_row,short my_col,short friend_row,short friend_col);
extern short Encounter(short myID,TankData *tank,Order *TankDir=TankDir);
//AIInfo.cpp
//如果两个点为同一点位置,返回的是1,相差1的返回2……
short Distance(Point &point1,Point &point2) //返回两点间的距离
{
short x,y;
short distance=-1;
x=abs(point1.col-point2.col);
y=abs(point1.row-point2.row);
distance=x+y+1;
return distance;
}
short Distance(short row1,short col1,short row2,short col2)
{
Point point1;
Point point2;
point1.row=row1;
point1.col=col1;
point2.row=row2;
point2.col=col2;
return Distance(point1,point2);
}
short WhoNearMe(DataForAI &data) //返回视野内敌方生命值最少的AI的ID号
{
int n;
int FoeNum=MAX_TANK_NUM/2;
short foerow,foecol;
short id=-1,id1=-1;
short shutlen=data.tank[data.myID].range;
short attackvalue=data.tank[data.myID].attack;
// short shuttime,shuttime1; //射程内可进行的射击次数
if(data.myID>=5)n=0; //敌方ID小于5
else n=5;
Point mypoint,foepoint;
mypoint.col=data.tank[data.myID].col;
mypoint.row=data.tank[data.myID].row;
for(int i=0;i<FoeNum;i++)
{
foerow=data.tank[i+n].row;
foecol=data.tank[i+n].col;
if(foerow!=-2 && foecol!=-2) //坦克在视野内
{
if(data.map[foerow][foecol].whoIsHere==-1)
continue;
foepoint.col=foecol;
foepoint.row=foerow;
if(data.tank[data.myID].range>=(Distance(mypoint,foepoint)-1))
{
id1=i+n;
if(id==-1)
id= id1;
else //有两台以上在射程内,根据生命值、与自己距离、敌我攻击力等进行判断
{
if(attackvalue>=data.tank[id].life && attackvalue>=data.tank[id1].life)
{
short distance=Distance(data.tank[id].row,data.tank[id].col,
data.tank[data.myID].row,data.tank[data.myID].col);
short distance1=Distance(data.tank[id1].row,data.tank[id1].col,
data.tank[data.myID].row,data.tank[data.myID].col);
if(distance>distance1)
id= id1;
}
else if(attackvalue>=data.tank[id].life)
{
id= id;
}
else if(attackvalue>=data.tank[id1].life)
{
id= id1;
}
else if(data.tank[id].life>data.tank[id1].life) //id保存最少血量的坦克
id=id1;
}
}
}
}
return id;
}
//获得离goalrow,goalcol最近的资源路径,路径存放在route中,大小为stepnum
Point * GetRoute(short sourcerow,short sourcecol,short goalrow,short goalcol,
MapCell (*map)[21+2],short &stepnum)
{
Point *route;
short map2[21+2][21+2];
std::vector <Point> point; //动态数组,保存分岔的点
memset(map2,23*23+5,sizeof(map2)); //数组全部置位高值 *23*23
map2[sourcerow][sourcecol]=0;
Point sourcepoint;
Point mypoint;
short row,col;
short num=0;
row=sourcerow;
col=sourcecol;
sourcepoint.row=row;
sourcepoint.col=col;
point.push_back(sourcepoint);
while(point.size())
{
//比当前点权值大于1的分支数,如果大于1则存储当前点
num=0;
if((map2[row+1][col]-map2[row][col])>1 && map[row+1][col].type!=STONE) //下一行
{
num++;
}
if((map2[row-1][col]-map2[row][col])>1 && map[row-1][col].type!=STONE) //上一行
{
num++;
}
if((map2[row][col+1]-map2[row][col])>1 && map[row][col+1].type!=STONE) //右列
{
num++;
}
if((map2[row][col-1]-map2[row][col])>1 && map[row][col-1].type!=STONE) //左列
{
num++;
}
if(num>1) //两个以上分支,保存当前点
{
mypoint.row=row;
mypoint.col=col;
point.push_back(mypoint);
}
if((map2[row+1][col]-map2[row][col])>1 && map[row+1][col].type!=STONE) //路径较长,被替换
{
map2[row+1][col]=map2[row][col]+1;
row++;
}
else if((map2[row-1][col]-map2[row][col]>1) && map[row-1][col].type!=STONE)
{
map2[row-1][col]=map2[row][col]+1;
row--;
}
else if((map2[row][col+1]-map2[row][col]>1) && map[row][col+1].type!=STONE)
{
map2[row][col+1]=map2[row][col]+1;
col++;
}
else if((map2[row][col-1]-map2[row][col]>1) && map[row][col-1].type!=STONE)
{
map2[row][col-1]=map2[row][col]+1;
col--;
}
//四边的单元格权值都小于或等于当前权值的下一权值,即最大的权值也相当于下一权值,
//此时回到最后一个分支点,走向另一分支 .并删除最后分支,重新检查是否分支点还是一个分支?
if( (map2[row+1][col]<=(map2[row][col]+1) || map[row+1][col].type==STONE)&&
(map2[row-1][col]<=(map2[row][col]+1) || map[row-1][col].type==STONE) &&
(map2[row][col+1]<=(map2[row][col]+1) || map[row][col+1].type==STONE)&&
(map2[row][col-1]<=(map2[row][col]+1) || map[row][col-1].type==STONE)
)
{
short end=-1;
end=point.size()-1;
mypoint=point.at(end);
point.pop_back();
row=mypoint.row;
col=mypoint.col;
}
}
stepnum=map2[goalrow][goalcol];
route=new Point[stepnum+1];
row=goalrow;
col=goalcol;
route[stepnum].row=row;
route[stepnum].col=col;
for(int i=stepnum-1;i>=0;i--)
{
if((map2[row][col]-map2[row+1][col])==1) //寻找前一步,前一步权值比当前权值小1
{
row++;
}
else if((map2[row][col]-map2[row-1][col])==1)
{
row--;
}
else if((map2[row][col]-map2[row][col+1])==1)
{
col++;
}
else if((map2[row][col]-map2[row][col-1])==1)
{
col--;
}
route[i].row=row; //
route[i].col=col; //
}
//route->row=row;
//route->col=col;
return route;
}
//获得一个最近的没被己方占领的资源和前往该资源的下一步,如果没有,则返回FALSE
bool GetResource(MapCell (*map)[MAP_HEIGHT+2],Point *source,short &ResourceRow,short &ResourceCol,
short my_row,short my_col,short my_flag)
{
short distance[MAX_SOURCE_NUM];
short mindistance,minID=-1;
memset(distance,23+23+1,sizeof(distance));
mindistance=distance[0];
short sourcetype;
for(int i=0;i<MAX_SOURCE_NUM;i++)
{
short row,col;
row=source[i].row;
col=source[i].col;
if(!((row>0 && row<(MAP_HEIGHT+2)) && (col>0 && col<(MAP_WIDTH+2)))) //如果不在区域内
continue;
sourcetype=map[row][col].isHereSource;
if(my_flag==RED) //自己是红方
{
if(sourcetype==BlueSource || sourcetype==NeutralSource)
{
distance[i]=Distance(source[i].row,source[i].col,my_row,my_col);
if(mindistance>distance[i])
{
mindistance=distance[i];
minID=i;
}
}
}
else //自己为蓝方
{
if(sourcetype==RedSource || sourcetype==NeutralSource)//
{
distance[i]=Distance(source[i].row,source[i].col,my_row,my_col);
if(mindistance>distance[i])
{
mindistance=distance[i];
minID=i;
}
}
}
}
if(minID==-1)
{
// printf("Never Found!\n");
return false;
}
ResourceRow=source[minID].row;
ResourceCol=source[minID].col;
return true;
}
//闪避
short Jook(MapCell (*map)[MAP_HEIGHT+2],short my_row,short my_col,short friend_row,short friend_col)
{
//测试哪个方向没有坦克,没有石头
if(map[my_row][my_col+1].type!=STONE && map[my_row][my_col+1].whoIsHere==-1)
{
if(map[my_row][my_col+1].type==PERVIOUS) //可通过
{
return GORIGHT;
}
}
else if(map[my_row][my_col-1].type!=STONE && map[my_row][my_col-1].whoIsHere==-1 )
{
if(map[my_row][my_col-1].type==PERVIOUS) //可通过
{
return GOLEFT;
}
}
else if(map[my_row+1][my_col].type!=STONE && map[my_row+1][my_col].whoIsHere==-1)
{
if(map[my_row+1][my_col].type==PERVIOUS) //可通过
{
return GODOWN;
}
}
else if(map[my_row-1][my_col].type!=STONE && map[my_row-1][my_col].whoIsHere==-1)
{
if(map[my_row-1][my_col].type==PERVIOUS) //可通过
{
return GOUP;
}
}
return STOP;
}
//获得与自己相遭遇的坦克ID
short Encounter(short myID,TankData *tank,Order *TankDir)
{
short my_row,my_col;
short row,col;
my_row=tank[myID].row;
my_col=tank[myID].col;
for(int i=0;i<MAX_TANK_NUM;i++)
{
row=tank[i].row;
col=tank[i].col;
if(Distance(my_row,my_col,row,col)==2) //距离为1,两坦克相接触
{
if(tank[i].flag==tank[myID].flag && i!=myID)
{ //正在坦克的前进方向上,则闪避
//双方互相占据了对方的下一步,则闪避
if((NextStep[i%5].row==my_row && NextStep[i%5].col==col) &&
(NextStep[myID%5].row==row && NextStep[myID%5].col==col))
return i;
}
}
}
return -1;
}
//请勿修改以上头文件
/*
您可以在这里添加您所需头文件
*/
/*
您可以在这里添加您的自定义函数
*/
Order TankDir[5]; //坦克方向保存
Point TankGoal[5]; //保存坦克目标
Point *route[5]; //每个坦克的路径
Point *oldroute[5];
Point NextStep[5]; //保存下一步位置,用作躲闪的依据
short mymap[5][21+2][21+2]; //每个坦克保存一个当前位置通往各处的最短路径图
short num[5]={-1,-1,-1,-1,-1};
short numold[5];
//平台0回合时调用此函数获取AI名称及坦克类型信息,请勿修改此函数声明。
extern "C" InitiateInfo chooseType()
{
extern Order TankDir[5];
InitiateInfo Info;
Info.tank[0]=Striker;
Info.tank[1]=Striker;
Info.tank[2]=Striker;
Info.tank[3]=Striker;
Info.tank[4]=Striker;
strcpy(Info.aiName,"Dong"); //AI名请勿使用中文。
return Info;
}
//平台从第1回合开始调用此函数获得每回合指令,请勿修改此函数声明。
extern "C" Order makeOrder(DataForAI data)
{
//定义Order类型变量用于返回
Order order;
int my_row,my_col;
int test_row,test_col;
short AttrackFoe; //敌人ID
short Resourcerow=-1,Resourcecol=-1;
MapCell tmpmap[MAP_HEIGHT+2][MAP_WIDTH +2];
memcpy(tmpmap,data.map,sizeof(tmpmap));
my_row = data.tank[data.myID].row; //行
my_col = data.tank[data.myID].col; //列
// printf("\nRound: %d\n",data.round);
// printf("ID: %d\n",data.myID);
bool jook=false;
do{
jook=false;
if(num[data.myID%5]==0) delete[] (oldroute[data.myID%5]);
if(GetResource(data.map,data.source,Resourcerow,Resourcecol,my_row,my_col,data.myFlag))
{
route[data.myID%5]=GetRoute(my_row,my_col,Resourcerow,Resourcecol,data.map,num[data.myID%5]); //寻径
oldroute[data.myID%5]=route[data.myID%5];
numold[data.myID%5]=num[data.myID%5];
route[data.myID%5]++; //自1开始,0位置为原点
//printf("OK1\n");
TankGoal[(data.myID)%5].row=Resourcerow;
TankGoal[(data.myID)%5].col=Resourcecol;
for(int i=0;i<5;i++)
{
//如果两目标相同,则路径较长的坦克改变目标
if(TankGoal[i].row==TankGoal[(data.myID)%5].row && TankGoal[i].col==TankGoal[(data.myID)%5].col)
{
//有比自身路径段的友军,则重新寻径,如果路径长相等,则ID值大的寻径
if(numold[i]<numold[data.myID%5] || (numold[i]==numold[data.myID%5] && i<(data.myID%5)) )
{
//把已占用的目标标记为无矿点,再次搜寻地图
data.map[TankGoal[i].row][TankGoal[i].col].isHereSource=NotSource;
num[data.myID%5]=0; //删除数组,重新选择路径
jook=true;
break;
}
else jook=false;
}
}
}
else //没有找到资源
{
if(jook==false)
{
if(GetResource(tmpmap,data.source,Resourcerow,Resourcecol,my_row,my_col,data.myFlag))
{
route[data.myID%5]=GetRoute(my_row,my_col,Resourcerow,Resourcecol,data.map,num[data.myID%5]); //寻径
oldroute[data.myID%5]=route[data.myID%5];
numold[data.myID%5]=num[data.myID%5];
route[data.myID%5]++; //自1开始,0位置为原点
TankGoal[(data.myID)%5].row=Resourcerow;
TankGoal[(data.myID)%5].col=Resourcecol;
}
}
}
}while(jook);
NextStep[data.myID%5].row =route[data.myID%5]->row; //确定下一步
NextStep[data.myID%5].col =route[data.myID%5]->col;
// printf("Goal row= %d, col= %d\n",TankGoal[data.myID%5].row,TankGoal[data.myID%5].col);
// printf("Next Step :row= %d col= %d\n",NextStep[data.myID%5].row,NextStep[data.myID%5].col);
//恢复被修改的地图
memcpy(data.map,tmpmap,sizeof(tmpmap));
//检测视野内敌人
AttrackFoe=WhoNearMe(data);
if(AttrackFoe!=-1)
{
order.type=FIRE;
order.row=data.tank[AttrackFoe].row;
order.col=data.tank[AttrackFoe].col;
return order;
}
/* */
//检测坦克相遇
short EncounterTankID=Encounter(data.myID,data.tank);
if(EncounterTankID!=-1) //两坦克相遇则先闪避
{
if(EncounterTankID>data.myID || 1) //ID小的坦克优先级低,闪避
{
order.type=(OrderType)Jook(data.map,my_row,my_col,data.tank[EncounterTankID].row,data.tank[EncounterTankID].col);
}
else if(EncounterTankID<data.myID)
{
//如果判断对方已无再闪的空间,则自己躲闪
if(STOP==(OrderType)Jook(data.map,data.tank[EncounterTankID].row,data.tank[EncounterTankID].col,my_row,my_col))
{
order.type=(OrderType)Jook(data.map,my_row,my_col,data.tank[EncounterTankID].row,data.tank[EncounterTankID].col);
}
}
return order;
}
/**/
//按照路径行走
if(route[data.myID%5]->row-my_row==1)
{
if(data.map[my_row+1][my_col].type==BRICK || //遇到可破坏的障碍
data.map[my_row+1][my_col].type==BREAKBRICK)
{
order.type=FIRE;
order.row=my_row+1;
order.col=my_col;
}
else order.type=GODOWN;
}
else if(route[data.myID%5]->row-my_row==-1)
{
if(data.map[my_row-1][my_col].type==BRICK || //遇到可破坏的障碍
data.map[my_row-1][my_col].type==BREAKBRICK)
{
order.type=FIRE;
order.row=my_row-1;
order.col=my_col;
}
else order.type=GOUP;
}
else if(route[data.myID%5]->col-my_col==1)
{
if(data.map[my_row][my_col+1].type==BRICK || //遇到可破坏的障碍
data.map[my_row][my_col+1].type==BREAKBRICK)
{
order.type=FIRE;
order.row=my_row;
order.col=my_col+1;
}
else order.type=GORIGHT;
}
else if(route[data.myID%5]->col-my_col==-1)
{
if(data.map[my_row][my_col-1].type==BRICK || //遇到可破坏的障碍
data.map[my_row][my_col-1].type==BREAKBRICK)
{
order.type=FIRE;
order.row=my_row;
order.col=my_col-1;
}
else order.type=GOLEFT;
}
if(order.type!=FIRE && order.type != STOP)
{
TankDir[data.myID%5].type=order.type;
}
return order;
}