Алгоритм выбора цели, выбор ближайщего монстра для атаки

Общие вопросы по OpenKore обсуждаются здесь. Можно сказать, что это - основной раздел форума.
Возник вопрос? Вам сюда.

Модератор: 4epT

Правила форума
Все вопросы по OK не касающиеся плагинов и макросов публикуются в этом разделе.
Перед тем как что то писать, пожалуйста, удостоверьтесь что данная тема не поднималась, вы полностью изучили мануалы по конфигурационным файлам бота и не нашли там решения.
Аватара пользователя
NyaNya
Начинающий
Сообщения: 22
Зарегистрирован: Пт июн 12, 2009 9:30 pm
Контактная информация:

Алгоритм выбора цели, выбор ближайщего монстра для атаки

Сообщение NyaNya »

Суть проблемы следующая, радиус обзора не регулируется ибо убрано из исходников
смотреть тут - viewtopic.php?f=8&t=7901
Радиус обзора на сервере очень большой, поэтому крайне необходимо чтобы бот выбирал для атаки монстра находящегося к нему ближе всего, уже довольно долго мучаю конфиг но добиться нормального поведения от бота так не смог :( . Буду признателен за любую информацию по этому поводу.

Код: Выделить всё

lockMap ein_fild04
attackAuto 1
attackAuto_party 1
attackAuto_onlyWhenSafe 1
attackAuto_followTarget 0
attackAuto_inLockOnly 1
attackAuto_notInTown 1
attackDistance 10
attackDistanceAuto 0
attackMinDistance 0
attackMaxDistance 10
attackMaxRouteDistance 5
attackMaxRouteTime 1
attackMinPlayerDistance 15
attackMinPortalDistance 4
attackUseWeapon 0
attackNoGiveup 0
attackCanSnipe 1
attackCheckLOS 1
attackLooters 0
attackChangeTarget 2
aggressiveAntiKS 0

Код: Выделить всё

route_escape_unknownMap 1
route_escape_reachedNoPortal 1
route_escape_randomWalk 1
route_escape_shout
route_randomWalk 0 << пробовал как при 1 так и при 0 толку не какова...
route_randomWalk_inTown 0
route_randomWalk_maxRouteTime 2
route_randomWalk_maxRouteDistance 15
route_maxWarpFee
route_maxNpcTries 5
route_teleport 0
route_teleport_minDistance 150
route_teleport_maxTries 8
route_teleport_notInMaps
route_step 15
route_avoidWalls 1

Код: Выделить всё

attackSkillSlot Fire Bolt {
	lvl 10
	MinDist 3
	MaxDist 10
	sp > 10%
	monsters Geographer, Yellow Plant
#Green Plant, Red Plant, Yellow Plant, Blue Plant, White Plant, Shining Plant
}
mon_control.txt

Код: Выделить всё

all 0 2 0
Geographer 2 2 0  <<тут также пробовал 1 2 0
Yellow Plant 2 0 0  << и тут 1 0 0  ну и естественно attackAuto при этом в 2 устанавливал...
Изображение
Аватара пользователя
wxBotowod
Грамотный
Сообщения: 228
Зарегистрирован: Пт ноя 07, 2008 4:13 pm
Сервер RO:: laggame
Контактная информация:

Re: Алгоритм выбора цели, выбор ближайщего монстра для атаки

Сообщение wxBotowod »

мне кажется нужно мучать attack.pm или corelogic.pm
Изображение
Аватара пользователя
kLabMouse
Профессионал
Сообщения: 4776
Зарегистрирован: Вс ноя 05, 2006 4:32 pm

Re: Алгоритм выбора цели, выбор ближайщего монстра для атаки

Сообщение kLabMouse »

NyaNya
По моему.. для АттакАуто есть несколько режимов.
В том числе, и выбор ближайшего моба.
Аватара пользователя
NyaNya
Начинающий
Сообщения: 22
Зарегистрирован: Пт июн 12, 2009 9:30 pm
Контактная информация:

Re: Алгоритм выбора цели, выбор ближайщего монстра для атаки

Сообщение NyaNya »

kLabMouse писал(а):NyaNya
По моему.. для АттакАуто есть несколько режимов.
В том числе, и выбор ближайшего моба.
По моему чтото такое когда то мелькало, но сейчас похоже все сходиться с мануалом а именно 3 режима...
файл corelogic.pm
функция sub processAutoAttack {

Код: Выделить всё

if (!AI::is(qw/sitAuto take items_gather items_take/)
				 && $config{'attackAuto'} >= 2 && !$ai_v{sitAuto_forcedBySitCommand}
				 && $attackOnRoute >= 2 && !$monster->{dmgFromYou} && $safe
				 && !positionNearPlayer($pos, $playerDist) && !positionNearPortal($pos, $portalDist)
				 && timeOut($monster->{attack_failed}, $timeout{ai_attack_unfail}{timeout})) {
					push @cleanMonsters, $_;
				}
1 - атака только в ответ, 2 агрессивно атаковать мобов.

От тудаже

Код: Выделить всё

if (!$attackTarget) {
				# No party monsters either; look for the closest, non-aggressive monster that:
				# 1) nobody's attacking
				# 2) has the highest priority

				undef $smallestDist;
				foreach (@cleanMonsters) {
					my $monster = $monsters{$_};
					next unless $monster;
					my $pos = calcPosition($monster);
					my $dist = distance($myPos, $pos);
					my $name = lc $monster->{name};

					if (!defined($smallestDist) || $priority{$name} > $highestPri
					  || ( $priority{$name} == $highestPri && $dist < $smallestDist )) {
						$smallestDist = $dist;
						$attackTarget = $_;
						$highestPri = $priority{$monster};
					}
				}
			}
На первый взгляд все правильно но почему тогда кор пытается идти через пол карты к дальнему гео?
При том что рандом валк отклчен.

Добавлено спустя 1 час 50 минут 33 секунды:
wxBotowod писал(а):мне кажется нужно мучать attack.pm или corelogic.pm
Помучал и вот что вышло
файл corelogic.pm
функция sub processAutoAttack

Код: Выделить всё

		### Step 1: Generate a list of all monsters that we are allowed to attack. ###
			my @aggressives;
			my @partyMonsters;
			my @cleanMonsters;

			# List aggressive monsters
			@aggressives = ai_getAggressives(1) if ($config{'attackAuto'} && $attackOnRoute);

			# There are two types of non-aggressive monsters. We generate two lists:
			foreach (@monstersID) {
				next if (!$_ || !checkMonsterCleanness($_));
				my $monster = $monsters{$_};
				# Ignore ignored monsters in mon_control.txt
				if (my $control = mon_control($monster->{name},$monster->{nameID})) {
					next if ( ($control->{attack_auto} ne "" && $control->{attack_auto} <= 0)
						|| ($control->{attack_lvl} ne "" && $control->{attack_lvl} > $char->{lv})
						|| ($control->{attack_jlvl} ne "" && $control->{attack_jlvl} > $char->{lv_job})
						|| ($control->{attack_hp}  ne "" && $control->{attack_hp} > $char->{hp})
						|| ($control->{attack_sp}  ne "" && $control->{attack_sp} > $char->{sp})
						|| ($control->{attack_auto} == 3 && ($monster->{dmgToYou} || $monster->{missedYou} || $monster->{dmgFromYou}))
						);
				}
				my $pos = calcPosition($monster);

############################################################################################
				# Ignore monsters with a distance greater than attack_MaxDistanceToBeginAttack.##########
############################################################################################
				if (distance(calcPosition($char), $pos) >= ($config{attack_MaxDistanceToBeginAttack} || 35)) {
				next;
				}
Добавленные строки

Код: Выделить всё

############################################################################################
				# Ignore monsters with a distance greater than attack_MaxDistanceToBeginAttack.##########
############################################################################################
				if (distance(calcPosition($char), $pos) >= ($config{attack_MaxDistanceToBeginAttack} || 35)) {
				next;
				}
Ну и в конфиге необходимо прописать

Код: Выделить всё

attack_MaxDistanceToBeginAttack 20
Кора не будет атаковать мобов находящихся на расстоянии больше чем указанно в attack_MaxDistanceToBeginAttack либо если значение не установлено 35.

Так бот работает гораздо лучше... и практически не ошибается.

Добавлено спустя 2 минуты:
Однако так и осталось загадкой почему не выберается ближайший моб
Последний раз редактировалось NyaNya Вт июн 30, 2009 11:36 am, всего редактировалось 1 раз.
Изображение
Аватара пользователя
BesT
Энтузиаст
Сообщения: 55
Зарегистрирован: Вс янв 21, 2007 4:46 am
Откуда: Киев
Контактная информация:

Re: Алгоритм выбора цели, выбор ближайщего монстра для атаки

Сообщение BesT »

Вот решения вашей проблемы!


Для етого вам нада в папке: "src" в файле: "Misc.pm" изменить:

Код: Выделить всё

if (!defined($highestPri) || ($priority{$name} > $highestPri)) {
                    $highestPri = $priority{$name};
                    $smallestDist = $dist;
                    $bestTarget = $_;
               }
               if ((!defined($highestPri) || $priority{$name} == $highestPri)
                 && (!defined($smallestDist) || $dist < $smallestDist)) {
                    $highestPri = $priority{$name};
                    $smallestDist = $dist;
                    $bestTarget = $_;
               }
Их несколько, и нада их все изменять.

Находиится в блоке: "sub getBestTarget"

поменять на ето:

Код: Выделить всё

if (!defined($smallestDist) || $dist < $smallestDist) {
                        $smallestDist = $dist;
                        $bestTarget = $_;
                   }

У меня перебоев нет, цель выберется ближнея...

Добавлено спустя 4 минуты 49 секунд:
Посте изменений блок выглядит так:

Код: Выделить всё

sub getBestTarget {
        my ($possibleTargets, $nonLOSNotAllowed) = @_;
        if (!$possibleTargets) {
                return;
        }

        my $portalDist = $config{'attackMinPortalDistance'} || 4;
        my $playerDist = $config{'attackMinPlayerDistance'} || 1;

        my @noLOSMonsters;
        my $myPos = calcPosition($char);
        my ($highestPri, $smallestDist, $bestTarget);

        # First of all we check monsters in LOS, then the rest of monsters

        foreach (@{$possibleTargets}) {
                my $monster = $monsters{$_};
                my $pos = calcPosition($monster);
                next if (positionNearPlayer($pos, $playerDist)
                        || positionNearPortal($pos, $portalDist)
                );
                if ((my $control = mon_control($monster->{name},$monster->{nameID}))) {
                        next if ( ($control->{attack_auto} == -1)
                                || ($control->{attack_lvl} ne "" && $control->{attack_lvl} > $char->{lv})
                                || ($control->{attack_jlvl} ne "" && $control->{attack_jlvl} > $char->{lv_job})
                                || ($control->{attack_hp}  ne "" && $control->{attack_hp} > $char->{hp})
                                || ($control->{attack_sp}  ne "" && $control->{attack_sp} > $char->{sp})
                                || ($control->{attack_auto} == 3 && ($monster->{dmgToYou} || $monster->{missedYou} || $monster->{dmgFromYou}))
                                || ($control->{attack_auto} == 0 && !($monster->{dmgToYou} || $monster->{missedYou}))
                        );
                }
                if ($config{'attackCanSnipe'}) {
                        if (!checkLineSnipable($myPos, $pos)) {
                                push(@noLOSMonsters, $_);
                                next;
                        }
                } else {
                        if (!checkLineWalkable($myPos, $pos)) {
                                push(@noLOSMonsters, $_);
                                next;
                        }
                }
                my $name = lc $monster->{name};
                my $dist = round(distance($myPos, $pos));
                
                # COMMENTED (FIX THIS): attackMaxDistance should never be used as indication of LOS
                #     The objective of attackMaxDistance is to determine the range of normal attack,
                #     and not the range of character's ability to engage monsters
                ## Monsters that aren't in attackMaxDistance are not checked up
                ##if ($nonLOSNotAllowed && ($config{'attackMaxDistance'} < $dist)) {
                ##      next;
                ##}
                if (!defined($smallestDist) || $dist < $smallestDist) {
                        $smallestDist = $dist;
                        $bestTarget = $_;
                }

        }
        if (!$nonLOSNotAllowed && !$bestTarget && scalar(@noLOSMonsters) > 0) {
                foreach (@noLOSMonsters) {
                        # The most optimal solution is to include the path lenghts' comparison, however it will take
                        # more time and CPU resources, so, we use rough solution with priority and distance comparison

                        my $monster = $monsters{$_};
                        my $pos = calcPosition($monster);
                        my $name = lc $monster->{name};
                        my $dist = round(distance($myPos, $pos));
                        if (!defined($highestPri) || ($priority{$name} > $highestPri)) {
                                $highestPri = $priority{$name};
                                $smallestDist = $dist;
                                $bestTarget = $_;
                        }
                        if ((!defined($highestPri) || $priority{$name} == $highestPri)
                          && (!defined($smallestDist) || $dist < $smallestDist)) {
                                $highestPri = $priority{$name};
                                $smallestDist = $dist;
                                $bestTarget = $_;
                        }
                }
        }
        return $bestTarget;
}
P.S. Простите за мой руский. Я украинец который питается писать по русски! (незная руского)
Аватара пользователя
NyaNya
Начинающий
Сообщения: 22
Зарегистрирован: Пт июн 12, 2009 9:30 pm
Контактная информация:

Re: Алгоритм выбора цели, выбор ближайщего монстра для атаки

Сообщение NyaNya »

Благодарю всех кто откликнулся на мой вопрос)
и спасибо за ответ BesT)) хотя он не решает мою проблему ,почему напишу ниже, но заставил меня еще покопаться в исходниках и похоже таки разобраться с этой мерзостью).

