Skip to content

如何编写你自己的WindBot AI

Mercury233 edited this page Nov 9, 2017 · 19 revisions

WindBot用C#开发。C#比较易于使用,因此编写一个AI并不困难。本文以编写一个光道卡组为例,介绍编写WindBot AI的方法。

There will be an English version of this document.

准备工作

  • Visual Studio
    在VS2015上测试通过,VS2010理论上可用.
  • 基本的编程基础
    变量、函数、类、对象、数组、if、for、while之类的基础知识。
  • 基本的YGOPro知识
    不会打牌也想教AI打牌?

开始吧

1. 组一个卡组

image

(我不会玩光道,这是我乱组的)

卡组以易用为优先。一张卡的用法越多,写AI就越难。

把ydk文件命名为AI_Lightsworn,放到windbot的decks文件夹里。

2. 创建Executor

Executor(与Java的那个无关)是执行者的意思,用来给每个卡组规定每张卡片的用法等。

在Game\AI\Decks下新建代码文件,命名为LightswornExecutor
(你操作时,LightswornExecutor可能已经被写好了,所以换个NewLightswornExecutor之类的名字)

在其中写以下代码:

using YGOSharp.OCGWrapper.Enums;
using System.Collections.Generic;
using WindBot;
using WindBot.Game;
using WindBot.Game.AI;

namespace WindBot.Game.AI.Decks
{
    [Deck("Lightsworn", "AI_Lightsworn")]
    public class LightswornExecutor : DefaultExecutor
    {

        public LightswornExecutor(GameAI ai, Duel duel)
            : base(ai, duel)
        {

        }

    }
}

可以看到,在WindBot.Game.AI.Decks下新建的LightswornExecutor继承了DefaultExecutor
Deck属性的第一个参数是卡组名,第二个是卡组文件名。

3. 跑一下看看

在YGOPro中建立主机后,使用以下参数在VS中启动

Deck=Lightsworn

image

如果一切正常,你可以看到AI加入房间并且准备了。

  • 如果AI没有出现,请确定是先建立主机才启动的WindBot。
  • 如果AI不准备,请确定卡组文件放到了正确的位置,并且WindBot有正确的cards.cdb。

但是开始游戏后我们会发现AI什么牌都不会出,这是因为我们没有给AI指定卡的使用方法。

WindBot只会使用卡组的Executor中指定了的卡,其他卡一律不做任何操作,除了攻击和必发效果。

所以我们要做的事就是为每张卡写用法。

(当然dalao可以尝试写一个所有卡都会用的Executor)

4. 建立卡名类

为便于在代码中指定卡名,我们建立一个CardId类,把每个卡名写成常量。

在LightswornExecutor下(不是构造函数里)创建CardId类,定义卡组里的每张卡的ID:

        public class CardId
        {
            public const int JudgmentDragon = 57774843;
            public const int Wulf = 58996430;
            public const int Garoth = 59019082;
            public const int Raiden = 77558536;
            public const int Lyla = 22624373;
            public const int Felis = 73176465;
            public const int Lumina = 95503687;
            public const int Minerva = 40164421;
            public const int Ryko = 21502796;
            public const int PerformageTrickClown = 67696066;
            public const int Goblindbergh = 25259669;
            public const int ThousandBlades = 1833916;
            public const int Honest = 37742478;
            public const int GlowUpBulb = 67441435;

            public const int SolarRecharge = 691925;
            public const int GalaxyCyclone = 5133471;
            public const int HarpiesFeatherDuster = 18144506;
            public const int ReinforcementOfTheArmy = 32807846;
            public const int MetalfoesFusion = 73594093;
            public const int ChargeOfTheLightBrigade = 94886282;

            public const int Michael = 4779823;
            public const int MinervaTheExalted = 30100551;
            public const int TrishulaDragonOfTheIceBarrier = 52687916;
            public const int ScarlightRedDragonArchfiend = 80666118;
            public const int PSYFramelordOmega = 74586817;
            public const int PSYFramelordZeta = 37192109;
            public const int NumberS39UtopiatheLightning = 56832966;
            public const int Number39Utopia = 84013237;
            public const int CastelTheSkyblasterMusketeer = 82633039;
            public const int EvilswarmExcitonKnight = 46772449;
            public const int DanteTravelerOfTheBurningAbyss = 83531441;
            public const int DecodeTalker = 1861629;
            public const int MissusRadiant = 3987233;
        }

image

如果你感觉英文卡名看不懂,也可以用中文,不过这会导致其他人看不懂,自行权衡吧。

5. 最简单的Executor,让AI会发羽毛扫,会通招莱登

除了卡组的Executor,每张卡片都应该有一个或多个Executor。

下面我们在LightswornExecutor的构造函数里注册两个Executor:

AddExecutor(ExecutorType.Activate, CardId.HarpiesFeatherDuster);

这让AI在HarpiesFeatherDuster可以发动时发动它。

AddExecutor(ExecutorType.Summon, CardId.Raiden);

这让AI在Raiden可以通常召唤时召唤它。

image

在AI的主要阶段,手里同时有莱登和羽毛扫,如何决定先后顺序呢?

答案是根据注册Executor的顺序,先注册的先操作。

每当AI可以发动效果或召唤,它会检查当前的卡组的Executor,依次判断里面的操作是否可用,如果可用则进行操作。
然后会重新从头开始,因为YGOPro不支持一次进行2个操作,而是在进行完一个操作之后重新发给客户端可进行的操作的列表。

Clone this wiki locally