💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
为了排解郁闷的心情,孙悟空又躲到角落里薅它头上的猴毛去了,只见随口一吹,几根毛发就变成了几个小猴子,来陪它来联机打太阳神三国杀了。 </br>(编者:不要总羡慕关羽能拿红牌当杀了,我们来设计一个所有牌都能当杀的技能盖过他吧?孙悟空:要所有牌都当决斗!……) </br>好吧,所以我们为了安慰我们的新武将孙悟空同志,就来看一看怎样实现下面的一个技能吧: > 斗佛:你可以将一张牌当作【决斗】使用。 </br>首先我们来分析一下这个技能: </br>这个技能和之前我们设计的技能有一个很大的不同,那就是前面的技能大多都有明确的触发时机,属于触发技;而这个技能虽然只能在出牌阶段使用,但是并没有明确的触发时机。我们可以上来就发动,也可以先装个八卦阵什么的再发动,甚至可以不发动。 </br>更为明显的是,这个技能明确表明,要将一张卡牌视作另外的一张卡牌使用。这样的一个技能,不正符合早先我们提到的“视为技”的特点吗?没错了,这就是一个典型的视为技了。 </br>所以为了创建这个技能,我们就应当采用创建视为技的那个方法了……叫什么来着?哦,是这个:sgs.CreateViewAsSkill。 </br>根据斗佛这个技能名字,还是取`name = "LuaDoufo"`吧。 </br>这是一个要求用1张牌发动技能的视为技,所以必然有参数n=1。 </br>由于任何一张牌都可以用来发动技能,所以view_filter函数直接返回true就好啦。 </br>view_as函数描述的是被视为的卡牌,我们需要花费心思的地方到了! </br>还记得在游戏里面那个游戏记录是怎么说的吧? “武将a 使用了【技能b】将 卡牌c 当成了 卡牌d 使用,目标是 武将e” </br>所以为了发动这个视为技,我们至少需要提供以下五个信息: 1. 技能的使用者武将a; 2. 技能的名字b 3. 发动技能所用的卡牌c; 4. 被视作的卡牌d; 5. 技能的使用对象武将e。 </br>而具体到被视为的卡牌上,需要的信息就是:技能名字b、发动卡牌c,和由此得到的被视作的卡牌d了。 </br>技能的名字啊……当然是刚才确定的"LuaDoufo"了; </br>而发动的卡牌呢?还记得view_as函数的原型是function(self, cards)吧?这个cards就是被选取用来发动技能的卡牌名单了。可以考虑从这里做一些文章。 </br>获取这个名单中的第一张卡牌(其实总共应该就有一张而已啦),所用的方法很简单,使用一个方括号里面写个"1"标注一下就可以了:cards[1]。 </br>不过在获取这张卡牌之前呢,还是要先猫腰打探一下名单里面到底有没有卡牌为妙。具体的方法就是测量一下名单到底有多长,要是0的话就没有卡牌,要是1的话就说明正确选取了发动技能的卡牌。 </br>测量名单长度的方法就更简单了,只需要把一个"#"放到名单前面,就可以了。没错,#cards就代表了cards这个名单的长度。 </br>所以现在代码应该是这样写的: ![](https://img.kancloud.cn/01/3c/013cd5386cf57ea082a2d43863369ef0_617x329.png) </br>那么要怎么创建这个虚构的卡牌呢? </br>一个卡牌有这么几个必要的信息: 1. 卡牌编号(id),是一个数字啦,表示在卡牌一览那个表里面的默认出现顺序啦。所以对于每张卡牌来说,编号是唯一的。当然虚构的卡牌就没有具体的编号了。 2. 卡牌花色(suit),就是什么黑桃、红心、方块、草花什么的信息了。我们这里就用卡牌c的花色作为这个虚构的卡牌花色吧。 3. 卡牌点数(number),用数字1~13代表A、2……10、J、Q、K这些现实中的点数。这里我们同样用c的点数作为这个虚构的卡牌点数吧。 </br>所以首先我们要先获得发动技能的这张卡牌的上述信息。这时来了一封邮件,是一个不熟悉的地址来的。“我是Card,是管教你们所遇到的各种卡牌的指挥官。你们可以从源码(可在群文件里搜索 秒沉水 查找到源码)的src\core\card.h中找到我。”接下来它为我们介绍了许多有关Card自身的信息,然后推荐了一些成员函数: </br>☆ getId():可以获得一张卡牌的编号 ![](https://img.kancloud.cn/10/5b/105b1036b3d51189803e998817fbfb1a_182x28.png) </br>☆ getEffectiveId():可以获得一张卡牌的名义上的编号(虚构卡牌也可用) ![](https://img.kancloud.cn/d7/72/d772a52cdbb632614405939d01414564_273x26.png) </br>☆ getSuit():可以获得一张卡牌的花色 ![](https://img.kancloud.cn/25/9d/259d67285d55a5bd6fedde0937184e33_216x26.png) </br>☆ getNumber():可以获得一张卡牌的点数 ![](https://img.kancloud.cn/0a/c0/0ac05d0a96148e947d52489fb0f1f093_224x25.png) </br>因此接下来的代码就是: ![](https://img.kancloud.cn/b1/0c/b10cf50986f3a9d709633ccc0819cb4c_475x154.png) </br>接下来到了关键的一步——创建虚构的决斗卡牌! </br>这需要我们邀请一位BOSS级别的大仙闪亮登场了!被称为太阳神三国杀发动机的Engine终于千呼万唤始出来了!大仙有一个堪称法宝的成员函数,那就是可以根据卡牌原型为我们创造各种虚构卡牌的 cloneCard!它的函数原型有三个,分别是: ``` cloneCard(card) cloneCard(name, suit, number) cloneCard(name, suit, number, flags) ``` ![](https://img.kancloud.cn/25/2a/252aec11ddd0547f0e0a538204937924_955x65.png) </br>第一个原型是根据一张已有的卡牌创造一张一样的卡牌,参数card就是那张给定的卡牌了; </br>第二个原型是根据给定的卡牌名称、花色、点数创造一张符合条件的卡牌,参数name表示卡牌类型名称,suit表示卡牌花色,number表示卡牌点数。 </br>第三个原型和第二个差不多,都是根据给定条件创造一张卡牌,参数上也就是多了一个flags而已。这个flags表示一些特定标志的列表。 </br>此外,在我们的诚挚请求下,Engine大仙还带来了它的一个得意化身来帮助我们完成这件事情,这就是:sgs.Sanguosha前辈。 </br>我们已经打探到,关于Engine和sgs.Sanguosha的详细信息,还是可以从源文件下的swig\sanguosha.i文件中找到的。 </br>在此有必要了解一下我们要创造的卡牌到底是什么名称,提供了这些细节的东西,才好继续我们的工作嘛。 </br>卡牌的类型名称,就列在下面了: </br>☆ 基本牌: * 杀:slash * 火杀:fire_slash * 雷杀:thunder_slash * 闪:jink * 桃:peach * 酒:analeptic ☆ 非延时性锦囊牌: * 决斗:duel * 火攻:fire_attack * 南蛮入侵:savage_assault * 万箭齐发:archery_attack * 过河拆桥:dismantlement * 顺手牵羊:snatch * 桃园结义:god_salvation * 五谷丰登:amazing_grace * 铁锁链环:iron_chain * 借刀杀人:collateral * 无中生有:ex_nihilo * 无懈可击:nullification ☆ 延时性锦囊牌: * 乐不思蜀:indulgence * 兵粮寸断:supply_shortage * 闪电:lightning </br>所以,创建一个虚构的决斗,应该是这样写的: ``` sgs.Sanguosha:cloneCard("duel", suit, point) ``` ![](https://img.kancloud.cn/f1/8e/f18edc87eb30689f08e89f102eb268e1_646x197.png) </br>这是一张刚刚被创建的卡牌,什么都没有,只是一层外壳,还很虚弱;而我们接下来要做的,就是建立它和我们发动技能的卡牌的联系,用我们的卡牌充实它,让它有信心、有能力实现自己的使命。 </br>用已有卡牌充实这张虚构卡牌的任务,就交给了Card的一个专职于此的成员函数:`addSubcard`,翻译为“添加子卡”。这个函数的原型是: ``` addSubcard(id) addSubcard(card) ``` ![](https://img.kancloud.cn/2e/f7/2ef70585677de1676e93bd0cf4bfa760_425x46.png) </br>哦,有两个原型,一个是以卡牌编号id为参数的,另一个是以卡牌本身card为参数的。这里我们就选择第一个好啦。 ![](https://img.kancloud.cn/32/1a/321a0d61db5c64b543e054eed79c8fb3_613x135.png) </br>OK,虚构卡牌完成,把早就等在一旁的技能名字"LuaDoufo"也交给它吧。这回,借助Card的成员函数setSkillName就可以了。原型是这样的: ``` setSkillName(skill_name) ``` ![](https://img.kancloud.cn/fb/41/fb4156e0f17dc456d5fea1a1d1a478ea_534x25.png) 其中的参数`skill_name`就是技能的名字啦。 这下,view_as部分就完整了!代码如下: ![](https://img.kancloud.cn/66/c3/66c3f3b44653c84d0168d41ce7a81b5b_684x355.png) </br>然后我们继续…… 由于我们可以在出牌阶段随意使用决斗,而在回合外又不能用决斗进行什么响应,跟无懈可击也没什么关系,所以剩下的三个函数: * enabled_at_play(默认为true) * enabled_at_response(默认为false) * enabled_at_nullification(默认为false) </br>我们就不再写了,让它们取默认值去吧! </br>最终这个技能就是这么创建出来的了…… ![](https://img.kancloud.cn/5a/7e/5a7ec80e0abff4228f800fc15d3a86ec_742x508.png) </br>到游戏里面体验一下吧! ![](https://img.kancloud.cn/27/68/276884f2a27df418bbaf9462d4af1dcd_244x122.png) </br>搞定!(编者:悟空!你去跟关羽决斗吧!)