我用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個構建好的卡組,估計使用自己手動打分會比較好,因爲更加全面客觀。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章