Beispiel #1
0
        //Створює юніта і задає йому шлях для руху
        public void SendUnit(BasicCity to)
        {
            ushort sendWarriors = GetAtkWarriorsWithoutAtk();

            if (sendWarriors == 0 || to == this)
            {
                return;
            }

            currWarriors -= sendWarriors;
            sendWarriors  = (ushort)Math.Round(sendWarriors * atkPersent);

            BasicUnit unit = CreateLinkedUnit(sendWarriors, to);

            if (unit != null)
            {
                UnitSend?.Invoke(new CityUnitsEvent(basicCityEvent, unit));
                gameMap.Units.Add(unit);
            }
        }
Beispiel #2
0
        //Створює юнита, якого посилатиме це місто
        public virtual BasicUnit CreateLinkedUnit(ushort sendWarriors, BasicCity to)
        {
            var path = BuildOptimalPath(to, out BasicCity realDest);

            return(new BasicUnit(sendWarriors, this.PlayerId, path, realDest, to));
        }
Beispiel #3
0
        //Повертає шлях до міста. є 2 типи шляхів
        //1) Шлях в обхід всіх ворожих міст
        //2) Шлях напролом. Створюється якщо не існує шляху1.
        public List <KeyValuePair <int, int> > BuildOptimalPath(BasicCity to, out BasicCity realDestination)
        {
            realDestination = to;
            if (to == null)
            {
                return(null);
            }

            if (hashedPath.ContainsKey(to))
            {
                return(hashedPath[to]);
            }

            int minFindValue = int.MaxValue;

            PathFinderCell[,] finder = new PathFinderCell[gameMap.Map.Count, gameMap.Map[0].Count];
            List <KeyValuePair <int, int> > reversedPath = new List <KeyValuePair <int, int> >();

            for (int i = 0; i < finder.GetLength(0); ++i)
            {
                for (int j = 0; j < finder.GetLength(1); ++j)
                {
                    finder[i, j] = new PathFinderCell(gameMap.Map[i][j]);
                }
            }

            bool isUnoptimal = false;

UNOPTIMAL_PATH_FINDER:

            var recQueue = new Queue <RecInfo>();

            recQueue.Enqueue(new RecInfo()
            {
                x = X, y = Y, value = 0
            });
            while (recQueue.Count != 0)
            {
                if (!isUnoptimal)
                {
                    RecAvoidEnemyCities(recQueue.Dequeue());
                }
                else
                {
                    RecThroughEnemyCities(recQueue.Dequeue());
                }
            }

            BuildBackPath(to.X, to.Y, finder[to.Y, to.X].num);
            reversedPath.Reverse();

            if (reversedPath.Count == 0 && realDestination == to)
            {
                recQueue.Clear();
                for (int i = 0; i < finder.GetLength(0); ++i)
                {
                    for (int j = 0; j < finder.GetLength(1); ++j)
                    {
                        finder[i, j].num = -1;
                    }
                }
                isUnoptimal = true;
                goto UNOPTIMAL_PATH_FINDER;
            }

            //Якщо послали в місто куди нема прямого шляху, то встановить новий Destination. Гравцю шо з цим методом, шо без нього, все одно нічого не помітно.
            //Але крепко воно діє на бота. Бот бачить що його рашать, і пробує щось робити, а ворог навіть не дійшов)
            if (reversedPath.Count != 0 && isUnoptimal)
            {
                for (int i = 0; i < reversedPath.Count - 1; ++i)
                {
                    if (gameMap.Map[reversedPath[i].Value][reversedPath[i].Key].City != null &&
                        gameMap.Map[reversedPath[i].Value][reversedPath[i].Key].City.PlayerId != this.PlayerId)
                    {
                        realDestination = gameMap.Map[reversedPath[i].Value][reversedPath[i].Key].City;
                        reversedPath.RemoveRange(i + 1, reversedPath.Count - i - 1);
                        break;
                    }
                }
            }


            //------------------------------- Inner methods ---------------------------------------
            //Пошук шляху в обхід ворога
            void RecAvoidEnemyCities(RecInfo info)
            {
                int x = info.x, y = info.y;

                if ((finder[y, x].num != -1 && finder[y, x].num <= info.value) ||
                    (info.value >= minFindValue) ||
                    (
                        gameMap.Map[y][x].City != null && gameMap.Map[y][x].City.PlayerId != this.PlayerId &&
                        (x != to.X || y != to.Y)
                    )
                    )
                {
                    return;
                }

                if (x == to.X && y == to.Y)
                {
                    minFindValue = info.value;
                }

                finder[y, x].num = info.value++;

                if (x != to.X || y != to.Y)
                {
                    AddNearbyToRecList(x, y, info.value);
                }
            }

            //Пошук шляху напролом
            void RecThroughEnemyCities(RecInfo info)
            {
                if ((finder[info.y, info.x].num != -1 && finder[info.y, info.x].num <= info.value) ||
                    (info.value >= minFindValue)
                    )
                {
                    return;
                }

                if (info.x == to.X && info.y == to.Y)
                {
                    minFindValue = info.value;
                }

                finder[info.y, info.x].num = info.value++;

                if (info.x != to.X || info.y != to.Y)
                {
                    AddNearbyToRecList(info.x, info.y, info.value);
                }
            }

            //Дадає клетки в ліст для наступного пошуку
            void AddNearbyToRecList(int x, int y, int val)
            {
                if (finder[y, x].IsOpenBottom)
                {
                    recQueue.Enqueue(new RecInfo()
                    {
                        x = x, y = y + 1, value = val
                    });
                }
                if (finder[y, x].IsOpenRight)
                {
                    recQueue.Enqueue(new RecInfo()
                    {
                        x = x + 1, y = y, value = val
                    });
                }
                if (finder[y, x].IsOpenTop)
                {
                    recQueue.Enqueue(new RecInfo()
                    {
                        x = x, y = y - 1, value = val
                    });
                }
                if (finder[y, x].IsOpenLeft)
                {
                    recQueue.Enqueue(new RecInfo()
                    {
                        x = x - 1, y = y, value = val
                    });
                }
            }

            //Будує сам шлях від міста до міста
            bool BuildBackPath(int x, int y, int prevValue)
            {
                if (prevValue == finder[y, x].num && finder[y, x].num != -1)
                {
                    reversedPath.Add(new KeyValuePair <int, int>(x, y));

                    List <KeyValuePair <int, int> > nextPathElement = new List <KeyValuePair <int, int> >(4);
                    if (finder[y, x].IsOpenBottom)
                    {
                        nextPathElement.Add(new KeyValuePair <int, int>(x, y + 1));
                    }
                    if (finder[y, x].IsOpenTop)
                    {
                        nextPathElement.Add(new KeyValuePair <int, int>(x, y - 1));
                    }
                    if (finder[y, x].IsOpenLeft)
                    {
                        nextPathElement.Add(new KeyValuePair <int, int>(x - 1, y));
                    }
                    if (finder[y, x].IsOpenRight)
                    {
                        nextPathElement.Add(new KeyValuePair <int, int>(x + 1, y));
                    }

                    while (nextPathElement.Count != 0)
                    {
                        int rPos = Rand.Next(0, nextPathElement.Count);
                        if (BuildBackPath(nextPathElement[rPos].Key, nextPathElement[rPos].Value, prevValue - 1))
                        {
                            break;
                        }
                        nextPathElement.RemoveAt(rPos);
                    }

                    return(true);
                }
                return(false);
            }

            //------------------------------- END of Inner methods ---------------------------------------

            if (reversedPath.Count != 0)
            {
                if (!hashedPath.ContainsKey(to))
                {
                    hashedPath.Add(to, new List <KeyValuePair <int, int> >(reversedPath));
                }
                return(reversedPath);
            }
            return(null);
        }
Beispiel #4
0
        public void ResendUnit(BasicCity to, BasicUnit unit)
        {
            var path = BuildOptimalPath(to, out BasicCity realDest);

            unit.SetPath(path, realDest, to);
        }