А не помогло потому что у нас видимо довольно сильно разные версии бота так как в моей все что касается выбора цели для атаки вынесено в файл srcAICoreLogic.pm
И так собственно решение
в файле srcAICoreLogic.pm необходимо нати следующий код в функции sub processAutoAttack

Код: Выделить всё

if (!$attackTarget) {
				# No party monsters either; look for the closest, non-aggressive monster that:
				# 1) nobody's attacking
				# 2) has the highest priority

				undef $smallestDist;
				foreach (@cleanMonsters) {
					my $monster = $monsters{$_};
					next unless $monster;
					my $pos = calcPosition($monster);
					my $dist = distance($myPos, $pos);
					my $name = lc $monster->{name};

					if (!defined($smallestDist) || $priority{$name} > $highestPri
					  || ( $priority{$name} == $highestPri && $dist < $smallestDist )) {
						$smallestDist = $dist;
						$attackTarget = $_;
						$highestPri = $priority{$monster};
					}
				}
			}
И заменить его на

Код: Выделить всё

if (!$attackTarget) {
				# No party monsters either; look for the closest, non-aggressive monster that:
				# 1) nobody's attacking
				# 2) has the highest priority

				undef $smallestDist;
				foreach (@cleanMonsters) {
					my $monster = $monsters{$_};
					next unless $monster;
					my $pos = calcPosition($monster);
					my $dist = distance($myPos, $pos);
					
					if ((!defined($smallestDist)) 
					  || ($priority{$monster} > $highestPri) 
                                          || (($priority{$monster} == $highestPri) && ($dist < $smallestDist))) {
						$smallestDist = $dist;
						$attackTarget = $_;
						$highestPri = $priority{$monster};
					}
				}
			}
