Artificial intelligence 这个人工智能我做错了什么?

Artificial intelligence 这个人工智能我做错了什么?,artificial-intelligence,Artificial Intelligence,我正在为我正在制作的一个棋盘游戏创建一个非常幼稚的AI(它甚至不应该被称为AI,因为它只是测试了很多可能性并为他挑选了最好的一个)。这是为了简化我需要进行的手动测试,以平衡游戏 AI独自玩,做以下事情:在每个回合中,AI与一个英雄玩,攻击战场上最多9个怪物中的一个。他的目标是以尽可能快的速度(最少的回合数)和最少的怪物激活完成战斗 为了实现这一点,我为人工智能实现了一个超前思考算法,在这个算法中,他不是在此刻执行尽可能最好的移动,而是根据其他英雄未来移动的可能结果选择一个移动。这是他用PHP编写

我正在为我正在制作的一个棋盘游戏创建一个非常幼稚的AI(它甚至不应该被称为AI,因为它只是测试了很多可能性并为他挑选了最好的一个)。这是为了简化我需要进行的手动测试,以平衡游戏

AI独自玩,做以下事情:在每个回合中,AI与一个英雄玩,攻击战场上最多9个怪物中的一个。他的目标是以尽可能快的速度(最少的回合数)和最少的怪物激活完成战斗

为了实现这一点,我为人工智能实现了一个超前思考算法,在这个算法中,他不是在此刻执行尽可能最好的移动,而是根据其他英雄未来移动的可能结果选择一个移动。这是他用PHP编写的代码片段:

/** Perform think ahead moves
 *
 * @params int         $thinkAheadLeft      (the number of think ahead moves left)
 * @params int         $innerIterator       (the iterator for the move)
 * @params array       $performedMoves      (the moves performed so far)
 * @param  Battlefield $originalBattlefield (the previous state of the Battlefield)
 */
public function performThinkAheadMoves($thinkAheadLeft, $innerIterator, $performedMoves, $originalBattlefield, $tabs) {
    if ($thinkAheadLeft == 0) return $this->quantify($originalBattlefield);

    $nextThinkAhead = $thinkAheadLeft-1;
    $moves = $this->getPossibleHeroMoves($innerIterator, $performedMoves);
    $Hero = $this->getHero($innerIterator);
    $innerIterator++;
    $nextInnerIterator = $innerIterator;
    foreach ($moves as $moveid => $move) {
        $performedUpFar = $performedMoves;
        $performedUpFar[] = $move;
        $attack = $Hero->getAttack($move['attackid']);
        $monsters = array();
        foreach ($move['targets'] as $monsterid) $monsters[] = $originalBattlefield->getMonster($monsterid)->getName();
        if (self::$debug) echo $tabs . "Testing sub move of " . $Hero->Name. ": $moveid of " . count($moves) . "  (Think Ahead: $thinkAheadLeft | InnerIterator: $innerIterator)\n";

        $moves[$moveid]['battlefield']['after']->performMove($move);

        if (!$moves[$moveid]['battlefield']['after']->isBattleFinished()) {
            if ($innerIterator == count($this->Heroes)) {
                $moves[$moveid]['battlefield']['after']->performCleanup();
                $nextInnerIterator = 0;
            }
            $moves[$moveid]['quantify'] = $moves[$moveid]['battlefield']['after']->performThinkAheadMoves($nextThinkAhead, $nextInnerIterator, $performedUpFar, $originalBattlefield, $tabs."\t", $numberOfCombinations);
        } else $moves[$moveid]['quantify'] = $moves[$moveid]['battlefield']['after']->quantify($originalBattlefield);
    }

    usort($moves, function($a, $b) {
        if ($a['quantify'] === $b['quantify']) return 0;
        else return ($a['quantify'] > $b['quantify']) ? -1 : 1;
    });

    return $moves[0]['quantify'];
}
它的作用是递归地检查未来的移动,直到达到
$thinkAheadleft
值,或者直到找到解决方案(即,所有怪物都被打败)。当它到达退出参数时,它计算战场的状态,与
$originalBattlefield
(第一次移动前的战场状态)相比。计算方法如下:

 /** Quantify the current state of the battlefield
 *
 * @param Battlefield $originalBattlefield (the original battlefield)
 *
 * returns int (returns an integer with the battlefield quantification)
 */
