CookieClickerをPython Selenium自動的に進める試み③~購入に指向性を持たせる~
何をしたか
これの続き
・前回までで自動でアップグレードするようにはなった
・思ったほど効率が出ず。購入方法に指向性を持たせることにした
・CPS換算で効率のいい施設を購入。長時間購入できない場合は適当に購入するようにした
Sample3
from Sample2 import Sample2 from selenium import webdriver from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.keys import Keys import datetime from GetElepsed import GetElepsed from operator import itemgetter #コスト関連https://www55.atwiki.jp/cookieclickerjpn/pages/7.html class Sample3(Sample2): def setCheckTime(self): self.checkTime = datetime.datetime.now() # 初期処理(コンストラクタめんどくせ) def sample3init(self): self.totalProducts = 0 self.million = 1000000 self.billion = 100000000 self.trillion = 10000000000 self.quadrillion = 10000000000000 # 10秒ごとに施設購入を検討する self.waitTimeMax = 10 self.setCheckTime() self.failCount = 0 #施設CPS def puroductCPS(self, productNo): cps = 0 if(productNo == 0): cps = 0.1 elif(productNo == 1): cps = 1 elif(productNo == 2): cps = 8 elif(productNo == 3): cps = 47 elif(productNo == 4): cps = 260 elif(productNo == 5): cps = 1400 elif(productNo == 6): cps = 7800 elif(productNo == 7): cps = 44000 elif(productNo == 8): cps = 260000 elif(productNo == 9): cps = 1.6 * self.million elif(productNo == 10): cps = 10 * self.million elif(productNo == 11): cps = 65 * self.million elif(productNo == 12): cps = 430 * self.million elif(productNo == 13): cps = 2.9 * self.billion elif(productNo == 14): cps = 21 * self.billion elif(productNo == 15): cps = 150 * self.billion return cps #施設の単価 def productsCost(self, productNo): cost = 0 if(productNo == 0): cost = 15 elif(productNo == 1): cost = 100 elif(productNo == 2): cost = 1100 elif(productNo == 3): cost = 12000 elif(productNo == 4): cost = 130000 elif(productNo == 5): cost = 1.4 * self.million elif(productNo == 6): cost = 20 * self.million elif(productNo == 7): cost = 330 * self.million elif(productNo == 8): cost = 5.1 * self.billion elif(productNo == 9): cost = 75 * self.billion elif(productNo == 10): cost = 1 * self.trillion elif(productNo == 11): cost = 14 * self.trillion elif(productNo == 12): cost = 170 * self.trillion elif(productNo == 13): cost = 2.1 * self.quadrillion elif(productNo == 14): cost = 26 * self.quadrillion elif(productNo == 15): cost = 310 * self.quadrillion # 最初以外は総施設数の1.15倍 multiple = self.productsOwned(productNo) * 1.15 if self.productsOwned(productNo) != 0 else 1 return cost * multiple # 所持数 def productsOwned(self, productNo): try: element = self.driver.find_element_by_id("productOwned" + str(productNo)) text = element.text if not text: text = "0" return int(text) except Exception as e: print(e) # 費用対効果 def cpsPerPrice(self, productNo): cost = self.productsCost(productNo) cps = self.puroductCPS(productNo) return cps / cost # 最も費用対効果順にならびかえ def mostCpsProduct(self): try: ret = [[0,0],[1,0],[2,0],[3,0],[4,0],[5,0],[6,0],[7,0],[8,0],[9,0],[10,0],[11,0],[12,0],[13,0],[14,0],[15,0]] for var in (range(0,15)): ret[var] = [var,self.cpsPerPrice(var)] return sorted(ret, key = itemgetter(1), reverse = True) except Exception as e: print(e) def buy(self,productNo): # 買えるだけ買う while(True): # 万とかなんとか桁の漢字を使ってくるので、Cookiesを取得するのが面倒だから、 # ownedの増加で買えたかどうか。を判定する preClickOwned = self.productsOwned(productNo) try: element = self.driver.find_element_by_id("product" + str(productNo)) element.click() except Exception: # オブジェクトがない。とかは無視(購入できなかった break clickedOwned = self.productsOwned(productNo) if(preClickOwned != clickedOwned): self.totalProducts = self.totalProducts + 1 return True break else: # Cookiesが足りない。購入できなかった。 break return False def productClick(self) : elepsed = GetElepsed.getElepsedNow(self.checkTime) if(elepsed < self.waitTimeMax): return self.setCheckTime() # 厳密には再計算がいるけど、誤差だろう productNos = self.mostCpsProduct() # 高効率Topを購入できるだけ買う success = self.buy(productNos[0][0]) if success : return self.failCount = self.failCount + 1 if self.failCount < 3: return #3回(30秒)も失敗するなら適当に買ったほうが早い self.failCount = 0 for var in productNos: # 買えるだけ買う self.buy(var[0]) def init(self): super().init() #メソッドリストにぶち込む def getBeforeExecFunctions(self): super().getBeforeExecFunctions() self.beforeExecFunctions.append(self.sample3init)
前回に引き続き、継承して無理やり動かすスタイル。
productClickを改変している
コメントをだいぶ書くようにした(書きなぐりだけど)
ざーっとソースを見ればわかると思うが、だいぶベタで書いている
# 最も費用対効果順にならびかえ def mostCpsProduct(self): try: ret = [[0,0],[1,0],[2,0],[3,0],[4,0],[5,0],[6,0],[7,0],[8,0],[9,0],[10,0],[11,0],[12,0],[13,0],[14,0],[15,0]] for var in (range(0,15)): ret[var] = [var,self.cpsPerPrice(var)] return sorted(ret, key = itemgetter(1), reverse = True) except Exception as e: print(e)
ここが目玉か。コメントの日本語がいかれている
16種類の施設のCpsPerPriceを拾ってきて、降順ソートしている
厳密なCPS効率はWiki参照。非常に詳しく書いてあってビビる
# 最初以外は総施設数の1.15倍 multiple = self.productsOwned(productNo) * 1.15 if self.productsOwned(productNo) != 0 else 1 return cost * multiple
pythonの三項演算子。C#と位置関係がずれてて見にくいなーとおもったけど
こっちのほうが「デフォルト」と「例外」が明示できて好きかもしれない。
c#は
x = (a == b) : "aaa" ? "xxx"
みたいに書くからどっちが「例外値」なんだろう。って割となる
結果
8時間で前回の(Sample2)とCPSを比較してみた
Sample2
Sample3
ソース | CPS |
Sample2.py | 152.1697万 |
Sample3.py | 176.8774万 |
指向性を持たせたほうが伸びてはいるが・・・思ったより伸びない
現状の「効率」はあくまでのCPSとCookiesの消費量から算出しているためだと思われる。(ちゃっちゃと買ったほうが早い場合、貯めたほうが早い場合が判定できていない
あとはアップグレードによる効率も無視してる(タイミング次第で倍々に効率が上がっていくから個数も重要になってくる
※高効率狙いすぎて「買わずに待機」が長いから40秒ぐらいでランダムで買ってしまってるけど。。。秒数をゲームの進行に合わせて伸ばすべきかも
所感
クッキークリッカー楽しい(邪道だけど)
コードもだいぶ雑になってきて、メソッド名も適当になりだしてるのでここらが潮時か・・・
そろそろPythonだし、AIの導入時期かもしれない(修練が足りないので導入できないが)
Wikiの狂気というか、数式はでるはシナジーは調べつくされてるはでガチ勢の恐ろしさを感じた
有志で1時間のタイムアタック(CPS)とかで勝負するのも楽しいかもしれない(Javascript禁止にしないとすぐいかれたCPSにできるけど)
python初心者。ぐらいには慣れたと思う。ライブラリも豊富でまだまだ手足のように・・・とはいかない