/// <summary> создается поле, и забиваются расположения стен и всего остального /// </summary> internal Radar(Mind mind,IAPI api) { map = new Map (api.getMinX(),api.getMinY(), api.getMaxX()+1,api.getMaxY()+1); // создается поле для сканирования this.mind = mind; // добавляются ссылки для обратного вызова this.api = api; recycleSectors = new Queue<MapSector>(); ICoordinates xy = StepsAndCoord.Coordinates ( api.getMinX (),api.getMinY () ); for (int i = api.getMinX (); i <= api.getMaxX (); i++) { // проход по карте построчно for (int j = api.getMinY (); j <= api.getMaxY (); j++) { StepsAndCoord.otherPositionOfThis ( xy,i,j ); if (api.isNorm(xy)) { map[i, j] = new MapSector(); if (api.getTypeOfField(xy) == TypesOfField.WALL) { map[i, j].type = TypesOfField.WALL; map[i,j].xy = StepsAndCoord.Coordinates ( i,j ); } else { map[i,j].xy = StepsAndCoord.Coordinates ( i,j ); map[i,j].type = api.getTypeOfField ( xy ); } } } } xFunct (); }
/// <summary>/// Конструктор /// </summary> internal Radar(Mind mind,IAPI api) { map = new MapSector[api.getMaxX()+1,api.getMaxY()+1]; // создается поле для сканирования map.Initialize (); this.mind = mind; this.api = api; recycleSectors = new Queue<MapSector>(); ICoordinates xy = Helper.Coordinates ( api.getMinX (),api.getMinY () ); for (int i = api.getMinX (); i <= api.getMaxX (); i++) { for (int j = api.getMinY (); j <= api.getMaxY (); j++) { Helper.otherPositionOfThis ( xy,i,j ); if (api.isNorm(xy)) { map[i, j] = new MapSector(xy, xy, 0); if (api.getTypeOfField(xy) == TypesOfField.WALL) { map[i, j].type = TypesOfField.WALL; } else { map[i, j].type = TypesOfField.NOTHING; } } } } }
/// <summary> ////получить всех соседей данной вершины /// </summary> /// <returns></returns> internal List<ICoordinates> getAllUsableSectors(MapSector s,Queue<ICoordinates> q) { List<ICoordinates> list = new List<ICoordinates> (); // в которые можно пройти кроме родительской this.getUsableSector ( s.xy.getX () + 1,s.xy.getY () + 0,list ); this.getUsableSector ( s.xy.getX () - 1,s.xy.getY () - 0,list ); this.getUsableSector ( s.xy.getX () + 0,s.xy.getY () + 1,list ); this.getUsableSector ( s.xy.getX () - 0,s.xy.getY () - 1,list ); for (int i = 0; i < list.Count; i++) { q.Enqueue ( list[i] ); } return list; }
//----------------------------------------------- /// <summary> /// Вычисление предположительного местоположения Противника относительно предыдущих координат /// </summary> private void whereHe(MapSector sector,TypesOfField btype,TypesOfField type) { if (!mind.He.WasFound) { //int a = 1; //int b = 0; //for (int i = 1; i <= 4; i++) { // mayBeHere ( sector.xy.getX () + a,sector.xy.getY () + b,mind.hisMayBeXY,sector ); // if (i == 1 || i==3) { // a = -a; // b = -b; // } // if (i == 2) { // b = -a; // a = 0; // } //} mayBeHere ( sector.xy.getX () + 1,sector.xy.getY (),mind.hisMayBeXY,sector ); mayBeHere ( sector.xy.getX () - 1,sector.xy.getY (),mind.hisMayBeXY,sector ); mayBeHere ( sector.xy.getX (),sector.xy.getY () - 1,mind.hisMayBeXY,sector ); mayBeHere ( sector.xy.getX (),sector.xy.getY () + 1,mind.hisMayBeXY,sector ); } }
//----------------------------------------------- /// <summary> /// выделение указателей на вершины графа определенного типа в соответсвующую базу /// </summary> private void simpleAddBase(MapSector sector,TypesOfField btypes,TypesOfField types) { if (types == TypesOfField.MEDKIT){ // то просто добавить в базу mind.healthXY.AddFirst(sector); } if (types == TypesOfField.BONUS){ mind.moneyXY.AddFirst ( sector ); } if (types == TypesOfField.HI){ if (!mind.hisMayBeXY.Contains ( sector )) { mind.hisMayBeXY.AddFirst ( sector ); } } }
//----------------------------------------------- /// <summary> /// Анализ изменений содержимого сектора карты /// </summary> private void sectorAnalysis(MapSector sector,TypesOfField btype,TypesOfField type) { if (btype == TypesOfField.HI) { // если до этого там был противник то вычисляем куда он направился whereHe ( sector,btype,type ); simpleAddBase ( sector,btype,type ); // и перебиваем базу } if (btype == TypesOfField.NOTHING) { // если до этого небыло ничего simpleAddBase ( sector,btype,type ); // просто перебиваем базу } if (btype == TypesOfField.MEDKIT || btype == TypesOfField.BONUS) { // была аптечка или бонус if (type == TypesOfField.NOTHING) { // а теперь пусто то он там //if (api.isVisible ( api.getCoordOfMe (),sector.xy/*api.getCoordOfEnemy ()*/ )) { mayBeHere ( sector.xy.getX (),sector.xy.getY (),mind.hisMayBeXY,sector ); if (btype == TypesOfField.MEDKIT) { mind.He.Health += Mind.cHealthM; mind.He.WasFound = true; } if (btype == TypesOfField.BONUS) { mind.He.Money += Mind.cMoneyM; mind.He.WasFound = true; } if (mind.He.WasFound) { mind.hisMayBeXY.Clear (); mind.hisMayBeXY.AddFirst ( sector ); mind.He.XY = sector.xy; } if (btype == TypesOfField.ME) { // а теперь он знает где я mind.I.WasFound = true; } //} } } }
//----------------------------------------------- /// <summary> /// пердсказание координат противника (вспомогательная ф- ия для whereHe()) /// </summary> private void mayBeHere(int x,int y,LinkedList<MapSector> hisMayBeXY,MapSector sector) { ICoordinates xy=Helper.Coordinates(x,y); if (EpsilonBot.api.isNorm(xy)){ // если внутри поля TypesOfField type = api.getTypeOfField ( xy ); if ( type != TypesOfField.WALL){ // если не стена if (!mind.He.WasFound) { // если не найден if (type == TypesOfField.HI){ // если нашл то в базу заносим 1 значение - точные координаты hisMayBeXY.Clear(); hisMayBeXY.AddFirst(sector); mind.He.WasFound = true; } if (!mind.He.WasFound && type == TypesOfField.NOTHING && !api.isVisible ()) { hisMayBeXY.AddFirst ( sector );// если пустая клетка, и его не видно то он может быть там } } } } }
//----------------------------------------------- /// <summary> /// сканирование карты с просчетом минимального пути до каждой вершины из расположения бота /// </summary> internal void scaning( ) { int distance = 1; Queue<MapSector> queue = new Queue<MapSector> (); MapSector temp = new MapSector ( api.getCoordOfMe (),api.getCoordOfMe (),distance ); queue.Enqueue (temp); int levelCount = 1; // кол-во вершин на данной волне int nextLevelCount = 0; // на след волне while ( queue.Count>0 ) { while ( levelCount>0 ) { temp = queue.Dequeue (); // достали вершину из очереди, пора узнать что в ней изменилось if (api.isNorm(temp.xy)) { this.mapSectorReLoad(temp); // анализ изменений в ячейке queue.Concat ( temp.getAllUsableSectors ( distance,ref nextLevelCount ) ); //всех соседей данной вершины графа levelCount--; // добавили в имеющуюся очередь // обновили информацию о вершине recycleSectors.Enqueue(temp); } } levelCount = nextLevelCount; nextLevelCount = 0; distance++; // удаленность волны } }
//----------------------------------------------- /// <summary> /// анализ измений значений вершин /// </summary> internal void mapSectorReLoad(MapSector sector) { TypesOfField type = api.getTypeOfField ( sector.xy ); TypesOfField btype = Radar.getSectorsType ( sector.xy ); if (btype != type) { // если тип поля изменился if (type == TypesOfField.HI){// он mayBeHere ( sector.xy.getX (),sector.xy.getY (),mind.hisMayBeXY,sector ); // обновить его координаты }else{ // если что нибудь другое this.sectorAnalysis ( sector,btype,type ); // анализируем прошлое значение } sector.type = api.getTypeOfField ( sector.xy ); // изменяем значения на новые на таблице } }
/// <summary>добавляет клетку поля для дальнейшей обработки при проходе карты в глубь - в ширь /// </summary> private void getUsableSector(int x,int y,Queue<MapSector> result,int len,ref int nextLevelCount) { ICoordinates temp = Helper.Coordinates ( x,y ); if (EpsilonBot.api.isNorm ( temp )) { // если внутри поля if ((EpsilonBot.api.getTypeOfField ( temp ) != TypesOfField.WALL) && Radar.usableSector ( temp )) { // если можно ходить MapSector f = new MapSector ( this.xy,temp,len ); // сама вершина станиовится мамой // и вершина не была посещена result.Enqueue ( f ); // помещаем в очередь для дальнейшей обработки nextLevelCount ++; } } }
//----------------------------------------------- /// <summary> /// выделение указателей на вершины графа определенного типа в соответсвующую базу /// </summary> private void simpleAddBase(MapSector sector,TypesOfField types) { if (types == TypesOfField.MEDKIT){ // то просто добавить в базу mind.healthXY.Add(sector); } if (types == TypesOfField.BONUS){ mind.moneyXY.Add ( sector ); } if (types == TypesOfField.HI){ mayBeHere ( sector.xy, mind.hisMayBeXY ); } }
//----------------------------------------------- /// <summary> /// Анализ изменений содержимого сектора карты /// </summary> private void sectorAnalysis(ICoordinates xy,TypesOfField btype,TypesOfField type,int distance) { // если до этого там был противник, а теперь исчез, то вычисляем куда он направился if (btype == TypesOfField.HI) { whereHe ( xy,btype,type ); } if (btype == TypesOfField.MEDKIT || btype == TypesOfField.BONUS) { // была аптечка или бонус if (type == TypesOfField.NOTHING) { // а теперь пусто то он там // mayBeHere ( xy,mind.hisMayBeXY ); if (btype == TypesOfField.MEDKIT) { mind.He.Health += Mind.cHealthM; mind.He.WasFound = true; } if (btype == TypesOfField.BONUS) { mind.He.Money += Mind.cMoneyM; mind.He.WasFound = true; } if (mind.He.WasFound) { heDetected ( xy ); } if (btype == TypesOfField.ME) { // а теперь он знает где я mind.I.WasFound = true; } //} } } if (btype==TypesOfField.NOTHING){ MapSector m = new MapSector (); m.usableForWave = true; m.type = type; m.xy.Copy ( xy ); } }