public function quantify(Battlefield $originalBattlefield) {

    $points = 0;
    foreach ($originalBattlefield->Monsters as $originalMonsterId => $OriginalMonster) {
        $CurrentMonster = $this->getMonster($originalMonsterId);

        $monsterActivated = $CurrentMonster->getActivations() - $OriginalMonster->getActivations();
        $points+=$monsterActivated*($this->quantifications['activations'] + $this->quantifications['activationsPenalty']);

        if ($CurrentMonster->isDead()) $points+=$this->quantifications['monsterKilled']*$CurrentMonster->Priority;
        else {
            $enragePenalty = floor($this->quantifications['activations'] * (($CurrentMonster->Enrage['max'] - $CurrentMonster->Enrage['left'])/$CurrentMonster->Enrage['max']));

            $points+=($OriginalMonster->Health['left'] - $CurrentMonster->Health['left']) * $this->quantifications['health'];
            $points+=(($CurrentMonster->Enrage['max'] - $CurrentMonster->Enrage['left']))*$enragePenalty;
        }
    }

    return $points;
}
当量化一些事物时,一些净正点,一些净负点指向状态。AI所做的是,他不使用当前移动后计算的点数来决定采取哪种移动,而是使用在提前思考部分后计算的点数,并根据其他英雄的可能移动选择移动

基本上,人工智能所做的,就是说现在攻击怪物1并不是最好的选择,但是如果其他英雄会这样做,从长远来看,这将是最好的结果

选择一个移动后,AI对英雄执行一个移动,然后对下一个英雄重复这个过程,使用+1移动计算

问题:我的问题是,我认为,一个“提前思考”3-4步的AI应该找到一个更好的解决方案,而不是一个目前只能执行最佳动作的AI。但我的测试案例显示的不同之处在于,在某些情况下,一个不使用“提前思考”选项的AI(即目前只玩尽可能最好的动作)胜过一个只想一步的AI。有时候,只想向前走3步的AI会比想向前走4或5步的AI强。为什么会这样?我的假设不正确吗?若然,原因为何?我是否使用了错误的重量数字?我对此进行了调查,并进行了测试,以自动计算要使用的权重,测试可能权重的间隔,并尝试使用最佳结果(即,产生最少转动次数和/或最少激活次数的结果),但我上面描述的问题仍然存在于这些权重中

我的当前版本的脚本限制为5步提前思考,与任何更大的提前思考数字一样,脚本速度非常慢(5步提前思考,它在大约4分钟内找到解决方案,但6步提前思考,它甚至没有在6小时内找到第一个可能的移动)

战斗如何进行:战斗以以下方式进行:由AI控制的多个英雄(2-4个),每个英雄拥有多个不同的攻击(1-x),可以在战斗中使用一次或多次,正在攻击多个怪物(1-9)。根据攻击值,怪物会失去生命,直到死亡。每次攻击后,如果被攻击的怪物没有死亡,他会被激怒,并且在每个英雄执行一个动作后,所有的怪物都会被激怒。当怪物达到愤怒极限时,他们就会激活

免责声明:我知道PHP不是用于此类操作的语言,但由于这只是一个内部项目,我宁愿牺牲速度,以我的母语编程语言尽可能快地编写代码

更新:我们目前使用的量化如下:

$Battlefield->setQuantification(array(
 'health'                   =>  16,
 'monsterKilled'            =>  86,
 'activations'              =>  -46,
 'activationsPenalty'       =>  -10
));

如果游戏中存在随机性,那么任何事情都可能发生。指出这一点,因为你在这里发布的材料并不清楚

如果没有随机性,演员们可以看到整个游戏的状态,那么一个更长的展望绝对会表现得更好。如果没有,则表明您的评估函数提供了对状态值的错误估计

在查看代码时,没有列出量化的值,在模拟中,看起来您只是让同一玩家重复移动,而没有考虑其他参与者的可能动作。你需要一步一步地运行一个完整的模拟,以产生准确的未来状态,你需要查看不同状态的价值估计,看看你是否同意它们,并相应地调整你的量化


另一种解决估值问题的方法是,在0.0到1.0的范围内,以百分比的形式明确预测你在这一轮中获胜的几率,然后选择让你获胜几率最高的动作。计算到目前为止所造成的伤害和杀死的怪物数量并不能告诉你为了赢得游戏还有多少事情要做。

Learn(这可能是一种比PHP更适合此类项目的语言)@BasileStarynkevitch learning将如何进行,在这个问题上有什么帮助?在这个模拟中没有任何随机性。我故意忽略了通常会随机进行战斗的所有内容,以确保在开发这个小脚本时得到正确的结果。我用量化值更新了主要问题,如果您能对其发表意见,我将不胜感激。你能详细说明一下缩放是如何进行的吗