斗地主之初始评估与叫牌

Posted by 小一在此 on August 23, 2017

有了牌型,我们还需要对牌型进行评估。评估的目的是判明各牌手、牌型的强弱,以决定如何打牌。评估包括两个阶段,第一阶段是牌型整理好之后、出牌之前的初始评估,以建立初始的基本判断;第二阶段是各玩家(包括自己在内)每出一手牌之后的动态评估,也就是调整之前的评估或重建最新的评估。

初始评估包括了三个层面:牌手的评估、牌型的评估、牌面的评估。

牌手的评估

牌手的评估主要是对每手牌都进行强弱的判断。包括两个步骤:

首先是牌力判断。即将我们指定的牌力大小(即剩余牌手数大小)转换为衡量牌力大小的模糊量。其实就是对牌力用大还是小这样的模糊量进行定性判断,而这种定性判断我在之前关于模糊控制的文章中说过,主要还是一种主观的判定。牌力判断的目的在于为后面利用人的知识做准备,因为一般来说,我们日常工作生活所用到的知识都是定性的经验判断

其次是初始牌力的调整。我们之前在用蚁群算法寻找最优牌型时使用的剩余牌手数是只考虑该牌手一般情况下的牌力,但没有考虑手中其它的牌。所以,首先我们就必须结合手中其它的牌点情况对牌力进行下调整。这个调整主要是在单张、对、三张、三带二等几个牌型中,是对部分有可能是最大的牌手进行调整,如当手中有大鬼、小鬼时,则将对2的牌力估计判断为最大。

对于顺子、连对、飞机等则不做调整。

牌型的评估

牌型的评估是针对单张、对子等某一牌型进行总体评估。单一牌点(即单张、对、三张、三带二等)的牌型强弱主要是看被判断为非常大的牌、较大的牌(可顺出去)和小牌(顺不出去的都算)这三者间的数量关系。原则上,是非常大的牌和小牌数量之间的差为强弱的主体判断,同时增加较大的牌的数量加以微调。

非常大的牌可能带牌,小牌则必须消耗掉一个牌权(一手非常大的牌或者炸弹)才能出去,较大的牌牌是可以顺出去。因此,这个处理是剩余牌手数概念的自然顺延,只是剩余牌手数是用于牌型整理过程最基础的牌力计算。而我们这里是将剩余牌手数转换为牌力大小的定性判断之后的处理。

而对于顺子、连对、飞机只是简单的看一下这些牌型中是否有防守牌型即可,这是由于这些牌想顺牌或带牌都必须要求有恰好相同数量的牌手才可以,所以对于这些牌型除非非常整齐,一般都不需要太过关切。

牌面的评估

牌面估计就是通过对上述各牌手、各牌型的估计,综合出对整个牌面的强弱估计,然后拟定大略的打牌策略。

斗地主和我们传统AI中的双人博弈的棋类游戏不同的一点就在于其牌型的变化组合与农民之间的配合,因此我们没办法简单的通过博弈树之类的方法来构造每一步的选择。我考虑,农民一方的基本策略是:

  • 寻找地主的弱点牌型,然后围绕该牌型组织过桥以将牌权控制在农民一方

  • 有攻击意图的农民(主要是对家和下家)利用过桥将手中小牌快速出完,然后开始攻击,或一击致命,或迫使地主因为阻击自己而导致牌型散乱从而为其他人的攻击创造条件

相应的,地主的策略是:

  • 保护自己的弱点,争取在农民一方寻找自己弱点的过程中多顺牌,并尽量消耗农民方的实力

  • 在适当时机打断农民的桥,迫使农民方原定的攻击者无法就位,不得不在重新组桥的过程中大量消耗实力

归根结底,人类的策略,不管是打牌,还是商业竞争,还是战争,都是基于对当前资源的了解、对同伴/对手的判断、预期其应对方略/演化趋势,然后根据目标来拟定行动计划。那么,斗地主就是一个目标非常明确(我方先出完牌)、资源非常明确(手中的牌,但可以自由组合为不同的牌手)、同伴/对手的动作非常明确(其他三家的出牌我当然一清二楚)。所以,斗地主的策略其实是很明确的,农民方的策略:

  • 攻击:牌型有力、位置有利,请求其他农民的配合以展开攻击

  • 防守:阻击地主、配合其他农民

地主方的策略:

  • 防守:顺牌,在适当时机打击尝试攻击的农民

  • 拉长战线:牌型不佳,弱点明显,以消耗农民牌力为主

  • 攻击:牌力强大,尝试攻击

但是,这样的策略如何反映到我们的程序中呢?!

还是那句话:数字世界和世界世界有着本质的不同,我们要进行恰当的转换。因此,我将简化后的策略理解为一个综合判断,用来指导打牌过程中每一手如何打。换成IT术语就是,预先计算出一个粗略的中间结果,而这个中间结果是对某玩家的出牌历史和手中的牌型的概括性判断,这样当在精确计算每一手牌如何打时,可以降低计算量。

其次,我将策略理解为一个衡量标准。策略不同,就是对手中各牌型、牌手的强弱采用不同的衡量标准。比如,拉长战线的策略下,三张2明显不如3个单张2有价值,但在攻击的策略下,显然是反过来的。

叫牌

叫牌其实还在牌型整理之前,但由于其比较简单,就顺便在这里说下了。由于还有底牌的8张牌的变数,而这个变数是接近三分之一的大变数(底牌8张,手中的牌是25张),所以叫牌其实没办法也不需要多么的精准,因此采用了基本的点数估算法:

  • 炸弹的数量

  • 三张的数量

  • 大鬼(如有两张大鬼则加上小鬼)的数量

  • 其他三家预估各有一手炸弹(即点数应减去3)

然后将这些点数累加后,进行下微调:如果大牌(K、A、2)的数量较少则减一、如果有其他玩家叫两档则其他三家预估炸弹数加一(总点数减一)。最终计算出来的点数即为叫牌档数

====================================================================================================

关注我的公众号及时获取推送的最新文章

公众号