本文共三個部分:
- 我用python玩爐石傳說(1)-----爐石卡牌相關度分析的手動打分器
- 我用python玩爐石傳說(2)-----爐石卡牌套牌爬取器及自動分析卡牌相關度
- 我用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個構建好的卡組,估計使用自己手動打分會比較好,因爲更加全面客觀。