Фактически удаляем строчку my $name = lc $monster->{name};
и вместо $priority{$name} вписываем $priority{$monster};
В перле я особо не разбираюсь но без данных изменений бот часто пропускает моба находящего буквально возле него и идет к дальнему...
Еще мне непонятно какой у моба будет приоритет если он не описан в priority.txt ?

Прикрепил к сообщению архив с отредактированным файлом.

П.С.
то BesT Земляк :wink:

Добавлено спустя 7 часов 28 минут 22 секунды:
Кстате... может боян, но логичнее было бы если бы бот выбирал для атаки не самого ближнего к нему моба, а моба до которого самый короткий маршрут, может кто нибудь подскажет есть ли функция для вычисления длинны маршрута?
Фактически такаяже проверка, только, вместо расчета дистанца будет рассчитываться дистанс маршрута...
Вложения
CoreLogic.zip
Исправленный CoreLogic.pm
(25.35 КБ) 123 скачивания
Изображение
Аватара пользователя
kLabMouse
Профессионал
Сообщения: 4776
Зарегистрирован: Вс ноя 05, 2006 4:32 pm

Re: Алгоритм выбора цели, выбор ближайщего монстра для атаки

Сообщение kLabMouse »

NyaNya писал(а):Добавлено спустя 7 часов 28 минут 22 секунды:
Кстате... может боян, но логичнее было бы если бы бот выбирал для атаки не самого ближнего к нему моба, а моба до которого самый короткий маршрут, может кто нибудь подскажет есть ли функция для вычисления длинны маршрута?
Фактически такаяже проверка, только, вместо расчета дистанца будет рассчитываться дистанс маршрута...
Вариант тяжёлый.
По умолчанию, в коре нет оптимизации/кеширования результатов алгоритма А*.
Аватара пользователя
NyaNya
Начинающий
Сообщения: 22
Зарегистрирован: Пт июн 12, 2009 9:30 pm
Контактная информация:

