You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

player4.cpp 89 kB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477
  1. #include <vector>
  2. #include <thread>
  3. #include <array>
  4. #include "AI.h"
  5. #include "constants.h"
  6. #include <cmath>
  7. #include <queue>
  8. #include <chrono>
  9. #include <thread>
  10. const double pi = acos(-1.0);
  11. // 为假则play()期间确保游戏状态不更新,为真则只保证游戏状态在调用相关方法时不更新
  12. extern const bool asynchronous = false;
  13. // 选手需要依次将player0到player4的职业在这里定义
  14. using namespace THUAI6;
  15. using namespace std;
  16. // 选手的学生职业
  17. extern const std::array<THUAI6::StudentType, 4> studentType = {
  18. THUAI6::StudentType::StraightAStudent,
  19. THUAI6::StudentType::StraightAStudent,
  20. THUAI6::StudentType::Teacher,
  21. THUAI6::StudentType::StraightAStudent };
  22. // 选手的捣蛋鬼职业
  23. extern const THUAI6::TrickerType trickerType = THUAI6::TrickerType::Assassin;
  24. // 映射表,用于将职业映射为最大沉迷度
  25. inline std::map<StudentType, int> maxAddiction{
  26. {StudentType::StraightAStudent, Constants::StraightAStudent::maxAddiction},
  27. {StudentType::Sunshine, Constants::Sunshine::maxAddiction},
  28. {StudentType::Athlete, Constants::Athlete::maxAddiction},
  29. {StudentType::Teacher, Constants::Teacher::maxAddiction}
  30. };
  31. // 映射表,用于将职业映射为翻窗速度
  32. inline std::map<StudentType, int> speedClimbing{
  33. {StudentType::StraightAStudent, Constants::StraightAStudent::speedOfClimbingThroughWindows},
  34. {StudentType::Sunshine, Constants::Sunshine::speedOfClimbingThroughWindows},
  35. {StudentType::Athlete, Constants::Athlete::speedOfClimbingThroughWindows},
  36. {StudentType::Teacher, Constants::Teacher::speedOfClimbingThroughWindows}
  37. };
  38. // 映射表,用于将职业映射为翻窗速度
  39. inline std::map<TrickerType, int> trickerspeedClimbing{
  40. {TrickerType::Assassin , Constants::Assassin::speedOfClimbingThroughWindows }
  41. };
  42. inline std::map<TrickerType, int> TrickerSpeed{
  43. {TrickerType::Assassin , Constants::Assassin::moveSpeed },
  44. {TrickerType::Klee , Constants::Klee::moveSpeed },
  45. {TrickerType::ANoisyPerson , Constants::ANoisyPerson::moveSpeed },
  46. {TrickerType::Idol , Constants::Idol::moveSpeed }
  47. };
  48. inline std::map<StudentType, int>StudentAlertRadius{
  49. {StudentType::StraightAStudent , Constants::StraightAStudent::alertnessRadius},
  50. {StudentType::Sunshine , Constants::Sunshine::alertnessRadius},
  51. {StudentType::Athlete , Constants::Athlete::alertnessRadius},
  52. {StudentType::Teacher , Constants::Teacher::alertnessRadius}
  53. };
  54. inline std::map<StudentType, int>StudentSpeed{
  55. {StudentType::StraightAStudent , Constants::StraightAStudent::moveSpeed},
  56. {StudentType::Sunshine , Constants::Sunshine::moveSpeed},
  57. {StudentType::Athlete , Constants::Athlete::moveSpeed},
  58. {StudentType::Teacher , Constants::Teacher::moveSpeed}
  59. };
  60. //映射表,用于将子弹类型映射为子弹速度,攻击范围,前摇时间,攻击力,用tuple存储
  61. inline std::map<BulletType, tuple<double, double, double, double>> bulletInfo{
  62. {BulletType::CommonAttackOfTricker , make_tuple(Constants::CommonAttackOfTricker::Speed,
  63. Constants::CommonAttackOfTricker::BulletAttackRange,
  64. Constants::CommonAttackOfTricker::CastTime,
  65. Constants::CommonAttackOfTricker::ap)},
  66. {BulletType::FlyingKnife , make_tuple(Constants::FlyingKnife::Speed,
  67. Constants::FlyingKnife::BulletAttackRange,
  68. Constants::FlyingKnife::CastTime,
  69. Constants::FlyingKnife::ap)},
  70. {BulletType::BombBomb , make_tuple(Constants::BombBomb::Speed,
  71. Constants::BombBomb::BulletAttackRange,
  72. Constants::BombBomb::CastTime,
  73. Constants::BombBomb::ap)}
  74. };
  75. struct PKT48 {
  76. TrickerType TheTrickerType = TrickerType::ANoisyPerson;
  77. vector<vector<PlaceType> >mp;
  78. vector<vector<int> >vis, exi;
  79. vector<vector<long long> >upt;
  80. vector<pair<double, double> >bb;//bombbomb
  81. vector<pair<int, int> >adr = vector<pair<int, int> >(4, pair<int, int>(-1, -1)), pos = adr, cls, gate;
  82. pair<int, int>now = pair<int, int>(-1, -1), lstpos = now, lstgrid = now, tripos = now;
  83. vector<pair<int, int> >line;
  84. vector<pair<int, int> >Grassland, Door_and_Window;
  85. //dtm
  86. int linecnt, lstgridcnt, svable[4];
  87. long long lstmvtime;
  88. double lstdir;
  89. long long getTime()
  90. {
  91. return std::chrono::duration_cast<std::chrono::milliseconds>
  92. (std::chrono::system_clock::now().time_since_epoch()).count();
  93. }
  94. void addExist(pair<int, int>p, int r, int val)
  95. {
  96. if (p.first == p.second && p.first == -1)return;
  97. if (p.first <= 0 || p.second <= 0 || p.first / 1000 >= mp.size() || p.second / 1000 >= mp.size())
  98. return;
  99. int x = p.first / 1000, y = p.second / 1000;
  100. if (x <= 0 || y <= 0 || x / 1000 >= mp.size() || y / 1000 >= mp[0].size())
  101. return;
  102. for (int i = -1; i <= 1; i++)
  103. for (int j = -1; j <= 1; j++)
  104. if (sqrt((p.first - (x + i) * 1000 - 500) * (p.first - (x + i) * 1000 - 500)
  105. + (p.second - (y + j) * 1000 - 500) * (p.second - (y + j) * 1000 - 500)) <= r + 410)
  106. exi[x + i][y + j] += val;
  107. return;
  108. }
  109. bool checkStandableCell(pair<int, int>p)
  110. {
  111. if ((mp[p.first][p.second] != PlaceType::Land &&
  112. mp[p.first][p.second] != PlaceType::Grass &&
  113. mp[p.first][p.second] != PlaceType::Door3 &&
  114. mp[p.first][p.second] != PlaceType::Door5 &&
  115. mp[p.first][p.second] != PlaceType::Door6) ||
  116. exi[p.first][p.second])
  117. return false;
  118. return true;
  119. }
  120. double getDistance(pair<int, int>x, pair<int, int>y)
  121. {
  122. return sqrt(1.0 * (x.first - y.first) * (x.first - y.first) +
  123. 1.0 * (x.second - y.second) * (x.second - y.second));
  124. }
  125. bool checkStandableGrid(pair<int, int>p, IStudentAPI& api)
  126. {
  127. int x = p.first / 1000, y = p.second / 1000;
  128. /*for (auto i : api.GetStudents())
  129. if (getDistance(p, make_pair(i->x, i->y)) < 1000)
  130. return false;
  131. for (auto i : api.GetTrickers())
  132. if (getDistance(p, make_pair(i->x, i->y)) < 1000)
  133. return false;*/
  134. for (int i = -1; i <= 1; i++)
  135. for (int j = -1; j <= 1; j++)if (i | j)
  136. if (!checkStandableCell(make_pair(x + i, y + j)))
  137. {
  138. int xx = x + i, yy = y + j;
  139. //cout << x << ' ' << y << ' ' << xx << ' ' << yy << endl;
  140. for (int a = 0; a <= 1; a++)
  141. for (int b = 0; b <= 1; b++)
  142. if (getDistance(p, make_pair((xx + a) * 1000, (yy + b) * 1000)) < 450)
  143. return false;
  144. if (xx * 1000 <= p.first && p.first <= xx * 1000 + 1000)
  145. if (abs(p.second - yy * 1000 - 500) < 910)
  146. return false;
  147. if (yy * 1000 <= p.second && p.second <= yy * 1000 + 1000)
  148. if (abs(p.first - xx * 1000 - 500) < 910)
  149. return false;
  150. }
  151. return true;
  152. }
  153. inline bool haveWay(double x, double y, double newX, double newY, IStudentAPI& api)
  154. {
  155. //cout << "haveWay" << ' ' << x << ' ' << y << ' ' << newX << ' ' << newY << endl;
  156. double divide = max(abs(newX - x), abs(newY - y)) / 10.0;
  157. if (divide == 0)
  158. return true;
  159. double dx = (newX - x) / divide, dy = (newY - y) / divide;
  160. double nowx = double(x), nowy = double(y);
  161. for (int i = 0; i < divide; i++)
  162. {
  163. nowx += dx;
  164. nowy += dy;
  165. if (!checkStandableGrid(make_pair(nowx, nowy), api))
  166. return false;
  167. }
  168. return true;
  169. }
  170. void updateMap(IStudentAPI& api)
  171. {
  172. vector<vector<PlaceType> >p = api.GetFullMap();
  173. if (mp.empty())
  174. {
  175. mp = p;
  176. vis = vector<vector<int> >(p.size(), vector<int>(p[0].size(), -1));
  177. exi = vector<vector<int> >(p.size(), vector<int>(p[0].size(), 0));
  178. upt = vector<vector<long long> >(p.size(), vector<long long>(p[0].size(), 0));
  179. for (int i = p.size() - 1; i >= 0; i--)
  180. for (int j = p[0].size() - 1; j >= 0; j--)
  181. {
  182. if (p[i][j] == PlaceType::ClassRoom)
  183. cls.push_back(make_pair(i, j));
  184. if (p[i][j] == PlaceType::Gate)
  185. gate.push_back(make_pair(i, j));
  186. if (p[i][j] == PlaceType::Door3 ||
  187. p[i][j] == PlaceType::Door5 ||
  188. p[i][j] == PlaceType::Door6)
  189. vis[i][j] = 0,
  190. Door_and_Window.push_back(make_pair(i, j));
  191. if (p[i][j] == PlaceType::Window)
  192. Door_and_Window.push_back(make_pair(i, j));
  193. if (p[i][j] == PlaceType::Grass)
  194. Grassland.push_back(make_pair(i, j));
  195. }
  196. }
  197. for (int i = p.size() - 1; i >= 0; i--)
  198. for (int j = p[0].size() - 1; j >= 0; j--)
  199. {
  200. if (mp[i][j] != p[i][j])mp[i][j] = p[i][j];
  201. if (!api.HaveView(1000 * i + 500, 1000 * j + 500))continue;
  202. if (p[i][j] == PlaceType::ClassRoom)
  203. {
  204. if (upt[i][j] >= getTime() - 200)continue;
  205. vis[i][j] = api.GetClassroomProgress(i, j);
  206. if (vis[i][j] != 1e7 && upt[i][j] >= getTime() - 3000)continue;
  207. upt[i][j] = getTime();
  208. for (int k = 0; k <= 3; k++)
  209. if (k != api.GetSelfInfo()->playerID)
  210. api.SendTextMessage(k, "5 " + to_string(i) + ' ' + to_string(j)
  211. + ' ' + to_string(api.GetClassroomProgress(i, j)));
  212. }
  213. if (p[i][j] == PlaceType::Door3 ||
  214. p[i][j] == PlaceType::Door5 ||
  215. p[i][j] == PlaceType::Door6)
  216. {
  217. if (upt[i][j] >= getTime() - 200)continue;
  218. upt[i][j] = getTime();
  219. if (vis[i][j] != api.IsDoorOpen(i, j))
  220. {
  221. exi[i][j] += api.IsDoorOpen(i, j) - vis[i][j];
  222. vis[i][j] = api.IsDoorOpen(i, j);
  223. for (int k = 0; k <= 3; k++)
  224. if (k != api.GetSelfInfo()->playerID)
  225. api.SendTextMessage(k, "6 " + to_string(i) + ' ' + to_string(j)
  226. + ' ' + to_string((int)api.IsDoorOpen(i, j)));
  227. }
  228. }
  229. if (p[i][j] == PlaceType::Gate)
  230. {
  231. if (vis[i][j] < 18000)
  232. {
  233. if (upt[i][j] >= getTime() - 200)continue;
  234. vis[i][j] = api.GetGateProgress(i, j);
  235. if (vis[i][j] != 18000 && upt[i][j] >= getTime() - 3000)continue;
  236. upt[i][j] = getTime();
  237. for (int k = 0; k <= 3; k++)
  238. if (k != api.GetSelfInfo()->playerID)
  239. api.SendTextMessage(k, "6 " + to_string(i) + ' ' + to_string(j)
  240. + ' ' + to_string(api.GetGateProgress(i, j)));
  241. }
  242. }
  243. }
  244. for (auto i : api.GetStudents())
  245. if (api.GetSelfInfo()->playerID != i->playerID)
  246. {
  247. addExist(pos[i->playerID], 400, -1);
  248. pos[i->playerID] = make_pair(i->x, i->y);
  249. addExist(pos[i->playerID], 400, 1);
  250. }
  251. static pair<int, int>tri;
  252. if (!api.GetTrickers().empty())
  253. {
  254. if (TrickerType::ANoisyPerson != api.GetTrickers()[0]->trickerType && api.GetTrickers()[0]->trickerType != TheTrickerType) {
  255. if (api.GetTrickers()[0]->trickerType != TrickerType::ANoisyPerson)
  256. for (int k = 0; k <= 3; k++)
  257. api.SendTextMessage(k, "114514");
  258. TheTrickerType = api.GetTrickers()[0]->trickerType;
  259. }
  260. addExist(tri, 400, -1);
  261. tripos = make_pair(api.GetTrickers()[0]->x, api.GetTrickers()[0]->y);
  262. tri = tripos;
  263. addExist(tri, 400, 1);
  264. if (upt[0][1] < getTime() - 900)
  265. {
  266. upt[0][1] = getTime();
  267. for (int k = 0; k <= 3; k++)
  268. if (k != api.GetSelfInfo()->playerID)
  269. api.SendTextMessage(k, "7 " + to_string(tripos.first) + ' '
  270. + to_string(tripos.second) + ' ' + to_string(upt[0][1]));
  271. }
  272. }
  273. else {
  274. addExist(tri, 400, -1);
  275. tri = make_pair(-1, -1);
  276. }
  277. }
  278. long long readMessage(int& p, string& s)
  279. {
  280. long long res = 0, f = 1;
  281. while (p < s.size() && (s[p] < '0' || s[p]>'9'))
  282. if (s[p++] == '-')f = -1;
  283. while (p < s.size() && (s[p] >= '0' && s[p] <= '9'))
  284. res = res * 10 + s[p++] - '0';
  285. return res * f;
  286. }
  287. void changeAddr(IStudentAPI& api, pair<int, int>p)
  288. {
  289. if (p == adr[api.GetSelfInfo()->playerID])return;
  290. if (p != make_pair(-1, -1))
  291. for (int i = 0; i <= 3; i++)
  292. if (i != api.GetSelfInfo()->playerID)
  293. api.SendTextMessage(i, "1 " + to_string(p.first) + ' ' + to_string(p.second));
  294. adr[api.GetSelfInfo()->playerID] = p;
  295. //api.Print("Change " + to_string(p.first) + ' ' + to_string(p.second));
  296. now = make_pair(-1, -1);
  297. linecnt = 0;
  298. line.clear();
  299. }
  300. void updateMessage(IStudentAPI& api)//消息格式:首个数字+后续
  301. {
  302. //api.Print("ERROR?-1");
  303. //return;
  304. while (api.HaveMessage())
  305. {
  306. //api.Print("ERROR?0");
  307. auto m = api.GetMessage();
  308. //api.Print("ERROR?1");
  309. auto a = m.first; auto b = m.second; int p = 0;
  310. //api.Print(to_string(a) + ' ' + b);
  311. long long x, y, z;
  312. switch (readMessage(p, b))
  313. {
  314. case 1://目标变更
  315. //cout << api.GetSelfInfo()->playerID << ' ' << a << ' ' << b << endl;
  316. x = readMessage(p, b), y = readMessage(p, b);
  317. adr[a] = make_pair(x, y);
  318. break;
  319. case 2://位置改变
  320. x = readMessage(p, b), y = readMessage(p, b);
  321. addExist(pos[a], 400, -1);
  322. pos[a] = make_pair(x, y);
  323. addExist(pos[a], 400, 1);
  324. break;
  325. case 3://教学楼门状态更新
  326. x = readMessage(p, b), y = readMessage(p, b), z = readMessage(p, b);
  327. exi[x][y] += z - vis[x][y];
  328. vis[x][y] = z;
  329. break;
  330. case 4://箱子状态更新
  331. x = readMessage(p, b), y = readMessage(p, b), z = readMessage(p, b);
  332. vis[x][y] = z;
  333. break;
  334. case 5://教室状态更新
  335. x = readMessage(p, b), y = readMessage(p, b), z = readMessage(p, b);
  336. vis[x][y] = z;
  337. break;
  338. case 6://校门状态更新
  339. x = readMessage(p, b), y = readMessage(p, b), z = readMessage(p, b);
  340. vis[x][y] = z;
  341. break;
  342. case 7://捣蛋鬼状态更新
  343. x = readMessage(p, b), y = readMessage(p, b), z = readMessage(p, b);
  344. addExist(tripos, 400, -1);
  345. tripos = make_pair(x, y);
  346. upt[0][1] = z;
  347. addExist(tripos, 400, 1);
  348. break;
  349. case 8://视野范围内有捣蛋鬼则暂时不救
  350. svable[a] = readMessage(p, b);
  351. break;
  352. case 999://毕业
  353. adr[a] = make_pair(-1, -1);
  354. addExist(pos[a], 400, -1);
  355. break;
  356. case 114514: // Anoisy
  357. TheTrickerType = TrickerType::Assassin;
  358. break;
  359. }
  360. }
  361. //api.Print("ERROR?2");
  362. }
  363. bool checkMap(int a, int b)
  364. {
  365. if (mp[a][b] != PlaceType::Land ||
  366. mp[a][b] != PlaceType::Grass)
  367. return false;
  368. else return true;
  369. }
  370. pair<int, int>findRecent(double x, double y)
  371. {
  372. double dis = 1e18;
  373. int px = -1, py = -1;
  374. for (int i = mp.size() - 1; i >= 0; i--)
  375. for (int j = mp[0].size() - 1; j >= 0; j--)
  376. if (checkStandableCell(make_pair(i, j)))
  377. {
  378. double check =
  379. (x - i * 1000 - 500) * (x - i * 1000 - 500) +
  380. (y - j * 1000 - 500) * (y - j * 1000 - 500);
  381. if (check < dis)
  382. {
  383. px = i; py = j;
  384. dis = check;
  385. }
  386. }
  387. return make_pair(px, py);
  388. }
  389. vector<vector<int> >dis, lst, ThroughDoors;
  390. vector<vector<int> >dis2, ThroughDoors2;
  391. queue<pair<int, int> >q;
  392. int checkSidable(pair<int, int>p)//不可到达返回-1否则返回九宫格距离
  393. {
  394. int d = 1e9;
  395. for (int i = -1; i <= 1; i++)
  396. for (int j = -1; j <= 1; j++)
  397. if (dis[p.first + i][p.second + j] != -1)
  398. d = min(d, dis[p.first + i][p.second + j]);
  399. if (d == 1e9) return -1;
  400. else return d;
  401. }
  402. int checkSidable2(pair<int, int>p)//不可到达返回-1否则返回九宫格距离
  403. {
  404. int d = 1e9;
  405. for (int i = -1; i <= 1; i++)
  406. for (int j = -1; j <= 1; j++)
  407. if (dis2[p.first + i][p.second + j] != -1)
  408. d = min(d, dis[p.first + i][p.second + j]);
  409. if (d == 1e9) return -1;
  410. else return d;
  411. }
  412. long long BFS(int p, pair<int, int>s, pair<int, int>t, IStudentAPI& api, int avoidtag = 0)
  413. {
  414. long long t1 = getTime();
  415. bool is = 0;
  416. dis = lst = ThroughDoors = vector<vector<int> >(mp.size(), vector<int>(mp[0].size(), -1));
  417. dis[s.first][s.second] = 0, ThroughDoors[s.first][s.second] = 0;
  418. while (!q.empty())
  419. q.pop();
  420. q.push(make_pair(s.first, s.second));
  421. bool canstand = 0;
  422. if (t != make_pair(-1, -1) && checkStandableCell(t)) canstand = 1;
  423. while (!q.empty())
  424. {
  425. pair<int, int>p = q.front(); q.pop();
  426. int x = p.first, y = p.second;
  427. if (mp[x][y] == PlaceType::Door3 || mp[x][y] == PlaceType::Door5 || mp[x][y] == PlaceType::Door6 || mp[x][y] == PlaceType::Window)
  428. ThroughDoors[x][y] ++;
  429. if (avoidtag == 1 && ThroughDoors2[x][y] == 0 && dis2[x][y] <= 15) {
  430. ThroughDoors[x][y] = dis[x][y] = lst[x][y] = -1;
  431. continue;
  432. }
  433. if (avoidtag == -1 && (getTime() - upt[0][1] < 8000 && (ThroughDoors2[x][y] == 0 && dis2[x][y] < min(11, dis2[s.first][s.second])))) {
  434. ThroughDoors[x][y] = dis[x][y] = lst[x][y] = -1;
  435. continue;
  436. }
  437. if (abs(x - t.first) <= 1 && abs(y - t.second) <= 1 && canstand == 0 && checkStandableCell(make_pair(x, y)))
  438. {
  439. t = make_pair(x, y);
  440. is = 1;
  441. break;
  442. }
  443. if (abs(x - t.first) + abs(y - t.second) <= 0)
  444. {
  445. t = make_pair(x, y);
  446. is = 1;
  447. break;
  448. }
  449. for (int i = 0; i <= 7; i++)if (!(i & 1))
  450. {
  451. int a = 0, b = 0;
  452. if (i == 0 || i == 1 || i == 7)a = 1;
  453. if (i == 3 || i == 4 || i == 5)a = -1;
  454. if (i == 1 || i == 2 || i == 3)b = 1;
  455. if (i == 5 || i == 6 || i == 7)b = -1;
  456. if (checkStandableCell(make_pair(x + a, y + b))
  457. || mp[x + a][y + b] == PlaceType::Window)
  458. {
  459. if (dis[x + a][y + b] == -1)
  460. {
  461. dis[x + a][y + b] = dis[x][y] + 1;
  462. ThroughDoors[x + a][y + b] = ThroughDoors[x][y];
  463. q.push(make_pair(x + a, y + b));
  464. lst[x + a][y + b] = i;
  465. }
  466. }
  467. }
  468. }
  469. line.clear();
  470. if (t != make_pair(-1, -1))
  471. {
  472. if (!is)
  473. return getTime() - t1;
  474. for (int x = t.first, y = t.second; x != s.first || y != s.second;) // line 从前往后 为终点到起点的路径
  475. {
  476. if (mp[x][y] != PlaceType::Window)
  477. line.push_back(make_pair(x, y));
  478. int i = lst[x][y], a = 0, b = 0;
  479. if (i == 0 || i == 1 || i == 7)a = 1;
  480. if (i == 3 || i == 4 || i == 5)a = -1;
  481. if (i == 1 || i == 2 || i == 3)b = 1;
  482. if (i == 5 || i == 6 || i == 7)b = -1;
  483. x -= a; y -= b;
  484. }
  485. if (!line.empty() && abs(line.back().first - s.first) + abs(line.back().second - s.second) == 2)
  486. {
  487. ;
  488. }
  489. else
  490. line.push_back(make_pair(s.first, s.second));
  491. }
  492. return getTime() - t1;
  493. }
  494. long long BFS2(int p, pair<int, int>s, pair<int, int>t, IStudentAPI& api)
  495. {
  496. long long t1 = getTime();
  497. bool is = 0;
  498. dis2 = ThroughDoors2 = vector<vector<int> >(mp.size(), vector<int>(mp[0].size(), -1));
  499. dis2[s.first][s.second] = ThroughDoors2[s.first][s.second] = 0;
  500. while (!q.empty())
  501. q.pop();
  502. q.push(make_pair(s.first, s.second));
  503. while (!q.empty())
  504. {
  505. pair<int, int>p = q.front(); q.pop();
  506. int x = p.first, y = p.second;
  507. if (mp[x][y] == PlaceType::Door3 || mp[x][y] == PlaceType::Door5 || mp[x][y] == PlaceType::Door6 || mp[x][y] == PlaceType::Window)
  508. ThroughDoors2[x][y] ++;
  509. for (int i = 0; i <= 7; i++)if (!(i & 1))
  510. {
  511. int a = 0, b = 0;
  512. if (i == 0 || i == 1 || i == 7)a = 1;
  513. if (i == 3 || i == 4 || i == 5)a = -1;
  514. if (i == 1 || i == 2 || i == 3)b = 1;
  515. if (i == 5 || i == 6 || i == 7)b = -1;
  516. if (checkStandableCell(make_pair(x + a, y + b))
  517. || mp[x + a][y + b] == PlaceType::Window)
  518. {
  519. if (dis2[x + a][y + b] == -1)
  520. {
  521. ThroughDoors2[x + a][y + b] = ThroughDoors2[x][y];
  522. dis2[x + a][y + b] = dis2[x][y] + 1;
  523. q.push(make_pair(x + a, y + b));
  524. }
  525. }
  526. }
  527. }
  528. return getTime() - t1;
  529. }
  530. }tts;
  531. void AI::play(IStudentAPI& api)
  532. {
  533. if (api.GetSelfInfo()->playerState == PlayerState::Graduated)return;
  534. auto self = api.GetSelfInfo();
  535. int id = this->playerID;
  536. tts.updateMap(api);
  537. tts.updateMessage(api);
  538. int x = api.GetSelfInfo()->x / 1000, y = api.GetSelfInfo()->y / 1000;
  539. //无法操作时,直接返回
  540. if (self->playerState == PlayerState::Attacking || self->playerState == PlayerState::Swinging
  541. || self->playerState == PlayerState::Stunned || self->playerState == PlayerState::Climbing
  542. || self->playerState == PlayerState::Addicted) {
  543. tts.lstmvtime = tts.getTime();
  544. return;
  545. }
  546. //救人的简单判定
  547. //nextaddction()
  548. auto nextaddction = [&](int x) {
  549. return x <= 78000 / 3 ? 78000 / 3 : x <= 78000 * 2 / 3 ? 78000 * 2 / 3 : 78000;
  550. };
  551. if (!api.GetStudents().empty()) {
  552. for (auto i : api.GetStudents())
  553. if (i->playerID != id)
  554. if (i->determination == 0) {
  555. if (abs(i->x / 1000 - x) <= 1 && abs(i->y / 1000 - y) <= 1)
  556. {
  557. if (i->addiction < nextaddction(i->addiction) - 3000 &&
  558. Constants::Teacher::alertnessRadius <= 8000 * (tts.TheTrickerType == TrickerType::ANoisyPerson ? 0 : self->dangerAlert))
  559. continue;
  560. api.StartRouseMate(i->playerID);
  561. this_thread::sleep_for(chrono::milliseconds(1050));
  562. return;
  563. }
  564. }
  565. }
  566. static int priority = 0x3f3f3f3f;
  567. int avoidtag = -1;
  568. if (tts.getTime() - tts.upt[0][1] <= 1000) {
  569. tts.BFS2(id, make_pair(api.GridToCell(tts.tripos.first), api.GridToCell(tts.tripos.second)), tts.adr[id], api);
  570. }
  571. //卡人的简单判定
  572. for (auto& s : api.GetTrickers()) {
  573. if (1ll * (s->x - self->x) * (s->x - self->x) + 1ll * (s->y - self->y) * (s->y - self->y) <= 810 * 810) {
  574. api.Move(50, atan2(s->y - self->y, s->x - self->x) + pi);
  575. this_thread::sleep_for(chrono::milliseconds(50));
  576. return;
  577. }
  578. }
  579. for (auto& s : api.GetStudents()) if (s->playerID != self->playerID) {
  580. if (1ll * (s->x - self->x) * (s->x - self->x) + 1ll * (s->y - self->y) * (s->y - self->y) <= 810 * 810) {
  581. api.Move(50, atan2(s->y - self->y, s->x - self->x) + pi);
  582. this_thread::sleep_for(chrono::milliseconds(50));
  583. return;
  584. }
  585. }
  586. if (api.GetSelfInfo()->studentType == StudentType::Teacher) {
  587. //输出tts.tripos.first , tts.tripos.second
  588. //api.Print(to_string(tts.tripos.first) + ' ' + to_string(tts.tripos.second));
  589. //输出tts.upt[0][1] , tts.getTime()
  590. //api.Print(fmt::format("time = {}, upt = {}", tts.getTime(), tts.upt[0][1]));
  591. static long long kjsj = tts.getTime();
  592. if (tts.getTime() == kjsj)
  593. api.UseSkill(1, 0);
  594. if (!api.GetTrickers().empty() && 1.0 * (api.GetTrickers()[0]->x - self->x) * (api.GetTrickers()[0]->x - self->x) + 1.0 * (api.GetTrickers()[0]->y - self->y) * (api.GetTrickers()[0]->y - self->y) < 5000 * 5000) {
  595. if (api.GetTrickers()[0]->playerState == PlayerState::Attacking) {
  596. api.EndAllAction();
  597. this_thread::sleep_for(chrono::milliseconds(5));
  598. double alpha = atan2(api.GetTrickers()[0]->y - self->y, api.GetTrickers()[0]->x - self->x);
  599. double xx = self->x + 600 * cos(alpha + pi / 2), yy = self->y + 600 * sin(alpha + pi / 2);
  600. //输出getTime
  601. if (tts.haveWay(self->x, self->y, xx, yy, api)) {
  602. api.Move(360, alpha + pi / 2);
  603. this_thread::sleep_for(chrono::milliseconds(200));
  604. }
  605. else {
  606. xx = self->x + 600 * cos(alpha - pi / 2), yy = self->y + 600 * sin(alpha - pi / 2);
  607. //if (tts.haveWay(self->x, self->y, xx, yy, api))
  608. {
  609. api.Move(360, alpha - pi / 2);
  610. this_thread::sleep_for(chrono::milliseconds(200));
  611. }
  612. //无路可逃
  613. }
  614. return;
  615. }
  616. }
  617. //考虑对抗
  618. if (!api.GetTrickers().empty() && 1.0 * (api.GetTrickers()[0]->x - self->x) * (api.GetTrickers()[0]->x - self->x) + 1.0 * (api.GetTrickers()[0]->y - self->y) * (api.GetTrickers()[0]->y - self->y) < 3000 * 3000) {
  619. if (api.GetTrickers()[0]->playerState == PlayerState::Attacking || api.GetTrickers()[0]->playerState == PlayerState::Swinging
  620. || api.GetTrickers()[0]->playerState == PlayerState::Climbing || api.GetTrickers()[0]->playerState == PlayerState::UsingSpecialSkill) {
  621. if (api.GetSelfInfo()->timeUntilSkillAvailable[0] == 0)
  622. api.UseSkill(0);
  623. }
  624. }
  625. for (auto i : api.GetStudents())
  626. if (i->determination == 0 && i->playerState != PlayerState::Quit)
  627. {
  628. priority = 0;
  629. tts.changeAddr(api, make_pair(api.GridToCell(i->x), api.GridToCell(i->y)));
  630. tts.BFS(id, make_pair(x, y), tts.adr[id], api);
  631. goto getsettoroll;
  632. }
  633. //保持距离
  634. if (!api.GetTrickers().empty() && api.GetTrickers()[0]->trickerType == TrickerType::Klee) {
  635. if (1.0 * (api.GetTrickers()[0]->x - self->x) * (api.GetTrickers()[0]->x - self->x) + (api.GetTrickers()[0]->y - self->y) * (api.GetTrickers()[0]->y - self->y) < 3000 * 3000)
  636. {
  637. double theta = atan2(api.GetTrickers()[0]->y - self->y, api.GetTrickers()[0]->x - self->x) + pi;
  638. for (int i = 0; i <= 5; i++) {
  639. double alpha = theta + i * pi / 5;
  640. double xx = api.GetTrickers()[0]->x + 4000 * cos(alpha), yy = api.GetTrickers()[0]->y + 4000 * sin(alpha);
  641. if (tts.haveWay(self->x, self->y, xx, yy, api)) {
  642. int t = 1000 * sqrt((xx - self->x) * (xx - self->x) + (yy - self->y) * (yy - self->y)) / self->speed;
  643. api.EndAllAction();
  644. this_thread::sleep_for(chrono::milliseconds(5));
  645. api.Move(t, alpha);
  646. return;
  647. }
  648. alpha = theta - i * pi / 5;
  649. xx = api.GetTrickers()[0]->x + 4000 * cos(alpha), yy = api.GetTrickers()[0]->y + 4000 * sin(alpha);
  650. if (tts.haveWay(self->x, self->y, xx, yy, api)) {
  651. int t = 1000 * sqrt((xx - self->x) * (xx - self->x) + (yy - self->y) * (yy - self->y)) / self->speed;
  652. api.EndAllAction();
  653. this_thread::sleep_for(chrono::milliseconds(5));
  654. api.Move(t, alpha);
  655. return;
  656. }
  657. }
  658. }
  659. }
  660. if (self->determination > 25000000) { // 可以靠近
  661. }
  662. else if (!api.GetTrickers().empty() && self->determination > 20000000) { // 老师要和坏学生保持距离
  663. /*double d = api.GetTrickers()[0]->facingDirection + atan2(api.GetTrickers()[0]->y - self->y, api.GetTrickers()[0]->x - self->x);
  664. d = fmod(d, 2 * pi);
  665. if (d > pi) d -= 2 * pi;
  666. api.Print(fmt :: format("api.GetTrickers()[0]->facingDirection = {} , d = {}", api.GetTrickers()[0]->facingDirection , d));
  667. if (fabs(d) < pi * 0.1)//对上眼了*/ // tmd射击不改变facingdirection
  668. if (1.0 * (api.GetTrickers()[0]->x - self->x) * (api.GetTrickers()[0]->x - self->x) + (api.GetTrickers()[0]->y - self->y) * (api.GetTrickers()[0]->y - self->y) < 2000 * 2000)
  669. {
  670. double theta = atan2(api.GetTrickers()[0]->y - self->y, api.GetTrickers()[0]->x - self->x) + pi;
  671. for (int i = 0; i <= 30; i++) {
  672. double alpha = theta + i * pi / 30;
  673. double xx = api.GetTrickers()[0]->x + 2500 * cos(alpha), yy = api.GetTrickers()[0]->y + 2500 * sin(alpha);
  674. if (tts.haveWay(self->x, self->y, xx, yy, api)) {
  675. int t = 1000 * sqrt((xx - self->x) * (xx - self->x) + (yy - self->y) * (yy - self->y)) / self->speed;
  676. api.EndAllAction();
  677. this_thread::sleep_for(chrono::milliseconds(5));
  678. api.Move(t, alpha);
  679. return;
  680. }
  681. alpha = theta - i * pi / 30;
  682. xx = api.GetTrickers()[0]->x + 2100 * cos(alpha), yy = api.GetTrickers()[0]->y + 2100 * sin(alpha);
  683. if (tts.haveWay(self->x, self->y, xx, yy, api)) {
  684. int t = 1000 * sqrt((xx - self->x) * (xx - self->x) + (yy - self->y) * (yy - self->y)) / self->speed;
  685. api.EndAllAction();
  686. this_thread::sleep_for(chrono::milliseconds(5));
  687. api.Move(t, alpha);
  688. return;
  689. }
  690. }
  691. // 无路可逃?
  692. }
  693. }
  694. else if (!api.GetTrickers().empty() && self->determination <= 20000000) {
  695. if (1.0 * (api.GetTrickers()[0]->x - self->x) * (api.GetTrickers()[0]->x - self->x) + (api.GetTrickers()[0]->y - self->y) * (api.GetTrickers()[0]->y - self->y) < 2500 * 2500)
  696. {
  697. double theta = atan2(api.GetTrickers()[0]->y - self->y, api.GetTrickers()[0]->x - self->x) + pi;
  698. for (int i = 0; i <= 5; i++) {
  699. double alpha = theta + i * pi / 5;
  700. double xx = api.GetTrickers()[0]->x + 3000 * cos(alpha), yy = api.GetTrickers()[0]->y + 3000 * sin(alpha);
  701. if (tts.haveWay(self->x, self->y, xx, yy, api)) {
  702. int t = 1000 * sqrt((xx - self->x) * (xx - self->x) + (yy - self->y) * (yy - self->y)) / self->speed;
  703. api.EndAllAction();
  704. this_thread::sleep_for(chrono::milliseconds(5));
  705. api.Move(t, alpha);
  706. return;
  707. }
  708. alpha = theta - i * pi / 5;
  709. xx = api.GetTrickers()[0]->x + 3000 * cos(alpha), yy = api.GetTrickers()[0]->y + 3000 * sin(alpha);
  710. if (tts.haveWay(self->x, self->y, xx, yy, api)) {
  711. int t = 1000 * sqrt((xx - self->x) * (xx - self->x) + (yy - self->y) * (yy - self->y)) / self->speed;
  712. api.EndAllAction();
  713. this_thread::sleep_for(chrono::milliseconds(5));
  714. api.Move(t, alpha);
  715. return;
  716. }
  717. }
  718. }
  719. }
  720. if (!api.GetTrickers().empty()) {
  721. priority = 1;
  722. tts.changeAddr(api, make_pair(api.GridToCell(api.GetTrickers()[0]->x), api.GridToCell(api.GetTrickers()[0]->y)));
  723. tts.BFS(id, make_pair(x, y), tts.adr[id], api);
  724. goto getsettoroll;
  725. }
  726. if (tts.getTime() - tts.upt[0][1] <= 1000) {
  727. priority = 2;
  728. tts.changeAddr(api, make_pair(api.GridToCell(tts.tripos.first), api.GridToCell(tts.tripos.second)));
  729. tts.BFS(id, make_pair(x, y), tts.adr[id], api);
  730. goto getsettoroll;
  731. }
  732. if (tts.getTime() - tts.upt[0][1] <= 10000) {
  733. priority = 3;
  734. tts.changeAddr(api, make_pair(api.GridToCell(tts.tripos.first), api.GridToCell(tts.tripos.second)));
  735. tts.BFS(id, make_pair(x, y), tts.adr[id], api);
  736. goto getsettoroll;
  737. }
  738. if (0) { // 准备写的 , 某个学霸听到在附近,请求教师协助。
  739. }
  740. goto getsettoroll;
  741. }
  742. /*
  743. if (api.GetSelfInfo()->studentType == StudentType::Athlete)
  744. {
  745. api.Print("check!" + to_string(api.GetSelfInfo()->timeUntilSkillAvailable[0]));
  746. if (!api.GetTrickers().empty() && api.GetTrickers()[0]->playerState != PlayerState::Stunned)
  747. {
  748. int ch = id;
  749. long long mn = 1e18;
  750. tts.updateMessage(api);
  751. for (auto i : api.GetStudents())
  752. if (i->studentType == StudentType::Athlete && i->determination > 0)
  753. if (i->timeUntilSkillAvailable[0] > 57000)
  754. {
  755. mn = -1;
  756. ch = i->playerID;
  757. }
  758. else if (!i->timeUntilSkillAvailable[0])
  759. {
  760. long long tx = api.GetTrickers()[0]->x - i->x;
  761. long long ty = api.GetTrickers()[0]->y - i->y;
  762. if (tx * tx + ty * ty < mn)
  763. {
  764. mn = tx * tx + ty * ty;
  765. ch = i->playerID;
  766. }
  767. }
  768. int skt = api.GetSelfInfo()->timeUntilSkillAvailable[0];
  769. if (ch == id && (!skt || skt > 58000))
  770. {
  771. api.Print("BRAVE!");
  772. tts.addExist(tts.tripos, 500, -1);
  773. if (tts.haveWay(api.GetSelfInfo()->x, api.GetSelfInfo()->y,
  774. api.GetTrickers()[0]->x, api.GetTrickers()[0]->y, api))
  775. {
  776. tts.addExist(tts.tripos, 500, 1);
  777. long long tx = api.GetTrickers()[0]->x - api.GetSelfInfo()->x;
  778. long long ty = api.GetTrickers()[0]->y - api.GetSelfInfo()->y;
  779. int t = 1e3 * sqrt(tx * tx + ty * ty) / api.GetSelfInfo()->speed;
  780. if (!skt && t < 600) { api.UseSkill(0); api.Print("SKILL!"); }
  781. if (skt > 57000)t /= 3;
  782. t = min(t, 50);
  783. api.Move(t, tts.lstdir = (ty > 0 ? acos(tx / sqrt(tx * tx + ty * ty)) :
  784. 2 * acos(-1) - acos(tx / sqrt(tx * tx + ty * ty))));
  785. //tts.BFS(id, make_pair(x, y), tts.adr[id], api);
  786. return;
  787. }
  788. else
  789. {
  790. tts.addExist(tts.tripos, 500, 1);
  791. if (tts.adr[id] != make_pair(tts.tripos.first / 1000, tts.tripos.second / 1000))
  792. {
  793. tts.changeAddr(api, make_pair(tts.tripos.first / 1000, tts.tripos.second / 1000));
  794. tts.BFS(id, make_pair(x, y), tts.adr[id], api);
  795. }
  796. }
  797. }
  798. }
  799. }
  800. */
  801. /*for (auto i : api.GetStudents())
  802. {
  803. //api.Print("STUDENT "+to_string(i->x)+' '+to)
  804. }
  805. */
  806. //输出tts.tripos.first, tts.tripos.second , tts.getTime(), tts.upt[0][1]
  807. //api.Print(fmt :: format("tripos = ({}, {}), time = {}, upt = {}", tts.tripos.first, tts.tripos.second, tts.getTime(), tts.upt[0][1]));
  808. if (priority == 1) {
  809. if ((tts.TheTrickerType != TrickerType::ANoisyPerson && StudentAlertRadius[self->studentType] > self->dangerAlert * 8000)
  810. || (tts.getTime() - tts.upt[0][1] <= 1000 && tts.dis2[self->x / 1000][self->y / 1000] > 11))
  811. priority = 0x3f3f3f3f;
  812. }
  813. if (priority == 2)
  814. {
  815. for (auto i : api.GetStudents())
  816. if (i->studentType == StudentType::Teacher)
  817. if (i->determination > 0 || (i->dangerAlert && tts.TheTrickerType != TrickerType::ANoisyPerson))
  818. priority = 0x3f3f3f3f;
  819. }
  820. if (tts.adr[id] != make_pair(-1, -1) && priority == 3)
  821. {
  822. if (tts.vis[tts.adr[id].first][tts.adr[id].second] == 1e7)
  823. priority = 0x3f3f3f3f;
  824. if (api.GetGameInfo()->subjectFinished >= 7)
  825. priority = 0x3f3f3f3f;
  826. }
  827. if (priority >= 1) {
  828. //考虑加入tricker不动的时候
  829. if (0) {
  830. }
  831. if (tts.getTime() - tts.upt[0][1] <= 8000 && tts.dis2[self->x / 1000][self->y / 1000] <= 11)
  832. {
  833. tts.BFS(id, make_pair(x, y), make_pair(-1, -1), api);
  834. int td = 0x3f3f3f3f;
  835. for (int i = -1; i <= 1; i++) for (int j = -1; j <= 1; j++)
  836. if (tts.ThroughDoors[api.GridToCell(tts.tripos.first) + i][api.GridToCell(tts.tripos.second) + j] != -1)
  837. td = min(td, tts.ThroughDoors[api.GridToCell(tts.tripos.first) + i][api.GridToCell(tts.tripos.second) + j]);
  838. //符号函数
  839. auto sgn = [](double x) {return x < 0 ? -1 : 1; };
  840. if (tts.mp[self->x / 1000][self->y / 1000] == PlaceType::Grass && tts.mp[api.GridToCell(tts.tripos.first)][api.GridToCell(tts.tripos.second)] != PlaceType::Grass
  841. && tts.mp[self->x / 1000 + sgn(tts.tripos.first - self->x)][self->y / 1000] != PlaceType::Grass
  842. && tts.mp[self->x / 1000][self->y / 1000 + sgn(tts.tripos.second - self->y)] != PlaceType::Grass
  843. && td == 0
  844. && StudentAlertRadius[self->studentType] <= 4000 * (tts.TheTrickerType == TrickerType::ANoisyPerson ? 0 : self->dangerAlert)) { // 很近了
  845. api.EndAllAction();
  846. this_thread::sleep_for(chrono::milliseconds(5));
  847. api.Move(50, atan2(api.CellToGrid(self->y) - tts.tripos.second, api.CellToGrid(self->x) - tts.tripos.first));
  848. return;
  849. }
  850. else if (td == 0) {// 在同一空间 , 寻找能够制造最多路程差的门
  851. double mx = -1e9;
  852. pair<int, int> ch = make_pair(-1, -1);
  853. for (auto s : tts.Door_and_Window) {
  854. for (int i = -1; i <= 1; i++) for (int j = -1; j <= 1; j++) if (i == 0 || j == 0) if (i | j)
  855. if (tts.checkStandableCell(make_pair(s.first + i, s.second + j)) && tts.ThroughDoors[s.first + i][s.second + j] == 1 &&
  856. (tts.dis[s.first + i][s.second + j] <= tts.dis2[s.first + i][s.second + j] - 1 || tts.dis[s.first + i][s.second + j] > 10)) {
  857. double t = tts.dis[s.first + i][s.second + j] * 1000 / StudentSpeed[self->studentType];
  858. double ret = tts.dis2[s.first + i][s.second + j] * 1000 - t * TrickerSpeed[tts.TheTrickerType];
  859. if (ret > mx) {
  860. mx = ret;
  861. ch = make_pair(s.first + i, s.second + j);
  862. }
  863. }
  864. }
  865. if (ch.first != -1 && ch.second != -1) {
  866. priority = 1;
  867. tts.changeAddr(api, ch);
  868. tts.BFS(id, make_pair(x, y), tts.adr[id], api);
  869. tts.linecnt = 0;
  870. goto getsettoroll;
  871. }
  872. else {
  873. //跑不过了,躲草丛。
  874. tts.BFS(id, make_pair(x, y), make_pair(-1, -1), api);
  875. //寻找制造距离差最大的草丛
  876. double mx = -0x3f3f3f3f;
  877. pair<int, int> ch = make_pair(-1, -1);
  878. for (auto s : tts.Grassland)
  879. if (tts.dis[s.first][s.second] != -1 && tts.ThroughDoors[s.first][s.second] == 0)
  880. {
  881. double t = tts.dis[s.first][s.second] * 1000 / StudentSpeed[self->studentType];
  882. double ret = tts.dis2[s.first][s.second] * 1000 - t * TrickerSpeed[tts.TheTrickerType];
  883. bool check = 1;
  884. for (int j = 0; j <= 3; j++)
  885. if ((j != id &&
  886. tts.adr[j].first == s.first &&
  887. tts.adr[j].second == s.second))
  888. check = 0;
  889. if (check && ret > mx)
  890. mx = ret,
  891. ch = s;
  892. }
  893. if (ch != make_pair(-1, -1)) // 必成立
  894. {
  895. priority = 1;
  896. tts.changeAddr(api, ch);
  897. tts.BFS(id, make_pair(x, y), tts.adr[id], api);
  898. tts.linecnt = 0;
  899. goto getsettoroll;
  900. }
  901. }
  902. }
  903. else if (td >= 2) {
  904. //远着呢,不用跑,等后面重新分配目标把
  905. }
  906. else { // 和tricker 一墙之隔 , 不跑进去自投罗网就是胜利
  907. avoidtag = 1;
  908. priority = 0x3f3f3f3f;
  909. }
  910. }
  911. else if (StudentAlertRadius[self->studentType] <= 8000 * (tts.TheTrickerType == TrickerType::ANoisyPerson ? 0 : self->dangerAlert) && priority > 1) // 听到了但是没人看见
  912. {
  913. static double lastalert = 0, lt = 0;
  914. //完全没有位置信息,只能躲草丛
  915. tts.BFS(id, make_pair(x, y), make_pair(-1, -1), api);
  916. //寻找最近不穿墙的草丛
  917. double mn = 1e18;
  918. pair<int, int> ch = make_pair(-1, -1);
  919. for (auto s : tts.Grassland)
  920. if (tts.dis[s.first][s.second] < mn && tts.dis[s.first][s.second] != -1 && tts.ThroughDoors[s.first][s.second] == 0)
  921. {
  922. bool check = 1;
  923. for (int j = 0; j <= 3; j++)
  924. if ((j != id &&
  925. tts.adr[j].first == s.first &&
  926. tts.adr[j].second == s.second))
  927. check = 0;
  928. if (check && tts.dis[s.first][s.second] < mn)
  929. mn = tts.dis[s.first][s.second],
  930. ch = s;
  931. }
  932. if (ch != make_pair(-1, -1)) // 必成立
  933. {
  934. priority = 1;
  935. tts.changeAddr(api, ch);
  936. tts.BFS(id, make_pair(x, y), tts.adr[id], api);
  937. tts.linecnt = 0;
  938. goto getsettoroll;
  939. }
  940. }
  941. }
  942. //api.Print(to_string(tts.adr[id].first) + ' ' + to_string(tts.adr[id].second));
  943. if (priority > 2)
  944. {
  945. bool check = 0;
  946. int a = 0, b = 0;
  947. int countlife = 0;
  948. for (auto i : api.GetStudents())
  949. if (i->studentType != StudentType::Teacher && i->playerState != PlayerState::Quit && i->playerState != PlayerState::Graduated)
  950. countlife++;
  951. for (auto i : api.GetStudents())
  952. if (i->studentType == StudentType::Teacher)
  953. if (i->determination == 0 && (i->dangerAlert == 0 || tts.TheTrickerType == TrickerType::ANoisyPerson) && (
  954. (api.GetGameInfo()->subjectFinished < 7)
  955. || countlife >= 2))
  956. {
  957. check = 1;
  958. a = i->x / 1000;
  959. b = i->y / 1000;
  960. }
  961. if (check)
  962. {
  963. int ch = 4, mn = 1e9;
  964. for (auto i : api.GetStudents())
  965. if (i->studentType != StudentType::Teacher && i->playerState != PlayerState::Addicted)
  966. if (mn > i->addiction || (mn == i->addiction && ch > i->playerID))
  967. {
  968. mn = i->addiction;
  969. ch = i->playerID;
  970. }
  971. if (ch == id)
  972. {
  973. tts.changeAddr(api, make_pair(a, b));
  974. tts.BFS(id, make_pair(x, y), tts.adr[id], api, avoidtag);
  975. tts.linecnt = 0;
  976. priority = 2;
  977. goto getsettoroll;
  978. }
  979. }
  980. }
  981. if (priority > 3) {
  982. {
  983. tts.updateMessage(api);
  984. tts.BFS(id, make_pair(x, y), make_pair(-1, -1), api, avoidtag);
  985. int ch = -1;
  986. double mn = 1e9;
  987. vector<pair<int, int> >tgt;
  988. if (api.GetGameInfo()->subjectFinished < 7)
  989. tgt = tts.cls;// 目标选择教室
  990. else
  991. tgt = tts.gate;// 目标选择门
  992. for (int i = tgt.size() - 1; i >= 0; i--)
  993. {
  994. bool check = (tts.checkSidable(tgt[i]) != -1) &&
  995. (tts.vis[tgt[i].first][tgt[i].second] < 1e7) &&
  996. (tts.getTime() - tts.upt[0][1] >= 8000 ||
  997. tts.checkSidable2(make_pair(tgt[i].first, tgt[i].second)) > 11);
  998. if (check && mn > tts.checkSidable(tgt[i])) //前往距离最近的目标?
  999. {
  1000. mn = tts.checkSidable(tgt[i]);
  1001. ch = i;
  1002. }
  1003. }
  1004. if (ch >= 0)
  1005. {
  1006. tts.changeAddr(api, make_pair(tgt[ch].first, tgt[ch].second));
  1007. tts.BFS(id, make_pair(x, y), tts.adr[id], api, avoidtag);
  1008. tts.linecnt = 0;
  1009. priority = 3;
  1010. }
  1011. }
  1012. }
  1013. getsettoroll://准备去卷
  1014. if (abs(api.GetSelfInfo()->x - tts.adr[id].first * 1000 - 500) > 1040 ||
  1015. abs(api.GetSelfInfo()->y - tts.adr[id].second * 1000 - 500) > 1040 ||
  1016. (tts.checkStandableCell(tts.adr[id]) && abs(api.GetSelfInfo()->x - tts.adr[id].first * 1000 - 500) > 200) ||
  1017. (tts.checkStandableCell(tts.adr[id]) && abs(api.GetSelfInfo()->y - tts.adr[id].second * 1000 - 500) > 200))
  1018. {
  1019. if ((abs(api.GetSelfInfo()->x - tts.now.first * 1000 - 500) < 20 &&
  1020. abs(api.GetSelfInfo()->y - tts.now.second * 1000 - 500) < 20) ||
  1021. (!tts.haveWay(self->x, self->y, tts.now.first * 1000 + 500, tts.now.second * 1000 + 500, api)))
  1022. tts.now = make_pair(-1, -1);
  1023. //api.Print(to_string(tts.now.first) + ' ' + to_string(tts.now.second));
  1024. if (tts.now == make_pair(-1, -1))
  1025. {
  1026. if (tts.linecnt > 0 || tts.line.empty())
  1027. {
  1028. tts.BFS(id, make_pair(x, y), tts.adr[id], api, self->studentType == StudentType::Teacher ? 0 : avoidtag);
  1029. tts.linecnt = 0;
  1030. //输出tts.line.size()
  1031. if (tts.line.empty())
  1032. {
  1033. tts.now = make_pair(-1, -1);
  1034. return;
  1035. }
  1036. }
  1037. int check = -1;
  1038. for (int i = max(0, (int)tts.line.size() - 8); i < tts.line.size() && check == -1; i++) {
  1039. if (tts.haveWay(api.GetSelfInfo()->x, api.GetSelfInfo()->y,
  1040. 1000 * tts.line[i].first + 500,
  1041. 1000 * tts.line[i].second + 500, api))
  1042. check = i;
  1043. }
  1044. tts.linecnt++;
  1045. if (check != -1)
  1046. while (tts.line.size() > check + 1)
  1047. tts.line.pop_back();
  1048. tts.now = tts.line.back();
  1049. tts.line.pop_back();
  1050. }
  1051. }
  1052. else
  1053. tts.now = make_pair(-1, -1);
  1054. if (tts.now != make_pair(-1, -1))
  1055. {
  1056. if (((abs(x - tts.now.first) == 2 && abs(y - tts.now.second) == 0) ||
  1057. (abs(x - tts.now.first) == 0 && abs(y - tts.now.second) == 2)) &&
  1058. tts.mp[(x + tts.now.first) / 2][(y + tts.now.second) / 2] == PlaceType::Window)
  1059. {
  1060. int t = 2000 * 1e3 / speedClimbing[api.GetSelfInfo()->studentType];
  1061. api.SkipWindow();
  1062. api.EndAllAction();
  1063. tts.now = make_pair(-1, -1);
  1064. this_thread::sleep_for(chrono::milliseconds(t));
  1065. }
  1066. else if (abs(api.GetSelfInfo()->x - tts.now.first * 1000 - 500) > 20 ||
  1067. abs(api.GetSelfInfo()->y - tts.now.second * 1000 - 500) > 20)
  1068. {
  1069. int tx = tts.now.first * 1000 + 500 - api.GetSelfInfo()->x,
  1070. ty = tts.now.second * 1000 + 500 - api.GetSelfInfo()->y;
  1071. int t = (int)(sqrt(tx * tx + ty * ty) * 1e3 / api.GetSelfInfo()->speed);
  1072. if (api.GetSelfInfo()->studentType == StudentType::Athlete &&
  1073. api.GetSelfInfo()->timeUntilSkillAvailable[0] > 57000)
  1074. t /= 3;
  1075. if (self->studentType == StudentType::Teacher && t >= 1200 && self->timeUntilSkillAvailable[1] == 0) {
  1076. api.EndAllAction();
  1077. api.UseSkill(1, (int)(atan2(ty, tx) * 1000));
  1078. }
  1079. else {
  1080. t = min(t, 100);
  1081. api.Move(t, tts.lstdir = atan2(ty, tx));
  1082. }
  1083. return;
  1084. }
  1085. else tts.now = make_pair(-1, -1);
  1086. }
  1087. if (abs(api.GetSelfInfo()->x - tts.adr[id].first * 1000 - 500) > 1040 ||
  1088. abs(api.GetSelfInfo()->y - tts.adr[id].second * 1000 - 500) > 1040 ||
  1089. (tts.checkStandableCell(tts.adr[id]) && abs(api.GetSelfInfo()->x - tts.adr[id].first * 1000 - 500) > 200) ||
  1090. (tts.checkStandableCell(tts.adr[id]) && abs(api.GetSelfInfo()->y - tts.adr[id].second * 1000 - 500) > 200)) {
  1091. return;
  1092. }
  1093. else {
  1094. if (self->playerState == PlayerState::Learning || self->playerState == PlayerState::OpeningAGate)
  1095. return;
  1096. for (int i = -1; i <= 1; i++)
  1097. for (int j = -1; j <= 1; j++)
  1098. if ((i || j) && tts.adr[id] == make_pair(x + i, y + j))
  1099. if (tts.mp[x + i][y + j] == PlaceType::ClassRoom)
  1100. {
  1101. //cout << x + i << ' ' << y + j << endl;
  1102. //api.Print("CLSCHECK" + to_string(x + i) + ' ' + to_string(y + j));
  1103. if (tts.vis[x + i][y + j] < 1e7 &&
  1104. api.GetGameInfo()->subjectFinished < 7)
  1105. {
  1106. //cout << api.GetClassroomProgress(x + i, y + j) << endl;
  1107. api.EndAllAction();
  1108. this_thread::sleep_for(chrono::milliseconds(5));
  1109. if (api.GetSelfInfo()->studentType == StudentType::StraightAStudent)
  1110. api.UseSkill(0);
  1111. api.StartLearning();
  1112. return;
  1113. }
  1114. }
  1115. else if (tts.mp[x + i][y + j] == PlaceType::Gate)
  1116. {
  1117. if (api.GetGameInfo()->subjectFinished >= 7)
  1118. {
  1119. api.EndAllAction();
  1120. this_thread::sleep_for(chrono::milliseconds(5));
  1121. if (api.GetGateProgress(x + i, y + j) < 18000)
  1122. api.StartOpenGate();
  1123. else {
  1124. for (int k = 0; k <= 3; k++)
  1125. if (k != id)
  1126. api.SendTextMessage(k, string("999"));
  1127. api.Graduate();
  1128. }
  1129. return;
  1130. }
  1131. }
  1132. }
  1133. }
  1134. // 抓PKT48的捣蛋鬼结构体
  1135. struct CKT48 {
  1136. vector<vector<PlaceType> >mp;
  1137. vector<vector<int> >vis, exi;
  1138. vector<vector<long long> >upt;
  1139. vector<pair<double, double> >bb;//bombbomb
  1140. pair<int, int>adr;
  1141. vector<pair<int, int> > cls, gate;
  1142. pair<int, int>now = pair<int, int>(-1, -1), lstpos = now, lstgrid = now, tripos = now;
  1143. vector<pair<int, int> >line;
  1144. int linecnt, lstgridcnt;
  1145. // lstdir 上一次的方向
  1146. double lstdir;
  1147. // getTime 返回当前时间,单位为毫秒
  1148. long long getTime()
  1149. {
  1150. return std::chrono::duration_cast<std::chrono::milliseconds>
  1151. (std::chrono::system_clock::now().time_since_epoch()).count();
  1152. }
  1153. void addExist(pair<int, int>p, int r, int val)
  1154. {
  1155. if (p.first == p.second && p.first == -1)return;
  1156. if (p.first <= 0 || p.second <= 0 || p.first / 1000 >= mp.size() || p.second / 1000 >= mp.size())
  1157. return;
  1158. int x = p.first / 1000, y = p.second / 1000;
  1159. if (x <= 0 || y <= 0 || x / 1000 >= mp.size() || y / 1000 >= mp[0].size())
  1160. return;
  1161. for (int i = -1; i <= 1; i++)
  1162. for (int j = -1; j <= 1; j++)
  1163. if (sqrt((p.first - (x + i) * 1000 - 500) * (p.first - (x + i) * 1000 - 500)
  1164. + (p.second - (y + j) * 1000 - 500) * (p.second - (y + j) * 1000 - 500)) <= r + 410)
  1165. exi[x + i][y + j] += val;
  1166. return;
  1167. }
  1168. bool checkStandableCell(pair<int, int>p)
  1169. {
  1170. if ((mp[p.first][p.second] != PlaceType::Land &&
  1171. mp[p.first][p.second] != PlaceType::Grass &&
  1172. mp[p.first][p.second] != PlaceType::Door3 &&
  1173. mp[p.first][p.second] != PlaceType::Door5 &&
  1174. mp[p.first][p.second] != PlaceType::Door6) ||
  1175. exi[p.first][p.second])
  1176. return false;
  1177. return true;
  1178. }
  1179. bool checkStandablebulletCell(pair<int, int>p)
  1180. {
  1181. if ((mp[p.first][p.second] != PlaceType::Land &&
  1182. mp[p.first][p.second] != PlaceType::Grass &&
  1183. mp[p.first][p.second] != PlaceType::Door3 &&
  1184. mp[p.first][p.second] != PlaceType::Door5 &&
  1185. mp[p.first][p.second] != PlaceType::Door6 &&
  1186. mp[p.first][p.second] != PlaceType::Window) ||
  1187. exi[p.first][p.second])
  1188. return false;
  1189. return true;
  1190. }
  1191. double getDistance(pair<int, int>x, pair<int, int>y)
  1192. {
  1193. return sqrt(1.0 * (x.first - y.first) * (x.first - y.first) +
  1194. 1.0 * (x.second - y.second) * (x.second - y.second));
  1195. }
  1196. bool checkStandableGrid(pair<int, int>p)
  1197. {
  1198. int x = p.first / 1000, y = p.second / 1000;
  1199. for (int i = -1; i <= 1; i++)
  1200. for (int j = -1; j <= 1; j++)if (i | j)
  1201. if (!checkStandableCell(make_pair(x + i, y + j)))
  1202. {
  1203. int xx = x + i, yy = y + j;
  1204. for (int a = 0; a <= 1; a++)
  1205. for (int b = 0; b <= 1; b++)
  1206. if (getDistance(p, make_pair((xx + a) * 1000, (yy + b) * 1000)) < 410)
  1207. return false;
  1208. if (xx * 1000 <= p.first && p.first <= xx * 1000 + 1000)
  1209. if (abs(p.second - yy * 1000 - 500) < 910)
  1210. return false;
  1211. if (yy * 1000 <= p.second && p.second <= yy * 1000 + 1000)
  1212. if (abs(p.first - xx * 1000 - 500) < 910)
  1213. return false;
  1214. }
  1215. return true;
  1216. }
  1217. inline bool haveWay(double x, double y, double newX, double newY)
  1218. {
  1219. double divide = max(abs(newX - x), abs(newY - y)) / 10;
  1220. if (divide == 0)return true;
  1221. double dx = (newX - x) / divide, dy = (newY - y) / divide;
  1222. double nowx = double(x), nowy = double(y);
  1223. for (int i = 0; i < divide; i++)
  1224. {
  1225. nowx += dx;
  1226. nowy += dy;
  1227. if (!checkStandableGrid(make_pair(nowx, nowy))) {
  1228. return false;
  1229. }
  1230. }
  1231. return true;
  1232. }
  1233. bool checkbulletStandableGrid(pair<double, double>p)
  1234. {
  1235. int x = int(p.first / 1000), y = int(p.second / 1000);
  1236. for (int i = -1; i <= 1; i++)
  1237. for (int j = -1; j <= 1; j++)if (i | j)
  1238. if (!checkStandablebulletCell(make_pair(x + i, y + j)))
  1239. {
  1240. int xx = x + i, yy = y + j;
  1241. for (int a = 0; a <= 1; a++)
  1242. for (int b = 0; b <= 1; b++)
  1243. if (getDistance(p, make_pair((xx + a) * 1000, (yy + b) * 1000)) < 210)
  1244. return false;
  1245. if (xx * 1000 <= p.first && p.first <= xx * 1000 + 1000)
  1246. if (abs(p.second - yy * 1000 - 500) < 710)
  1247. return false;
  1248. if (yy * 1000 <= p.second && p.second <= yy * 1000 + 1000)
  1249. if (abs(p.first - xx * 1000 - 500) < 710)
  1250. return false;
  1251. }
  1252. return true;
  1253. }
  1254. bool havebulletWay(double x, double y, double newX, double newY)
  1255. {
  1256. //输出一下
  1257. //printf("x = %lf, y = %lf, newX = %lf, newY = %lf\n", x, y, newX, newY);
  1258. double theta = atan2(newY - y, newX - x);
  1259. x += cos(theta) * 400, y += sin(theta) * 400;
  1260. newX -= cos(theta) * 400, newX -= sin(theta) * 400;
  1261. double divide = max(abs(newX - x), abs(newY - y)) / 10.0;
  1262. if (divide == 0)return true;
  1263. double dx = (newX - x) / divide, dy = (newY - y) / divide;
  1264. double nowx = double(x), nowy = double(y);
  1265. for (int i = 0; i < divide; i++)
  1266. {
  1267. nowx += dx;
  1268. nowy += dy;
  1269. if (!checkbulletStandableGrid(make_pair(nowx, nowy))) {
  1270. return false;
  1271. }
  1272. }
  1273. return true;
  1274. }
  1275. // updateMap 更新地图
  1276. void updateMap(ITrickerAPI& api)
  1277. {
  1278. vector<vector<PlaceType> >p = api.GetFullMap();
  1279. if (mp.empty())
  1280. {
  1281. mp = p;
  1282. vis = vector<vector<int> >(p.size(), vector<int>(p[0].size(), -1));
  1283. exi = vector<vector<int> >(p.size(), vector<int>(p[0].size(), 0));
  1284. for (int i = p.size() - 1; i >= 0; i--)
  1285. for (int j = p[0].size() - 1; j >= 0; j--)
  1286. {
  1287. if (p[i][j] == PlaceType::ClassRoom)
  1288. cls.push_back(make_pair(i, j));
  1289. if (p[i][j] == PlaceType::Gate)
  1290. gate.push_back(make_pair(i, j));
  1291. }
  1292. }
  1293. }
  1294. void changeAddr(ITrickerAPI& api, pair<int, int>p)
  1295. {
  1296. adr = p;
  1297. now = make_pair(-1, -1);
  1298. linecnt = 0;
  1299. line.clear();
  1300. }
  1301. bool checkMap(int a, int b)
  1302. {
  1303. if (mp[a][b] != PlaceType::Land ||
  1304. mp[a][b] != PlaceType::Grass)
  1305. return false;
  1306. else return true;
  1307. }
  1308. pair<int, int>findRecent(double x, double y)
  1309. {
  1310. double dis = 1e18;
  1311. int px = -1, py = -1;
  1312. for (int i = mp.size() - 1; i >= 0; i--)
  1313. for (int j = mp[0].size() - 1; j >= 0; j--)
  1314. if (checkStandableCell(make_pair(i, j)))
  1315. {
  1316. double check =
  1317. (x - i * 1000 - 500) * (x - i * 1000 - 500) +
  1318. (y - j * 1000 - 500) * (y - j * 1000 - 500);
  1319. if (check < dis)
  1320. {
  1321. px = i; py = j;
  1322. dis = check;
  1323. }
  1324. }
  1325. return make_pair(px, py);
  1326. }
  1327. vector<vector<int> >dis, lst;
  1328. queue<pair<int, int> >q;
  1329. int checkSidable(pair<int, int>p)//不可到达返回-1否则返回九宫格距离
  1330. {
  1331. int d = 1e9;
  1332. for (int i = -1; i <= 1; i++)
  1333. for (int j = -1; j <= 1; j++)
  1334. if (dis[p.first + i][p.second + j] != -1)
  1335. d = min(d, dis[p.first + i][p.second + j]);
  1336. if (d == 1e9)return -1;
  1337. else return d;
  1338. }
  1339. long long BFS(pair<int, int>s, pair<int, int>t, ITrickerAPI& api, bool canstand = 0)//spd:翻窗/普通移速
  1340. {
  1341. long long t1 = getTime();
  1342. bool is = 0;
  1343. dis = lst = vector<vector<int> >(mp.size(), vector<int>(mp[0].size(), -1));
  1344. dis[s.first][s.second] = 0;
  1345. while (!q.empty())q.pop();
  1346. q.push(make_pair(s.first, s.second));
  1347. //cout << s.first << ' ' << s.second << ' ' << t.first << ' ' << t.second << endl;
  1348. /*for (int i = 0; i < mp.size(); i++)
  1349. {
  1350. string s;
  1351. for (int j = 0; j < mp[0].size(); j++)
  1352. s += to_string(exi[i][j]) + ' ';
  1353. api.Print(s);
  1354. }*/
  1355. if (checkStandableCell(t)) canstand = 1;
  1356. while (!q.empty())
  1357. {
  1358. pair<int, int>p = q.front(); q.pop();
  1359. int x = p.first, y = p.second;
  1360. //cout << x << ' ' << y << ' ' << dis[x][y] << endl;
  1361. if (abs(x - t.first) + abs(y - t.second) <= 1 && canstand == 0 && checkStandableCell(make_pair(x, y)))
  1362. {
  1363. //cout << x << ' ' << t.first << ' ' << y << ' ' << t.second << endl;
  1364. t = make_pair(x, y);
  1365. is = 1;
  1366. break;
  1367. }
  1368. if (abs(x - t.first) + abs(y - t.second) <= 0)
  1369. {
  1370. //cout << x << ' ' << t.first << ' ' << y << ' ' << t.second << endl;
  1371. t = make_pair(x, y);
  1372. is = 1;
  1373. break;
  1374. }
  1375. for (int i = 0; i <= 7; i++)if (!(i & 1))
  1376. {
  1377. int a = 0, b = 0;
  1378. if (i == 0 || i == 1 || i == 7)a = 1;
  1379. if (i == 3 || i == 4 || i == 5)a = -1;
  1380. if (i == 1 || i == 2 || i == 3)b = 1;
  1381. if (i == 5 || i == 6 || i == 7)b = -1;
  1382. //cout << x << ' ' << y << ' ' << a << ' ' << b << endl;
  1383. if (checkStandableCell(make_pair(x + a, y + b))
  1384. || mp[x + a][y + b] == PlaceType::Window)
  1385. {
  1386. if (dis[x + a][y + b] == -1)
  1387. {
  1388. dis[x + a][y + b] = dis[x][y] + 1;
  1389. q.push(make_pair(x + a, y + b));
  1390. lst[x + a][y + b] = i;
  1391. }
  1392. }
  1393. }
  1394. }
  1395. line.clear();
  1396. /*for (int i = 0; i < mp.size(); i++, cout << endl)
  1397. for (int j = 0; j < mp[0].size(); j++)
  1398. cout << dis[i][j] << ' ';
  1399. for (int i = 0; i < mp.size(); i++, cout << endl)
  1400. for (int j = 0; j < mp[0].size(); j++)
  1401. cout << lst[i][j] << ' ';
  1402. for (int i = 0; i < mp.size(); i++, cout << endl)
  1403. for (int j = 0; j < mp[0].size(); j++)
  1404. cout << exi[i][j] << ' ';*/
  1405. if (t != make_pair(-1, -1))
  1406. {
  1407. if (!is)return getTime() - t1;
  1408. for (int x = t.first, y = t.second; x != s.first || y != s.second;)
  1409. {
  1410. if (mp[x][y] != PlaceType::Window)
  1411. line.push_back(make_pair(x, y));
  1412. //cout << lst[x][y] << endl;
  1413. int i = lst[x][y], a = 0, b = 0;
  1414. if (i == 0 || i == 1 || i == 7)a = 1;
  1415. if (i == 3 || i == 4 || i == 5)a = -1;
  1416. if (i == 1 || i == 2 || i == 3)b = 1;
  1417. if (i == 5 || i == 6 || i == 7)b = -1;
  1418. x -= a; y -= b;
  1419. /*cout << x << ' ' << y << endl;
  1420. cout << "check" << ' ' << s.first << ' ' << s.second << endl;
  1421. cout << "check" << ' ' << t.first << ' ' << t.second << endl;*/
  1422. }
  1423. if (!line.empty() && abs(line.back().first - s.first) + abs(line.back().second - s.second) == 2)
  1424. {
  1425. ;
  1426. }
  1427. else
  1428. line.push_back(make_pair(s.first, s.second));
  1429. }
  1430. return getTime() - t1;
  1431. }
  1432. }TTSF;
  1433. pair<int, int> lastLoc[4] = { make_pair(-1,-1),make_pair(-1,-1),make_pair(-1,-1),make_pair(-1,-1) };
  1434. long long lastSeen[4] = { -1,-1,-1,-1 };
  1435. int playerstate[4] = { 0 , 0 , 0 , 0 };
  1436. double player_v[4] = { 0.0 , 0.0 , 0.0 , 0.0 }; // -1 代表无法计算
  1437. bool TAGONLYTEACHER = 0;
  1438. pair<int, double> Shoot(ITrickerAPI& api, tuple<double, double, double, double>bullet) {
  1439. auto students = api.GetStudents();
  1440. auto self = api.GetSelfInfo();
  1441. // 经测试facing direction是移动方向,但是他不动我也没有办法。
  1442. vector< tuple<double, double, int> > studentsWithAngle; // theta , time , id
  1443. int timid = 0;
  1444. for (auto& s : students) {
  1445. timid++;
  1446. int id = s->playerID, v = player_v[id];
  1447. if (v != -1) {
  1448. double t = 0.1; // s
  1449. double theta = 0.0; // rad
  1450. double Speed = get<0>(bullet); // Replace 0.0 with the known value of Speed
  1451. double CastTime = get<2>(bullet) / 1000; // Replace 0.0 with the known value of CastTime
  1452. double self_x = self->x; // Replace 0.0 with the known value of self->x
  1453. double self_y = self->y; // Replace 0.0 with the known value of self->y
  1454. double sx = s->x; // Replace 0.0 with the known value of sx
  1455. double sy = s->y; // Replace 0.0 with the known value of sy
  1456. double tx, ty;
  1457. if (v == 0) {
  1458. t = sqrt(1.0 * (self->x - s->x) * (self->x - s->x) + 1.0 * (self->y - s->y) * (self->y - s->y)) / Speed;
  1459. theta = atan2(s->y - self->y, s->x - self->x);
  1460. tx = sx + v * cos(s->facingDirection) * (t + CastTime);
  1461. ty = sy + v * sin(s->facingDirection) * (t + CastTime);
  1462. }
  1463. else if (Speed < 70000) {
  1464. /*
  1465. 解方程组
  1466. sx + vx * (t + CastTime) = self -> x + t * Speed * cos(theta)
  1467. sy + vy * (t + CastTime) = self -> y + t * Speed * sin(theta)
  1468. */
  1469. double vx = v * cos(s->facingDirection); // Replace 0.0 with the known value of vx
  1470. double vy = v * sin(s->facingDirection); // Replace 0.0 with the known value of vy
  1471. //api.Print(fmt::format("vx = {}, vy = {}", vx, vy));
  1472. // 使用二分查找解t
  1473. int l = 0, r = 1001, mid;
  1474. while (l < r) {
  1475. mid = (l + r) >> 1;
  1476. double tx = sx + vx * (mid / 1000.0 + CastTime);
  1477. double ty = sy + vy * (mid / 1000.0 + CastTime);
  1478. double dis = sqrt((self->x - tx) * (self->x - tx) + (self->y - ty) * (self->y - ty));
  1479. if (dis < Speed * (mid / 1000.0)) {
  1480. r = mid;
  1481. }
  1482. else {
  1483. l = mid + 1;
  1484. }
  1485. }
  1486. t = l / 1000.0;
  1487. //tx = sx + v * cos(s->facingDirection) * (t + CastTime);
  1488. //ty = sy + v * sin(s->facingDirection) * (t + CastTime);
  1489. tx = sx, ty = sy;
  1490. theta = atan2(ty - self->y, tx - self->x);
  1491. }
  1492. else {
  1493. t = sqrt(1.0 * (self->x - s->x) * (self->x - s->x) + (self->y - s->y) * (self->y - s->y)) / Speed;
  1494. theta = atan2(s->y - self->y, s->x - self->x);
  1495. tx = sx + v * cos(s->facingDirection) * (t + CastTime);
  1496. ty = sy + v * sin(s->facingDirection) * (t + CastTime);
  1497. }
  1498. //判断是否仍在射程之内
  1499. if (t >= get<1>(bullet) / Speed) continue; //不在射程内
  1500. t -= 1200.0 / Speed; //实际上子弹出来的时候是和发射者相切的,那么飞行总距离要小1200
  1501. //避免鞭尸的射击判定
  1502. bool blocked_by_body = false;
  1503. for (auto& s : students) if (s->playerState == PlayerState::Addicted) {
  1504. //求(s->x , s->y)到线段(tx , ty) , (self ->x , self->y)的距离
  1505. double a = self->y - ty;
  1506. double b = tx - self->x;
  1507. double c = self->x * ty - tx * self->y;
  1508. double dis = abs(a * s->x + b * s->y + c) / sqrt(a * a + b * b);
  1509. if (dis <= 400) {
  1510. blocked_by_body = true;
  1511. break;
  1512. }
  1513. }
  1514. //在射程内,可以尝试射击
  1515. if (blocked_by_body == false && TTSF.havebulletWay(self->x, self->y, tx, ty)) {
  1516. studentsWithAngle.push_back(make_tuple(theta, t, timid - 1));
  1517. }
  1518. }
  1519. }
  1520. /* 射击优先级设计 射击分数最大的
  1521. 一次能射死 1000 , 学霸 1000 + (身上的冥想进度 / 100) , 开心果 800 , 运动员500 , 教师 0
  1522. 沉迷度三档 2000 , 1000 , 0
  1523. 正在开校门的10000 , 正在做作业的 3000 , 正在开箱子的800
  1524. 有二倍速的 - 2000 , 有复活甲的 - 500 , 如果在此之上还一次能射死的再 - 2000 , 有盾的 - 1000 , 如果自己有破盾就变为+1000
  1525. 正在唤醒的 + 3000
  1526. t * Speed<=200的 + 2000 , <= 300 的 + 1500 , <= 400的 + 500 , <= 500 的 + 0 , <= 700 的-500 , 剩余的 - 5000
  1527. 已经沉迷了的 - 20000
  1528. */
  1529. int maxScore = -0x3f3f3f3f;
  1530. double maxScoreangle = 0;
  1531. int Damage = get<3>(bullet);
  1532. for (auto& s : studentsWithAngle) {
  1533. int Score = 0;
  1534. int id = get<2>(s);
  1535. auto& p = students[id];
  1536. // 一次能射死 1000
  1537. if (p->determination <= Damage) {
  1538. Score += 1000;
  1539. }
  1540. // 学霸 1000 + (身上的冥想进度 / 100) , 开心果 800 , 运动员500 , 教师 0
  1541. if (p->studentType == StudentType::StraightAStudent) Score += 1000;//没有查看冥想进度的接口,你没资格啊
  1542. else if (p->studentType == StudentType::Sunshine) Score += 800;
  1543. else if (p->studentType == StudentType::Athlete) Score += 600;
  1544. else if (p->studentType == StudentType::Teacher) Score += -3000;
  1545. if (TAGONLYTEACHER) Score += 3000;
  1546. // 沉迷度三档 2000 , 1000 , 0
  1547. // 使用lambda表达式计算沉迷度的档次,addiction < maxAddiction * 0.33为最低档,addiction > maxAddiction * 0.66为最高档
  1548. auto addictionLevel = [&](int addiction, int maxAddiction) {
  1549. if (addiction < maxAddiction * 0.33) return 0;
  1550. else if (addiction > maxAddiction * 0.66) return 2;
  1551. else return 1;
  1552. };
  1553. Score += addictionLevel(p->addiction, maxAddiction[p->studentType]) * 1000;
  1554. // 正在开校门的10000 , 正在做作业的 3000 , 正在开箱子的800 , 正在唤醒的 + 3000, 正在爬树的 + 800, 正在鼓舞的 + 800, 正在被鼓舞的 + 800
  1555. if (p->playerState == PlayerState::OpeningAGate) Score += 10000;
  1556. else if (p->playerState == PlayerState::Learning
  1557. || p->playerState == PlayerState::Stunned) Score += 3000;
  1558. else if (p->playerState == PlayerState::OpeningAChest
  1559. || p->playerState == PlayerState::Encouraging
  1560. || p->playerState == PlayerState::Encouraged
  1561. || p->playerState == PlayerState::Rousing
  1562. || p->playerState == PlayerState::Climbing
  1563. ) Score += 7000;
  1564. else if (p->playerState == PlayerState::Addicted
  1565. || p->playerState == PlayerState::Roused)
  1566. Score -= 20000;
  1567. // 有二倍速的 - 2000 , 有复活甲的 - 500 , 如果在此之上还一次能射死的再 - 2000 , 有盾的 - 1000 , 如果自己有破盾就变为+1000
  1568. // 太复杂了,暂时不写了
  1569. // t * Speed<=200的 + 2000 , <= 300 的 + 1500 , <= 400的 + 500 , <= 500 的 + 0 , <= 700 的-500 , 剩余的 - 5000
  1570. double t = get<1>(s);
  1571. double speed = p->speed * abs(std::cos(p->facingDirection - get<0>(s) - pi / 2));
  1572. //api.Print(fmt::format("t: {}, speed: {}", t, speed));
  1573. if (t * speed <= 200) Score += 2000;
  1574. else if (t * speed <= 300) Score += 1500;
  1575. else if (t * speed <= 400) Score += 500;
  1576. else if (t * speed <= 500) Score += 0;
  1577. else if (t * speed <= 800) Score -= 500;
  1578. else Score -= 5000;
  1579. // 优先级最高的
  1580. if (Score > maxScore) {
  1581. maxScore = Score;
  1582. maxScoreangle = get<0>(s);
  1583. }
  1584. //api.Print(fmt::format("id = {} , score = {}", id, Score));
  1585. }
  1586. //输出maxScore
  1587. //api.Print(fmt::format("maxScore: {}", maxScore));
  1588. // 如果周围有cd好了的教师则 - 10000 , 除非自己的buff中有invisible
  1589. bool will_be_shocked = false;
  1590. for (auto& s : students) if (s->studentType == StudentType::Teacher) {
  1591. //输出技能cd
  1592. //api.Print(fmt::format("teacher skill cd: {}", s->timeUntilSkillAvailable[0]));
  1593. if (s->timeUntilSkillAvailable[0] < get<2>(bullet)) {
  1594. will_be_shocked = true;
  1595. break;
  1596. }
  1597. }
  1598. // 加入了判断是否为刺客,如果是刺客,且隐身技能cd好了,就用技能
  1599. if (will_be_shocked && maxScore > 0 && self->trickerType == TrickerType::Assassin && self->timeUntilSkillAvailable[0] == 0) {
  1600. api.UseSkill(0);
  1601. this_thread::sleep_for(chrono::milliseconds(3));
  1602. }
  1603. // 如果自己身上有invisible,就不用管了
  1604. bool isInvisible = false;
  1605. for (auto& t : self->buff) if (t == TrickerBuffType::Invisible) {
  1606. isInvisible = true;
  1607. break;
  1608. }
  1609. if (isInvisible == false && will_be_shocked == true) {
  1610. maxScore -= 1000; // 不管了,杀
  1611. }
  1612. api.Print(fmt::format(" maxScore : {} ", maxScore));
  1613. // 是否射击?
  1614. return make_pair(maxScore, maxScoreangle);
  1615. }
  1616. void AI::play(ITrickerAPI& api)
  1617. {
  1618. auto self = api.GetSelfInfo();
  1619. auto actualtime = TTSF.getTime();
  1620. auto students = api.GetStudents();
  1621. TTSF.updateMap(api);
  1622. // 计算视野内学生的速度,以及上次被看见的时间,是否是尸体等等信息的预处理
  1623. static int TeacherID = 0, IsTeacherAddicted = 0;
  1624. for (auto& s : students) {
  1625. int id = s->playerID, v = -1;
  1626. if (actualtime - lastSeen[id] <= 200)
  1627. if (lastLoc[id].first == s->x && lastLoc[id].second == s->y)
  1628. v = 0;
  1629. else
  1630. v = s->speed;
  1631. //api.Print(fmt::format("id: {} , x: {} , y:{} , sx:{} , sy:{} , v: {}", id, s->x,s->y,self->x,self->y, v));
  1632. player_v[id] = v;
  1633. //把尸体看作路障
  1634. if (s->studentType == THUAI6::StudentType::Teacher) {
  1635. TTSF.addExist(lastLoc[id], 400, -1);
  1636. TTSF.addExist(make_pair(s->x, s->y), 400, 1);
  1637. playerstate[id] = 1;
  1638. TeacherID = id;
  1639. if (s->playerState == PlayerState::Addicted)
  1640. IsTeacherAddicted = 1;
  1641. else
  1642. IsTeacherAddicted = 0;
  1643. }
  1644. else {
  1645. if (s->playerState == PlayerState::Addicted) {
  1646. if (playerstate[id] == 0)
  1647. TTSF.addExist(make_pair(s->x, s->y), 400, 1);
  1648. playerstate[id] = 1;
  1649. }
  1650. else { //复活了就去除路障
  1651. if (playerstate[id] == 1)
  1652. TTSF.addExist(lastLoc[id], 400, -1);
  1653. playerstate[id] = 0;
  1654. }
  1655. }
  1656. //更新上一次见到的位置
  1657. lastSeen[id] = actualtime;
  1658. lastLoc[id] = make_pair(s->x, s->y);
  1659. }
  1660. static int kaqiangcleantag = 0;
  1661. //无法操作时,直接返回
  1662. if (self->playerState == PlayerState::Attacking || self->playerState == PlayerState::Swinging
  1663. || self->playerState == PlayerState::Stunned || self->playerState == PlayerState::Climbing) {
  1664. kaqiangcleantag = 1;//无法操作时无法判断是否卡墙了。
  1665. return;
  1666. }
  1667. static int priority = 0x3f3f3f3f;
  1668. {
  1669. static int lx = -1, ly = -1;
  1670. static double lt = 0, ltheta = 0;
  1671. if (kaqiangcleantag) {
  1672. lx = ly = -1;
  1673. kaqiangcleantag = 0;
  1674. }
  1675. bool bodyonface = 0;
  1676. for (auto s : students) {
  1677. if (1.0 * (self->x - s->x) * (self->x - s->x) + (self->y - s->y) * (self->y - s->y) < 1000 * 1000 && s->playerState != PlayerState::Addicted) {
  1678. bodyonface = 1;
  1679. break;
  1680. }
  1681. }
  1682. if (lx == self->x && ly == self->y && priority < 0x3f3f3f3f) {//有目标但是不动
  1683. if (Constants::Assassin::alertnessRadius / self->trickDesire <= 1000 && !bodyonface) {
  1684. int x = api.GridToCell(self->x), y = api.GridToCell(self->y);
  1685. double alpha = 0;
  1686. bool flg = 0;
  1687. for (int i = -1; i <= 1; i++)
  1688. for (int j = -1; j <= 1; j++)
  1689. if (i == 0 || j == 0)
  1690. if (i | j)
  1691. if (TTSF.mp[x + i][y + j] == THUAI6::PlaceType::Grass) {
  1692. alpha = atan2(api.CellToGrid(y + j) - self->y, api.CellToGrid(x + i) - self->x);
  1693. flg = 1;
  1694. goto outside;
  1695. }
  1696. outside:
  1697. if (TTSF.mp[TTSF.adr.first][TTSF.adr.second] == THUAI6::PlaceType::Grass) {
  1698. alpha = atan2(api.CellToGrid(TTSF.adr.second) - self->y, api.CellToGrid(TTSF.adr.first) - self->x);
  1699. flg = 1;
  1700. }
  1701. if (flg) {
  1702. if (self->timeUntilSkillAvailable[0] == 0)
  1703. api.UseSkill(0);
  1704. if (self->timeUntilSkillAvailable[1] == 0)
  1705. api.UseSkill(1);
  1706. api.Attack(alpha);
  1707. }
  1708. }
  1709. if (actualtime - lt > 300) {
  1710. api.EndAllAction();
  1711. this_thread::sleep_for(chrono::milliseconds(5));
  1712. static double lstdir = TTSF.lstdir;
  1713. api.Move(300, lstdir + pi);
  1714. lstdir += pi / 5;
  1715. this_thread::sleep_for(chrono::milliseconds(300));
  1716. return;
  1717. }
  1718. }
  1719. else {
  1720. lt = actualtime;
  1721. }
  1722. lx = self->x, ly = self->y;
  1723. }
  1724. // 射击判断
  1725. if (self->timeUntilSkillAvailable[1] == 0) {
  1726. auto Knife = Shoot(api, bulletInfo[BulletType::FlyingKnife]);
  1727. if (Knife.first >= 5000) {
  1728. api.EndAllAction();
  1729. this_thread::sleep_for(chrono::milliseconds(1));
  1730. api.UseSkill(1);
  1731. this_thread::sleep_for(chrono::milliseconds(1));
  1732. api.Attack(Knife.second);
  1733. return;
  1734. }
  1735. }
  1736. auto ShootItem = Shoot(api, bulletInfo[BulletType::CommonAttackOfTricker]);
  1737. //输出ShootItem
  1738. //api.Print(fmt::format("ShootItem.first = {} , ShootItem.second = {}", ShootItem.first, ShootItem.second));
  1739. if (ShootItem.first >= 0) {
  1740. api.EndAllAction();
  1741. api.Attack(ShootItem.second);
  1742. return;
  1743. }
  1744. bool OnlyTeacher = 1;
  1745. for (int i = 0; i < 3; i++) if (playerstate[i] == 0)
  1746. OnlyTeacher = 0;
  1747. //OnlyTeacher = 1;
  1748. if (OnlyTeacher && !IsTeacherAddicted) {
  1749. playerstate[TeacherID] = 0;
  1750. }
  1751. TAGONLYTEACHER = OnlyTeacher;
  1752. // 优先级:1.追看得见的 , 2.追1s内的最后出现位置 , 3/4 先听,然后去找作业/听到的位置(可能按照距离决定先后) , 5 追10s内出现的最后位置 , 6 面向地图编程
  1753. //追看的见的 优先级为1 同优先级时替换目标
  1754. {
  1755. if (students.empty() == false && priority >= 1) {
  1756. // 找出欧几里得距离最近的不是教师的student
  1757. long long minDist = 1e18;
  1758. int minDistid = -1;
  1759. for (auto s : students)if (s->playerState != PlayerState::Addicted && ((OnlyTeacher) || s->studentType != StudentType::Teacher)) {
  1760. long long dist = (s->x - self->x) * (s->x - self->x) + (s->y - self->y) * (s->y - self->y);
  1761. if (dist < minDist) {
  1762. minDist = dist;
  1763. minDistid = s->playerID;
  1764. }
  1765. }
  1766. if (minDistid != -1) {
  1767. TTSF.changeAddr(api, make_pair(lastLoc[minDistid].first / 1000, lastLoc[minDistid].second / 1000));
  1768. TTSF.BFS(make_pair(self->x / 1000, self->y / 1000), TTSF.adr, api);//应用翻窗速度。。。
  1769. priority = 1;
  1770. goto getsetgo;
  1771. }
  1772. }
  1773. }
  1774. //追最后1s内目击地点 优先级为2 同优先级不替换
  1775. if (priority > 2) {
  1776. long long LstSeenTim = -1;
  1777. pair<int, int> LstSeenPos = make_pair(-1, -1);
  1778. for (int i = 0; i < 4; i++) if (playerstate[i] == 0)
  1779. {
  1780. if (LstSeenTim < lastSeen[i])
  1781. {
  1782. LstSeenTim = lastSeen[i];
  1783. LstSeenPos = lastLoc[i];
  1784. }
  1785. }
  1786. if (actualtime - LstSeenTim <= 1000) {
  1787. TTSF.changeAddr(api, make_pair(LstSeenPos.first / 1000, LstSeenPos.second / 1000));
  1788. TTSF.BFS(make_pair(self->x / 1000, self->y / 1000), TTSF.adr, api);
  1789. priority = 2;
  1790. goto getsetgo;
  1791. }
  1792. }
  1793. //追听得见的 优先级为3/4 同优先级不替换
  1794. {
  1795. static double lastclassVolume = 0, dv = 0, lt = 0;
  1796. static int lx = -1, ly = -1, tim = 0;
  1797. static int targetcls = -1;
  1798. static set<int>candidate;
  1799. static double sumerr[11] = {};
  1800. static int lprogress[11] = {}, progress[11] = {};
  1801. memset(progress, -1, sizeof progress);
  1802. for (int i = 0; i < TTSF.cls.size(); i++)
  1803. if (api.HaveView(api.CellToGrid(TTSF.cls[i].first), api.CellToGrid(TTSF.cls[i].second)))
  1804. progress[i] = api.GetClassroomProgress(TTSF.cls[i].first, TTSF.cls[i].second);
  1805. if (priority >= 3) {
  1806. if (self->classVolume > 0) {
  1807. auto isclear = [&](double x, double y, int id) {
  1808. if (self->trickDesire * (sqrt((x - self->x) * (x - self->x) + (y - self->y) * (y - self->y)) + 2000) < Constants::Assassin::alertnessRadius)
  1809. return true;
  1810. if (api.HaveView(int(x), int(y)))
  1811. if (progress[id] == lprogress[id])
  1812. return true;
  1813. return false;
  1814. };
  1815. auto chk = [&](double x, double y, int id) {
  1816. if ((x - self->x) * (x - self->x) + (y - self->y) * (y - self->y) > Constants::Assassin::alertnessRadius * Constants::Assassin::alertnessRadius)
  1817. return false;
  1818. if (self->classVolume * sqrt((x - self->x) * (x - self->x) + (y - self->y) * (y - self->y)) > Constants::Assassin::alertnessRadius)
  1819. return false;
  1820. if (self->trickDesire * (sqrt((x - self->x) * (x - self->x) + (y - self->y) * (y - self->y)) + 2000) < Constants::Assassin::alertnessRadius)
  1821. return false;
  1822. if (api.HaveView(int(x), int(y))) {
  1823. if (progress[id] == lprogress[id])
  1824. return false;
  1825. }
  1826. return true;
  1827. };
  1828. if (targetcls != -1 && isclear(api.CellToGrid(TTSF.cls[targetcls].first), api.CellToGrid(TTSF.cls[targetcls].second), targetcls)) {// 突然听不到目标点周围有人在做作业了,说明清剿完毕
  1829. lastclassVolume = dv = lt = 0;
  1830. lx = ly = -1;
  1831. targetcls = -1;
  1832. memset(sumerr, 0, sizeof sumerr);
  1833. tim = 0;
  1834. candidate.clear();
  1835. }
  1836. bool vis[11] = {};
  1837. for (int i = 0; i < TTSF.cls.size(); i++)
  1838. if (chk(api.CellToGrid(TTSF.cls[i].first), api.CellToGrid(TTSF.cls[i].second), i)) {
  1839. vis[i] = 1;
  1840. }
  1841. else vis[i] = 0;
  1842. if (candidate.empty()) {
  1843. for (int i = 0; i < TTSF.cls.size(); i++)
  1844. if (vis[i])
  1845. candidate.insert(i);
  1846. }
  1847. else {
  1848. for (int i = 0; i < TTSF.cls.size(); i++)
  1849. if (!vis[i] && candidate.count(i))
  1850. candidate.erase(i);
  1851. if (candidate.empty()) {
  1852. lastclassVolume = dv = lt = 0;
  1853. lx = ly = -1;
  1854. memset(sumerr, 0, sizeof sumerr);
  1855. targetcls = -1;
  1856. tim = 0;
  1857. candidate.clear();
  1858. }
  1859. }
  1860. {
  1861. if (lx == self->x && ly == self->y) {
  1862. dv = (self->classVolume - lastclassVolume) / lastclassVolume / (actualtime - lt);
  1863. }
  1864. if (lx == -1 && ly == -1) {
  1865. lx = self->x, ly = self->y;
  1866. lt = actualtime;
  1867. lastclassVolume = self->classVolume;
  1868. api.EndAllAction();
  1869. this_thread::sleep_for(chrono::milliseconds(48));
  1870. priority = 0x3f3f3f3f;
  1871. return;
  1872. }
  1873. double calclassVolume = lastclassVolume * (1 + dv * (actualtime - lt));
  1874. for (auto s : candidate) {
  1875. sumerr[s] += fabs(calclassVolume
  1876. * sqrt(1.0 * (api.CellToGrid(TTSF.cls[s].first) - lx) * (api.CellToGrid(TTSF.cls[s].first) - lx) + 1.0 * (api.CellToGrid(TTSF.cls[s].second) - ly) * (api.CellToGrid(TTSF.cls[s].second) - ly))
  1877. - self->classVolume
  1878. * sqrt(1.0 * (api.CellToGrid(TTSF.cls[s].first) - self->x) * (api.CellToGrid(TTSF.cls[s].first) - self->x) + 1.0 * (api.CellToGrid(TTSF.cls[s].second) - self->y) * (api.CellToGrid(TTSF.cls[s].second) - self->y)));
  1879. }
  1880. //每2s选择sumerr最小的
  1881. if ((tim++) % 20 == 0) {
  1882. double minerr = 1e20;
  1883. targetcls = -1;
  1884. for (auto s : candidate) {
  1885. if (minerr > sumerr[s]) {
  1886. minerr = sumerr[s];
  1887. targetcls = s;
  1888. }
  1889. //输出cls[s].first , cls[s].second
  1890. //api.Print(fmt :: format("cls[{}] = ({}, {})", s, TTSF.cls[s].first, TTSF.cls[s].second));
  1891. }
  1892. if (targetcls != -1) {
  1893. TTSF.changeAddr(api, make_pair(TTSF.cls[targetcls].first, TTSF.cls[targetcls].second));
  1894. TTSF.BFS(make_pair(self->x / 1000, self->y / 1000), TTSF.adr, api);
  1895. priority = 3;
  1896. goto getsetgo;
  1897. }
  1898. }
  1899. }
  1900. }
  1901. else {
  1902. if (lx != -1) { // 突然听不见了
  1903. for (auto s : TTSF.cls)
  1904. if (fabs(1.0 * (api.CellToGrid(s.first) - self->x) * (api.CellToGrid(s.first) - self->x)
  1905. + 1.0 * (api.CellToGrid(s.second) - self->y) * (api.CellToGrid(s.second) - self->y)
  1906. - Constants::Assassin::alertnessRadius * Constants::Assassin::alertnessRadius) < 1000 * 1000) {
  1907. TTSF.changeAddr(api, make_pair(s.first, s.second));
  1908. TTSF.BFS(make_pair(self->x / 1000, self->y / 1000), TTSF.adr, api);
  1909. priority = 3;
  1910. goto getsetgo;
  1911. }
  1912. }
  1913. lastclassVolume = dv = lt = 0;
  1914. lx = ly = -1;
  1915. targetcls = -1;
  1916. memset(sumerr, 0, sizeof sumerr);
  1917. tim = 0;
  1918. candidate.clear();
  1919. }
  1920. }
  1921. memcpy(lprogress, progress, sizeof progress);
  1922. }
  1923. static double Nottoheartill = 0;
  1924. static bool hearing = false; // 是否正在听
  1925. static vector< tuple<double, double, double, double> > circles; // 圆心坐标,半径 , 过了的时间 , 此数组用于听trickDesire
  1926. if (priority > 4 && actualtime > Nottoheartill) {
  1927. static double lstalpha = 0, lsttheta = 0; // 上一次的alpha和theta
  1928. if (hearing == true) {
  1929. if (self->trickDesire <= 0) { // 听不到了
  1930. hearing = false;
  1931. goto priority3;
  1932. }
  1933. else if (circles.empty() == false) {
  1934. // 还在听
  1935. double lastangle = atan2(self->y - get<1>(circles.back()), self->x - get<0>(circles.back()));
  1936. circles.push_back(make_tuple(self->x, self->y,
  1937. Constants::Assassin::alertnessRadius / self->trickDesire, actualtime));
  1938. if (circles.size() >= 3) { // 尝试计算目标起始点和速度
  1939. //具体思路 写出三个圆的方程,然后代入两个变量theta(为初始时的极角)和alpha(为对方速度极角),然后使用牛顿迭代数值求解
  1940. int id = circles.size() - 1;
  1941. double x[3] = { get<0>(circles[id - 2]), get<0>(circles[id - 1]), get<0>(circles[id]) },
  1942. y[3] = { get<1>(circles[id - 2]), get<1>(circles[id - 1]), get<1>(circles[id]) },
  1943. r[3] = { get<2>(circles[id - 2]), get<2>(circles[id - 1]), get<2>(circles[id]) },
  1944. t[3] = { get<3>(circles[id - 2]), get<3>(circles[id - 1]), get<3>(circles[id]) };
  1945. //如果三点共线,则无法计算
  1946. if (fabs((x[0] - x[1]) * (y[1] - y[2]) - (x[1] - x[2]) * (y[0] - y[1])) < 1e-2) {
  1947. goto continuetohear;
  1948. }
  1949. //api.Print(fmt::format("x[{}]= {}, y[{}] = {}, r[{}] = {}, t[{}] = {}", 0, x[0], 0, y[0], 0, r[0], 0, t[0]));
  1950. //api.Print(fmt::format("x[{}]= {}, y[{}] = {}, r[{}] = {}, t[{}] = {}", 1, x[1], 1, y[1], 1, r[1], 1, t[1]));
  1951. //api.Print(fmt::format("x[{}]= {}, y[{}] = {}, r[{}] = {}, t[{}] = {}", 2, x[2], 2, y[2], 2, r[2], 2, t[2]));
  1952. //先判断三个圆是否有一个交点
  1953. //if(0) // disabled
  1954. {
  1955. /*
  1956. 圆方程为 (x - x[i])^2 + (y - y[i])^2 = r[i]^2
  1957. */
  1958. // 计算前两个圆的两个交点
  1959. auto distance = [](double x1, double y1, double x2, double y2) {
  1960. return std::sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
  1961. };
  1962. double d = distance(x[0], y[0], x[1], y[1]);
  1963. if (d > r[0] + r[1] || d < std::abs(r[0] - r[1])) {
  1964. //api.Print("No intersection points.");
  1965. goto continuetohear;
  1966. }
  1967. double a = (r[0] * r[0] - r[1] * r[1] + d * d) / (2 * d);
  1968. double h = std::sqrt(r[0] * r[0] - a * a);
  1969. double x3 = x[0] + a * (x[1] - x[0]) / d;
  1970. double y3 = y[0] + a * (y[1] - y[0]) / d;
  1971. double x1 = x3 + h * (y[1] - y[0]) / d;
  1972. double y1 = y3 - h * (x[1] - x[0]) / d;
  1973. double x2 = x3 - h * (y[1] - y[0]) / d;
  1974. double y2 = y3 + h * (x[1] - x[0]) / d;
  1975. //api.Print(fmt::format("x1 = {} , y1 = {}", x1, y1));
  1976. //api.Print(fmt::format("dis = {}", (x1 - x[2]) * (x1 - x[2]) + (y1 - y[2]) * (y1 - y[2]) - r[2] * r[2]));
  1977. //代入两个交点,判断是否在第三个圆上
  1978. if (fabs((x1 - x[2]) * (x1 - x[2]) + (y1 - y[2]) * (y1 - y[2]) - r[2] * r[2]) < 100.0 && x1 >= 1000 && x1 < 49000 && y1 >= 1000 && y1 < 49000) {
  1979. // api.Print(fmt::format("x1 = {} , y1 = {}", x1, y1));
  1980. hearing = false;
  1981. for (int i = 0; i < 4; i++)
  1982. if (playerstate[i] == 1)
  1983. if ((x1 - lastLoc[i].first) * (x1 - lastLoc[i].first) + (y1 - lastLoc[i].second) * (y1 - lastLoc[i].second) < 22000 * 22000) {
  1984. Nottoheartill = actualtime + 6000;
  1985. goto priority3;
  1986. }
  1987. priority = 4;
  1988. TTSF.changeAddr(api, make_pair((int)x1 / 1000, (int)y1 / 1000));
  1989. TTSF.BFS(make_pair(self->x / 1000, self->y / 1000), TTSF.adr, api);
  1990. lsttheta = atan2(y1 - y[2], x1 - x[2]);
  1991. goto getsetgo;
  1992. }
  1993. //api.Print(fmt::format("x2 = {} , y2 = {}", x2, y2));
  1994. if (fabs((x2 - x[2]) * (x2 - x[2]) + (y2 - y[2]) * (y2 - y[2]) - r[2] * r[2]) < 100.0 && x2 >= 1000 && x2 < 49000 && y2 >= 1000 && y2 < 49000) {
  1995. //api.Print(fmt::format("x2 = {} , y2 = {}", x2, y2));
  1996. hearing = false;
  1997. for (int i = 0; i < 4; i++)
  1998. if (playerstate[i] == 1)
  1999. if ((x2 - lastLoc[i].first) * (x2 - lastLoc[i].first) + (y2 - lastLoc[i].second) * (y2 - lastLoc[i].second) < 22000 * 22000) {
  2000. Nottoheartill = actualtime + 6000;
  2001. goto priority3;
  2002. }
  2003. priority = 4;
  2004. TTSF.changeAddr(api, make_pair((int)x2 / 1000, (int)y2 / 1000));
  2005. TTSF.BFS(make_pair(self->x / 1000, self->y / 1000), TTSF.adr, api);
  2006. lsttheta = atan2(y2 - y[2], x2 - x[2]);
  2007. goto getsetgo;
  2008. }
  2009. }
  2010. t[1] -= t[0], t[2] -= t[0], t[0] = 0;
  2011. x[1] -= x[0], x[2] -= x[0], x[0] = 0;
  2012. y[1] -= y[0], y[2] -= y[0], y[0] = 0;
  2013. //无交点则v = 3000
  2014. {
  2015. //初始坐标为(r\cos\theta,r\sin\theta) , 速度为(v\cos\alpha,v\sin\alpha)
  2016. /*
  2017. (r\cos\theta + v\cos\alpha t[1] - x[1])^2 + (r\sin\theta + v\sin\alpha t[1] - y[1])^2 = r[1]^2
  2018. (r\cos\theta + v\cos\alpha t[2] - x[2])^2 + (r\sin\theta + v\sin\alpha t[2] - y[2])^2 = r[2]^2
  2019. */
  2020. // 牛顿迭代
  2021. // Define the known values
  2022. double R = r[0];
  2023. double v = 3;
  2024. // Define the system of equations
  2025. auto f1 = [&](double theta, double alpha) {
  2026. return std::pow(R * std::cos(theta) + v * std::cos(alpha) * t[1] - x[1], 2) +
  2027. std::pow(R * std::sin(theta) + v * std::sin(alpha) * t[1] - y[1], 2) - std::pow(r[1], 2);
  2028. };
  2029. auto f2 = [&](double theta, double alpha) {
  2030. return std::pow(R * std::cos(theta) + v * std::cos(alpha) * t[2] - x[2], 2) +
  2031. std::pow(R * std::sin(theta) + v * std::sin(alpha) * t[2] - y[2], 2) - std::pow(r[2], 2);
  2032. };
  2033. // Define the Jacobian matrix
  2034. double delta = 1e-6;
  2035. std::array<std::array<std::function<double(double, double)>, 2>, 2> J{ {
  2036. {{[&](double theta, double alpha) { return (f1(theta + delta, alpha) - f1(theta, alpha)) / delta; },
  2037. [&](double theta, double alpha) { return (f1(theta, alpha + delta) - f1(theta, alpha)) / delta; }}},
  2038. {{[&](double theta, double alpha) { return (f2(theta + delta, alpha) - f2(theta, alpha)) / delta; },
  2039. [&](double theta, double alpha) { return (f2(theta, alpha + delta) - f2(theta, alpha)) / delta; }}}
  2040. } };
  2041. // Initial guess
  2042. double theta = 0.0;
  2043. double alpha = 0.0;
  2044. int tim = 0, max_iter = 30;
  2045. double eps = 1e-6;
  2046. // Newton-Raphson method
  2047. for (int i = 0; i < max_iter; ++i, tim++) {
  2048. double J11 = J[0][0](theta, alpha);
  2049. double J12 = J[0][1](theta, alpha);
  2050. double J21 = J[1][0](theta, alpha);
  2051. double J22 = J[1][1](theta, alpha);
  2052. double det = J11 * J22 - J12 * J21;
  2053. if (fabs(det) < 1e-20) {
  2054. tim = max_iter;
  2055. break;
  2056. }
  2057. //api.Print(fmt::format("J11 = {}, J12 = {}, J21 = {}, J22 = {}, det = {}", J11, J12, J21, J22, det));
  2058. double dx = (-J22 * f1(theta, alpha) + J12 * f2(theta, alpha)) / det;
  2059. double dy = (J21 * f1(theta, alpha) - J11 * f2(theta, alpha)) / det;
  2060. theta += dx;
  2061. alpha += dy;
  2062. if (std::abs(dx) < eps && std::abs(dy) < eps)
  2063. break;
  2064. }
  2065. //api.Print(fmt::format("theta = {}, alpha = {}", theta, alpha));
  2066. if (tim >= max_iter) {
  2067. //api.Print("No solution");
  2068. goto continuetohear;
  2069. }
  2070. lsttheta = theta, lstalpha = alpha;
  2071. double tx = r[0] * cos(theta) + v * cos(alpha) * t[2] + get<0>(circles[id - 2]),
  2072. ty = r[0] * sin(theta) + v * sin(alpha) * t[2] + get<1>(circles[id - 2]);
  2073. if (tx < 1000 || tx > 49000 || ty < 1000 || ty > 49000)
  2074. goto continuetohear;
  2075. for (int i = 0; i < 4; i++)
  2076. if (playerstate[i] == 1)
  2077. if ((tx - lastLoc[i].first) * (tx - lastLoc[i].first) + (ty - lastLoc[i].second) * (ty - lastLoc[i].second) < 2000 * 2000) {
  2078. hearing = false;
  2079. goto priority3;
  2080. }
  2081. // api.Print(fmt::format("tx = {}, ty = {}", tx, ty));
  2082. priority = 4;
  2083. TTSF.changeAddr(api, make_pair((int)tx / 1000, (int)ty / 1000));
  2084. TTSF.BFS(make_pair(self->x / 1000, self->y / 1000), TTSF.adr, api);
  2085. hearing = false;
  2086. goto getsetgo;
  2087. }
  2088. }
  2089. continuetohear:
  2090. api.EndAllAction();
  2091. //输出lastangle和当前位置
  2092. //api.Print(fmt::format("lastangle = {}, x = {}, y = {}", lastangle, self->x, self->y));
  2093. api.Move(100, lastangle + pi / 2);
  2094. this_thread::sleep_for(chrono::milliseconds(48));
  2095. return;
  2096. }
  2097. }
  2098. else if (self->trickDesire > 0) {
  2099. circles.clear();
  2100. double R0 = Constants::Assassin::alertnessRadius / self->trickDesire;
  2101. if (Constants::Assassin::alertnessRadius - R0 <= 1000) {
  2102. // 不能听
  2103. goto priority3;
  2104. }
  2105. hearing = true;// 开始听
  2106. api.EndAllAction();
  2107. circles.push_back(make_tuple(self->x, self->y, R0, actualtime));
  2108. int mx = api.CellToGrid(self->x / 1000), my = api.CellToGrid(self->y / 1000);
  2109. double alpha = 0;
  2110. if (self->x >= mx && self->y >= my) alpha = pi;
  2111. else if (self->x >= mx && self->y < my) alpha = pi / 2;
  2112. else if (self->x < mx && self->y >= my) alpha = pi * 3 / 2;
  2113. else alpha = 0;
  2114. api.Move(50, alpha);
  2115. this_thread::sleep_for(chrono::milliseconds(48));
  2116. return;
  2117. }
  2118. }
  2119. priority3://以后可能要改下名字
  2120. // 听到的是尸体
  2121. //听不到 则前往最后看到的目标的10s内的最后地点 优先级为5 同优先级不替换
  2122. if (priority > 5) {
  2123. long long LstSeenTim = -1;
  2124. pair<int, int> LstSeenPos = make_pair(-1, -1);
  2125. for (int i = 0; i < 4; i++) if (playerstate[i] == 0)
  2126. {
  2127. if (LstSeenTim < lastSeen[i])
  2128. {
  2129. LstSeenTim = lastSeen[i];
  2130. LstSeenPos = lastLoc[i];
  2131. }
  2132. }
  2133. if (actualtime - LstSeenTim <= 10000) { // 我感觉没有时间限制比较好 , 在没有别的线索的情况下
  2134. TTSF.changeAddr(api, make_pair(LstSeenPos.first / 1000, LstSeenPos.second / 1000));
  2135. TTSF.BFS(make_pair(self->x / 1000, self->y / 1000), TTSF.adr, api);
  2136. priority = 5;
  2137. goto getsetgo;
  2138. }
  2139. }
  2140. //去找作业 优先级为6 同优先级不替换
  2141. if (priority > 7) {
  2142. double maxdis = 0;
  2143. pair<int, int>target = make_pair(-1, -1);
  2144. for (auto s : TTSF.cls) {
  2145. double dis = sqrt(1.0 * (api.CellToGrid(s.first) - self->x) * (api.CellToGrid(s.first) - self->x) + 1.0 * (api.CellToGrid(s.second) - self->y) * (api.CellToGrid(s.second) - self->y));
  2146. if (dis > maxdis) {
  2147. maxdis = dis;
  2148. target = s;
  2149. }
  2150. }
  2151. if (target.first != -1) {
  2152. TTSF.changeAddr(api, target);
  2153. TTSF.BFS(make_pair(self->x / 1000, self->y / 1000), TTSF.adr, api);
  2154. priority = 7;
  2155. goto getsetgo;
  2156. }
  2157. }
  2158. // 寻路
  2159. getsetgo://案批
  2160. if (priority <= 4) hearing = false; // 有目标则中断听
  2161. //输出TTSF.adr , TTSF.now , self ->x ,self->y
  2162. if (TTSF.checkStandableCell(TTSF.adr)) {
  2163. if (self->x / 1000 != TTSF.adr.first
  2164. || self->y / 1000 != TTSF.adr.second) {
  2165. if (abs(api.GetSelfInfo()->x - TTSF.now.first * 1000 - 500) < 20 &&
  2166. abs(api.GetSelfInfo()->y - TTSF.now.second * 1000 - 500) < 20)
  2167. TTSF.now = make_pair(-1, -1);
  2168. if (TTSF.now == make_pair(-1, -1))
  2169. {
  2170. if (TTSF.linecnt > 0 || TTSF.line.empty())
  2171. {
  2172. TTSF.BFS(make_pair(self->x / 1000, self->y / 1000), TTSF.adr, api);
  2173. TTSF.linecnt = 0;
  2174. if (TTSF.line.empty())
  2175. {
  2176. TTSF.now = make_pair(-1, -1);
  2177. return;
  2178. }
  2179. }
  2180. int check = -1;
  2181. //for (int i = tts.line.size() - 1; i >= 0 && check == -1; i--)
  2182. for (int i = 0; i < TTSF.line.size() && check == -1; i++)
  2183. //if (abs(tts.line[i].first - x) == abs(tts.line[i].second - y))
  2184. {
  2185. //pair<int, int>a = tts.line[i], b = make_pair(x, y);
  2186. //api.Print(to_string(a.first) + ' ' + to_string(a.second));
  2187. if (TTSF.haveWay(api.GetSelfInfo()->x, api.GetSelfInfo()->y,
  2188. 1000 * TTSF.line[i].first + 500,
  2189. 1000 * TTSF.line[i].second + 500))
  2190. check = i;
  2191. /*
  2192. if (a.second > b.second)swap(a, b);
  2193. if ((a.first < b.first ?
  2194. TTSF.crl[b.first][b.second] : TTSF.crr[b.first][b.second]) < a.second)
  2195. check = i;*/
  2196. }
  2197. TTSF.linecnt++;
  2198. //api.Print("CHECK!!! " + to_string(check));
  2199. //cout << "ERROR?" << ' ' << check << endl;
  2200. if (check != -1)
  2201. while (TTSF.line.size() > check + 1)TTSF.line.pop_back();
  2202. TTSF.now = TTSF.line.back();
  2203. TTSF.line.pop_back();
  2204. //else api.Move((i & 1 ? sqrt(2) : 1.0) * 1e6 / api.GetSelfInfo()->speed, acos(-1) * i / 4);
  2205. //cout << i << ' ' << api.GetSelfInfo()->speed << endl;
  2206. }
  2207. }
  2208. else {
  2209. TTSF.now = make_pair(-1, -1), priority = 0x3f3f3f3f;
  2210. }
  2211. }
  2212. else {
  2213. if (abs(api.GetSelfInfo()->x - TTSF.adr.first * 1000 - 500) +
  2214. abs(api.GetSelfInfo()->y - TTSF.adr.second * 1000 - 500) > 1100)
  2215. {
  2216. if (abs(api.GetSelfInfo()->x - TTSF.now.first * 1000 - 500) < 50 &&
  2217. abs(api.GetSelfInfo()->y - TTSF.now.second * 1000 - 500) < 50)
  2218. TTSF.now = make_pair(-1, -1);
  2219. if (TTSF.now == make_pair(-1, -1))
  2220. {
  2221. if (TTSF.linecnt > 0 || TTSF.line.empty())
  2222. {
  2223. TTSF.BFS(make_pair(self->x / 1000, self->y / 1000), TTSF.adr, api);
  2224. TTSF.linecnt = 0;
  2225. if (TTSF.line.empty())
  2226. {
  2227. TTSF.now = make_pair(-1, -1);
  2228. return;
  2229. }
  2230. }
  2231. int check = -1;
  2232. //for (int i = tts.line.size() - 1; i >= 0 && check == -1; i--)
  2233. for (int i = 0; i < TTSF.line.size() && check == -1; i++)
  2234. //if (abs(tts.line[i].first - x) == abs(tts.line[i].second - y))
  2235. {
  2236. //pair<int, int>a = tts.line[i], b = make_pair(x, y);
  2237. //api.Print(to_string(a.first) + ' ' + to_string(a.second));
  2238. if (TTSF.haveWay(api.GetSelfInfo()->x, api.GetSelfInfo()->y,
  2239. 1000 * TTSF.line[i].first + 500,
  2240. 1000 * TTSF.line[i].second + 500))
  2241. check = i;
  2242. /*
  2243. if (a.second > b.second)swap(a, b);
  2244. if ((a.first < b.first ?
  2245. TTSF.crl[b.first][b.second] : TTSF.crr[b.first][b.second]) < a.second)
  2246. check = i;*/
  2247. }
  2248. TTSF.linecnt++;
  2249. //api.Print("CHECK!!! " + to_string(check));
  2250. //cout << "ERROR?" << ' ' << check << endl;
  2251. if (check != -1)
  2252. while (TTSF.line.size() > check + 1)TTSF.line.pop_back();
  2253. TTSF.now = TTSF.line.back();
  2254. TTSF.line.pop_back();
  2255. //else api.Move((i & 1 ? sqrt(2) : 1.0) * 1e6 / api.GetSelfInfo()->speed, acos(-1) * i / 4);
  2256. //cout << i << ' ' << api.GetSelfInfo()->speed << endl;
  2257. }
  2258. }
  2259. else {
  2260. TTSF.now = make_pair(-1, -1), priority = 0x3f3f3f3f;
  2261. }
  2262. }
  2263. if (abs(api.GetSelfInfo()->x - TTSF.adr.first * 1000 - 500) +
  2264. abs(api.GetSelfInfo()->y - TTSF.adr.second * 1000 - 500) < 2000 && priority == 1) { //目标点在尸体, 被尸体卡了
  2265. TTSF.now = make_pair(-1, -1), priority = 0x3f3f3f3f;
  2266. }
  2267. if (TTSF.now != make_pair(-1, -1))
  2268. {
  2269. if (((abs(self->x / 1000 - TTSF.now.first) == 2 && abs(self->y / 1000 - TTSF.now.second) == 0) ||
  2270. (abs(self->x / 1000 - TTSF.now.first) == 0 && abs(self->y / 1000 - TTSF.now.second) == 2)) &&
  2271. TTSF.mp[(self->x / 1000 + TTSF.now.first) / 2][(self->y / 1000 + TTSF.now.second) / 2] == PlaceType::Window)
  2272. {
  2273. int t = 2000 * 1e3 / trickerspeedClimbing[api.GetSelfInfo()->trickerType];
  2274. api.EndAllAction();
  2275. api.SkipWindow();
  2276. TTSF.now = make_pair(-1, -1);
  2277. this_thread::sleep_for(chrono::milliseconds(t));
  2278. }
  2279. else if (abs(api.GetSelfInfo()->x - TTSF.now.first * 1000 - 500) > 20 ||
  2280. abs(api.GetSelfInfo()->y - TTSF.now.second * 1000 - 500) > 20)
  2281. {
  2282. int tx = TTSF.now.first * 1000 + 500 - api.GetSelfInfo()->x,
  2283. ty = TTSF.now.second * 1000 + 500 - api.GetSelfInfo()->y;
  2284. int t = min(200, (int)(sqrt(1.0 * tx * tx + 1.0 * ty * ty) * 1e3 / api.GetSelfInfo()->speed));
  2285. /*if (TTSF.lstgrid == make_pair(api.GetSelfInfo()->x / 1000,
  2286. api.GetSelfInfo()->y / 1000))
  2287. {
  2288. if (api.GetSelfInfo()->playerState != PlayerState::Stunned)
  2289. TTSF.lstgridcnt++;
  2290. }
  2291. else {
  2292. TTSF.lstgrid = make_pair(api.GetSelfInfo()->x / 1000,
  2293. api.GetSelfInfo()->y / 1000);
  2294. TTSF.lstgridcnt = 0;
  2295. }
  2296. if (TTSF.lstgridcnt > 10)
  2297. {
  2298. pair<int, int>to = TTSF.findRecent(api.GetSelfInfo()->x,
  2299. api.GetSelfInfo()->y);
  2300. tx = to.first * 1000 + 500 - api.GetSelfInfo()->x;
  2301. ty = to.second * 1000 + 500 - api.GetSelfInfo()->y;
  2302. api.Move(t = (int)(sqrt(tx * tx + ty * ty) * 1e3 / api.GetSelfInfo()->speed),
  2303. TTSF.lstdir = (ty > 0 ? acos(tx / sqrt(tx * tx + ty * ty)) :
  2304. 2 * acos(-1) - acos(tx / sqrt(tx * tx + ty * ty))));
  2305. TTSF.BFS(id, make_pair(x, y), TTSF.adr[id]);
  2306. TTSF.now = make_pair(-1, -1);
  2307. TTSF.lstgridcnt = 0;
  2308. }
  2309. else if (make_pair(api.GetSelfInfo()->x, api.GetSelfInfo()->y) == TTSF.lstpos
  2310. && api.GetSelfInfo()->playerState != PlayerState::Stunned)//添加按时间(非按次数)判定机制
  2311. {
  2312. api.Move(t = 50, fmod(TTSF.lstdir + acos(-1), 2 * acos(-1)));
  2313. TTSF.BFS(id, make_pair(x, y), TTSF.adr[id]);
  2314. TTSF.now = make_pair(-1, -1);
  2315. }
  2316. else*/
  2317. {
  2318. TTSF.lstpos = make_pair(api.GetSelfInfo()->x, api.GetSelfInfo()->y);
  2319. api.Move(t, TTSF.lstdir = atan2(ty, tx));
  2320. }
  2321. return;
  2322. }
  2323. else TTSF.now = make_pair(-1, -1);
  2324. }
  2325. }