我用python玩炉石传说(3)-----炉石卡牌套牌自动构建算法

 

本文共三个部分:

  1. 我用python玩炉石传说(1)-----炉石卡牌相关度分析的手动打分器
  2. 我用python玩炉石传说(2)-----炉石卡牌套牌爬取器及自动分析卡牌相关度
  3. 我用python玩炉石传说(3)-----炉石卡牌套牌自动构建算法

 

引言:

前面两部分已经完成了卡牌之间的相关度分析,现在需要完成我们的最终目的,构建一个套牌deck。

最初,想用最简单的方法,即选择相关度最高的来完成构建,例如:首先选择情势反转,最相关的是阿兰纳斯蛛后,最选择与蛛后最相关的,地狱烈焰,然后依次进行,直至选满30张卡牌。

但实际发现这样构建出的套牌,虽然看似相关度高,但实际非常分散与自闭(由于缺少尘与卡牌,所以并没有完全按选出的卡牌实测)。表现出非常卡手,或是combo往往难以达成,提前拆散,可以想象为自行车链条,每个节点高度相关,成链式。但如果某张卡牌不得不出于解场,除掉后,相关性就中断了。也就是虽然combo很多,但combo与combo之间的耦合度很低,套牌构建不完善。

所以需要一种能发现最佳套牌的算法。需要两个‘器件’,迭代器以及打分算法

autobuild.py

一,卡组记录类

class BDeck:
    cardinfo = None
    corrmat = None

    def __init__(self, dicklist: list, cardnum: int, score: float):
        self.dicklist = dicklist
        self._cardnum = cardnum
        self._score = score

    def __len__(self):
        return len(self.dicklist)

    def __lt__(self, other):
        return self.score < other.score

    def appid(self, idn: int):
        self._score = self._score + self._newscore(idn)
        self._cardnum = self._cardnum + self.cardinfo.id2cardmaxnum(idn)
        self.dicklist.append(idn)

    def _newscore(self, idn):
        newscore = 0.0
        for n, i in enumerate(reversed(self.dicklist), 1):
            s = self.corrmat.get_rmatrix[idn, i]
            newscore += s / n
        return newscore

类中记录卡组的卡牌,以及卡组的得分,卡牌数量。

func appid:为添加新卡进入卡组时,自动计算其总得分

分数计算方法改进:不只是计算新加入的卡牌与其之前的卡牌相关度得分(4-5),还要计算其与之前所有加入卡牌的相关度累加得分(1-5, 2-5,,,),其中会对其卡牌距离做一定的衰减,例如 1-5会除于其相距距离5,2-5除4。可以理解成,我们希望新加入的卡牌,能与之前的卡牌有一定的相关耦合关系,成为一个体系,而不是又节外生枝发展出另一个体系(例如,本来是ZOOLOCK的,但发展到后来又出现了handlock卡牌)。但是,我们知道一个卡组里不可能全部都与一张卡牌相关,那样耦合的过于紧密,类似于全部聚类在了一起,那样只要1卡牌出完,那整个体系就崩溃了,所以加入衰减使卡牌加入顺序相隔越远的,所受影响会越小。(但实际上最后实验效果还是出现了多分支)

 

二,遍历所有卡牌组合的递归算法

def recursion_trave(deck: BDeck, spreed, deep):
    if deep < 1:
        spreed = 20
    elif deep == 1:
        spreed = 15
    elif deep == 2:
        spreed = 10
    elif deep == 3:
        spreed = 5
    elif deep == 4:
        spreed = 5
    elif 5 <= deep <= 6:
        spreed = 5
    elif 7 < deep <= 15:
        spreed = 3

    lastcard = deck.dicklist[-1]
    scope = RM.get_rmatrix[lastcard, :]
    scope[deck.dicklist] = 0
    scopesort = np.argsort(scope)[::-1]

    maxscoredeck = deck

    for i in range(spreed):
        if scope[scopesort[i]] > 0:
            idn = scopesort[i]
        else:
            break
        nextdeck = deepcopy(deck)
        nextdeck.appid(idn)

        if nextdeck.cardnum < 30:
            nextdeck = recursion_trave(nextdeck, spreed, deep)
        maxscoredeck = max(maxscoredeck, nextdeck)

    return maxscoredeck

选定一张核心牌1,然后遍历其所有与之相关的卡牌(2,3,4,5,6),进一步,再分别遍历与(1-6)相关的(1-6-7,1-6-8,1-6-9.。。。),无限递归进行下去,直至加入卡牌数量达到30张。就这样遍历了基本所有可能性,然后总结出得分最高的卡组。

 

代码链接:https://github.com/GladosAI/hearthstone-card-correlation-analys

 

实验效果

莫瑞甘的灵界
烈焰小鬼
虚空行者
怪盗天才
残酷集结
双生小鬼
巨型小鬼
小鬼狱火
拉法姆的阴谋
恶魔法阵
至暗时刻
伊瑟拉
恶狼大法师
凯恩·血蹄
人偶大师多里安
邪能领主贝图格
情势反转
阿兰纳丝蛛后

(默认是除了传说,其他都带两张,自己缺卡没试过,估计不行,算法还要改进,有条件的朋友可以试试)

(我个人觉得 换掉伊瑟拉 为一个效果不错的亡语或巨人 可能还能玩。恶狼大法师还是太卡,也换掉。把卡牌风格向zoo上靠,可能还救得活,毕竟反转+人偶大师/邪能 也能铺场)

这是算法自己生成的,有个问题,在恶魔法阵前本是恶魔zoo术的,后来由于至暗时刻与恶魔法阵与阴谋算是combo,导致后面节外生枝为另一个体系反转术。这里使用的是第二章里的相关度数据,来自400个构建好的卡组,估计使用自己手动打分会比较好,因为更加全面客观。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值