Re: Алгоритм выбора цели, выбор ближайщего монстра для атаки

Сообщение NyaNya »

тяжелый но интересно на сколько, в принципе перед атакой просчитывать скажем 10 коротких роутов и 2 длинные, к тому же сделать расчет с отсечением, тоесть скажем функция расчет_растояния_маршрута(координат чара, координаты моба, тек минимальное растояние)
если чилсо блоков привышает тек минимальное растояние то скажем возвращаем егоже +1; или там код -1. Както так...

Добавлено спустя 26 минут 54 секунды:
По идее есть еще такая опция - attackMaxRouteDistance
Если эта опция указана, Кора не будет идти дальше чем указанное число клеток чтобы атаковать цель. Это используется для того чтоб избежать обхода длинных стен/склонов чтоб атаковать цель.
Но нашлась она в странных местах... к томуже создается чувство что кора ее игнорит...
в Network\Receive.pm
в функции sub skill_cast

Код: Выделить всё

			my (%vec, %pos);
			getVector(\%vec, \%coords, $char->{pos_to});
			moveAlongVector(\%pos, $char->{pos_to}, \%vec, distance($char->{pos_to}, \%coords));
			ai_route($field{name}, $pos{x}, $pos{y},
				maxRouteDistance => $config{attackMaxRouteDistance},
				maxRouteTime => $config{attackMaxRouteTime},
				noMapRoute => 1);
			message TF("Avoid casting Skill - switch position to : %s,%s\n", $pos{x}, $pos{y}), 1;
		}
И в коре лоджике в проверке на подъем лута...
Изображение
Аватара пользователя
kLabMouse
Профессионал
Сообщения: 4776
Зарегистрирован: Вс ноя 05, 2006 4:32 pm

Re: Алгоритм выбора цели, выбор ближайщего монстра для атаки

Сообщение kLabMouse »

МММ.. диффни.
Аватара пользователя
kLabMouse
Профессионал
Сообщения: 4776
Зарегистрирован: Вс ноя 05, 2006 4:32 pm

Re: Алгоритм выбора цели, выбор ближайщего монстра для атаки

Сообщение kLabMouse »

Бля. Лучше бы разницу между твоим и тем который в СВНке.
Ответить