//monkey doctor
#include"AI.h"
#include"Constants.h"
#include"Structures.h"
#include<iostream>
#include<vector>
#include<list>
#include<chrono>
#include<malloc.h>
#include<stdexcept>
#include<cstdio>
#include<cstdlib>
#include<random>
using namespace std;
//无符号整数
typedef unsigned char u8;
typedef unsigned short int u16;
typedef unsigned int u32;
typedef unsigned long long int u64;
//重要设置
#define MULTIPLE_PLAYER_MODE_ //用这个宏来选择游戏模式:多个玩家还是单个
extern const THUAI4::JobType playerJob = THUAI4::JobType::Job4; //选手职业,选手 !!必须!! 定义此变量来选择职业
extern const bool asynchronous = true; //我的写法必须为true
//时间模块
u64 startTime; //游戏起始时间
#define NOW std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now ().time_since_epoch ()).count ()
#define EPOCHS_SINCE_START (((NOW) - startTime) / 50) //以50ms为单位的时间
#define TIME_SINCE_START (NOW - startTime) //以ms为单位的时间
//特殊指针
typedef vector<shared_ptr<const THUAI4::Wall>> WALLS_PTR;
//常数
constexpr inline double PI = 3.14159265358979323846; //常数PI
constexpr inline double twoPI = 2 * PI;
#define SQRT_2 1.4142135623730951
#define radiusInCells 5
#define radiusInCellsSquared 25
#define sightRadius 5000
//随机数引擎
default_random_engine e;
uniform_real_distribution<double> rd(0, twoPI);
//重要的全局变量
THUAI4::Character self; //自己的信息
THUAI4::ColorType teamColor = THUAI4::ColorType::None; //本队的颜色
u32 teamScore = 1;
u32 PlayerNum = 4; //本局游戏的玩家数量
//地图相关
static u8 Map[50][50]; //基本的地图数据
static double MapValue[50][50]; //地图评分
static int lastExplorationTime[50][50]; //上次探索时间
int lastAttackTimes[50][50]; //上次攻击时间,防止重复攻击
void InitMap(); //初始化两个地图
//查看地图状态使用的宏
#define isWall(x,y) (Map[x][y] & 1)
#define isBirthPoint(x,y) ((Map[x][y] & 2)>>1)
#define isEmpty(x,y) ((!isWall(x,y)) && !isBirthPoint(x,y))
#define isExplored(x,y) ((Map[x][y] & 4) >> 2)
#define isColored(x,y) (((Map[x][y] & 8) >> 3))
#define isMyColor(x,y) (isColored(x, y) && ((Map[x][y] & 16) >> 4))
#define isSelfExplored(x,y) ((Map[x][y] & 64) >> 6)
#define isExploredInSimu(x,y) ((Map[x][y] & 16) >> 4)
#define Exists(x,y) ((Map[x][y] & 32) >> 5)
//改变地图状态
#define ExploreCell(x,y) (Map[x][y] = (Map[x][y] | (1 << 2)))
#define SelfExploreCell(x,y) (Map[x][y] = (Map[x][y] | (1 << 6)))
#define MarkWall(x,y) (Map[x][y] = (Map[x][y] | 1))
#define ExploreInSimu(x,y) (Map[x][y] = (Map[x][y] | (1 << 4)))
#define UnexploreInSimu(x,y) (Map[x][y] = (Map[x][y] & ~(1 << 4)))
#define toExist(x,y) (Map[x][y] = (Map[x][y] | (1 << 5)))
#define unExist(x,y) (Map[x][y] = (Map[x][y] & ~(1 << 5)))
void toExplore(u32 coordX, u32 coordY); //把给定坐标的视野内的cell改变为explored
void updateLocalMap(WALLS_PTR& visibleWalls); //从获取的墙壁信息来标记出地图上的墙壁
void printMap(); //打印地图(测试)
#define CharaInfoLen 12 //用于同步的玩家数据
struct SimplifiedCharacter {
void PrintChara();
SimplifiedCharacter(THUAI4::Character&);
SimplifiedCharacter() = default;
void upDate(THUAI4::Character&);
// 数据:12个字节
u8 jobType : 3;
u8 propType : 4;
u8 placeholder1 : 1;
u8 isDying : 1;
u8 bulletNum : 6;
u8 placeholder2 : 1;
u16 x;
u16 y;
u16 hp;
u16 ap;
u16 mvSpeed;
};
//对u16数据的编码与解码
#define decodeu16Data(code) ((((code) & (127 << 8)) << 1) + (((code) & 127) << 2) + 2);
#define decodeu16DataHL(H,L) ((((u16)(H))<<7)+(u16)(L))
#define encodeu16Data(data) ((((data) & (254 << 8)) >> 1) + ((((data) >> 1) & 254) >> 1))
#define encodeu16DataH(data) ((u8)((data) >> 7))
#define encodeu16DataL(data) ((u8)((data) & 127))
//u64数据(有损压缩与解压)
void encodeu64Data(string& msg, u64 data, int startCnt) {
data >>= 1;
const u64 mask = 127;
for (u32 i = 0; i < 9; ++i) {
msg[startCnt++] = (u8)(data & mask);
data >>= 7;
}
}
u64 decodeu64Data(string& msg, int startCnt) {
u64 result = 0;
for (int i = 0; i < 9; ++i) result += (((u64)msg[startCnt++]) << (i * 7));
result <<= 1;
return result;
}
//对u64数据的无损压缩与解压
void encodeGUID(string& msg, u64 guid, int startCnt) {
const u64 mask = 127;
for (u32 i = 0; i < 10; ++i) {
msg[startCnt + i] = (u8)(guid & mask);
guid >>= 7;
}
}
u64 decodeGUID(string& msg, int startCnt) {
u64 ret = 0;
for (int i = 0; i < 10; ++i) ret += (((u64)msg[startCnt + i]) << (i * 7));
return ret;
}
//用于处理接受消息的全局变量
string MSG(64, 0); //用于临时存储接收到的消息
u32 MSGCntRec; //用于接受消息过程中对字节的计数
u32 MSGCntSend; //发送普通型消息的计数
//消息头(id和时间两部分,总共3个字节)
namespace MSGhead {
//消息id部分
//获取发送者身份
constexpr inline int LocID(u8 id) { return (id & 3); }
//判断消息类型(Normal或Abnormal)
constexpr inline u8 NormalMode(u8 id) { return (id & 4) >> 2; }
//提取Abnormal类型消息的Type部分
constexpr inline u8 AbnormalType(u8 id) { return ((id & (15 << 3)) >> 3); }
//Abnormal类型消息的不同Type:
constexpr inline u8 Initialize = 0;
constexpr inline u8 CallAttack = 1;
constexpr inline u8 ExteriorAttackInfo = 2;
constexpr inline u8 CallColor = 3;
constexpr inline u8 UpdatePropAlloc = 4;
constexpr inline u8 EnemyInfo = 5;
//Normal类型下的四个比特开关
constexpr inline u8 UpdateCharaInfo(u8 id) { return (id & 8) >> 3; }
constexpr inline u8 UpdateMap(u8 id) { return (id & 16) >> 4; }
constexpr inline u8 UpdateEnemyInfo(u8 id) { return (id & 32) >> 5; }
//生成普通消息的消息头
constexpr inline u8 MakeIDNormal(u8 locid, u8 updatecharainfo, u8 updatemap, u8 updateenemyinfo, u8 reserved) {
return (locid + ((u8)1 << 2) + (updatecharainfo << 3) + (updatemap << 4) + (updateenemyinfo << 5) + (reserved << 6));
}
//计算普通消息的长度
constexpr inline u32 MakeMSGLenNormal(u8 updatecharainfo, u8 updatemap, u8 updateenemyinfo, u8 reserved) {
if (updatemap)return 64; //说不准消息得有多长
return 3 + updatecharainfo * CharaInfoLen + reserved * 2;
}
//生成特殊消息的消息头
constexpr inline u8 MakeIDAbnormal(u8 locid, u8 type) {
return (locid + (type << 3));
}
//消息发送时间(2bytes)
u16 decodeTime(string& msg) { return (((u16)msg[2]) << 7) + ((u16)msg[1]); }
void encodeTime(string& msg);
bool checkTime(string& msg, u32 epochDiff); //判断消息时效性
}//namespace MSGhead
//普通消息的内容
namespace NormalMSG {
//角色基本信息(8bytes)
void decodeChara(string& msg, SimplifiedCharacter& chara);
void encodeChara(string& msg, SimplifiedCharacter& chara);
//地图更新(unknow bytes)
void decodeMapUpdate(string& msg);
void encodeMapUpdate(string& msg);
}//namespace NormalMSG
//非普通消息的处理
namespace AbnormalMSG {
//游戏开始时间同步
void SendInitMSG(GameApi& self, int IDto);
//发送道具主权声明
void DeclarePropOwnership(GameApi& self, u64 guid, u64 timeOfDiscovery);
//敌情通报
void SendEnemyInfo(GameApi& self, int cellX, int cellY);
}//namespace AbnormalMSG
//关于敌人的信息
vector<u64> enemyGUIDs = {};
//关于自己及队伍的信息
u32 myLocalID = -1; //自己的玩家ID
vector<SimplifiedCharacter> teamMates = {}; //包括自己的队伍信息
int myBirthPointX = 0, myBirthPointY = 0; //自己的出生点cell位置
//识别原地遍历的队伍
struct birthpoint {
int cellX;
int cellY;
int discoverCnt; //在出生点发现敌人的次数
int lastHitTime;
bir