Guest User

Python 3 script for figuring out the best Ignite Mage deck - 2023 version. By Lt.Labcoat

a guest
Apr 19th, 2023
897
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 24.42 KB | None | 0 0
  1. # Python 3 script for figuring out the best Ignite Mage deck
  2. # by Lt.Labcoat
  3.  
  4.  
  5. import random
  6. import sys
  7.  
  8. start_hand = []
  9.  
  10. # unused card names:
  11. # biscuit-maker 2manadraw1 3manadraw2 heropower 3manaspellsearch jaxon 2manaspellsearch
  12. # ice-search-2mana firesale sapience wonder-deck spicebaker
  13.  
  14. # Tradeables: 6
  15. # Deck size: 30
  16. # Chance to win if survived to turn 5: 0.65528 - Average turns: 5.26672625
  17.  
  18.  
  19. # TODO: Sivara odds should be higher. Just treated as an ice block right now.
  20. # TODO: ETC calculations. Currently treated as a dead card.
  21.  
  22. deck_base = ["evoc",
  23. "tradeable", "firstflame",
  24. "ele", "tradeable", "tradeable",
  25. "ice",
  26. ] * 2
  27. deck_base += ["sorc", "sorc"]
  28.  
  29.  
  30. deck_base += ["volume", "sivara", "rewind", "rewind", "ETC", "rommath"]
  31. deck_base += ["volume", "ignite", "reflection", "hotstreak", "magister", "2manadraw1"]
  32.  
  33. deck_base += ["ice-search-2mana-spell", "sapience"]
  34.  
  35. print(f'Tradeables: {deck_base.count("tradeable")}')
  36.  
  37. spells = ["hotstreak", "evoc", "biscuit-maker", "firstflame", "ignite", "ice", "reflection", "heropower", "firesale",
  38. "springwater", "volume", "rewind"]
  39. spells_chandler = ["hotstreak", "firstflame", "firstflame", "generic-fire"]
  40. spells_nonchandler = ["ice", "biscuit-maker", "firesale", "springwater", "ice-used-chandblock", "volume", "ice-search-2mana-spell"]
  41. spells_chandler_expensive = ["ignite", "reflection"]
  42.  
  43. hand_skips = ["jaxon", "reflection", "tradeable", "ele-search", "magister", "firesale", "3manadraw2", "firstflame", "hotstreak", "sorc-search", "ignite",
  44. "2manadraw1"]
  45.  
  46. print(f"Deck size: {len(deck_base)}")
  47. if len(deck_base) != 30:
  48. sys.exit()
  49.  
  50. wonder_counter = 0
  51. turns_taken = []
  52.  
  53. for i in range(0, 50000):
  54. deck = deck_base.copy()
  55. random.shuffle(deck)
  56. hand = list()
  57. enemy_is_rattable = False # (i%100 >= 95)
  58. enemy_is_spells = False # (i % 1000 <= 1000*(1-(15/43)))
  59. enemy_ignores_secrets = False # random.random() <= 15/45
  60. enemy_is_reno = False # random.random() <= 10/45
  61. enemy_destroys_secrets = False # enemy_is_reno or random.random() <= 5/45
  62.  
  63. if start_hand:
  64. going_second = len(start_hand) % 4 == 0
  65. hand.extend(start_hand)
  66. else:
  67. going_second = (i % 2 == 1)
  68. hand.append(deck.pop())
  69. hand.append(deck.pop())
  70. hand.append(deck.pop())
  71. if going_second:
  72. hand.append(deck.pop())
  73.  
  74. # mulligan
  75. for c in range(0, len(hand)):
  76. hand_c = hand[c]
  77. if hand_c in hand_skips or \
  78. (enemy_is_spells and hand_c == "varden") or (not enemy_is_spells and hand_c == "loatheb") or \
  79. (hand_c == "ele-search" and "ele" in hand) or (hand_c == "sorc-search" and "sorc" in hand) or \
  80. (hand_c == "ele" and hand.count("ele") > 1) or (hand_c == "sorc" and hand.count("sorc") > 1) or \
  81. (hand_c == "ice" and ("ice-search" in hand or "ice-search-2mana" in hand or hand.count("ice") > 1)) or \
  82. (hand_c == "ice-search" and ("ice-search-2mana" in hand or hand.count("ice-search") > 1)) or \
  83. (hand_c == "ice-search-2mana" and hand.count("ice-search-2mana") > 1) or \
  84. (hand_c == "ice-search-2mana-spell" and hand.count("ice-search-2mana-spell") > 1) or \
  85. (not (enemy_is_rattable or enemy_destroys_secrets) and hand_c == "rat") or \
  86. (not enemy_is_reno and hand_c == "albatross"):
  87. hand[c] = deck.pop(0)
  88. deck.append(hand_c)
  89. random.shuffle(deck)
  90.  
  91. iced_turns = 0
  92. iceblock_used = 0
  93. success = False
  94. sapience = False
  95. jaxon = False
  96. volume_used = False
  97. acolyte_hp = 0
  98.  
  99. for turn in range(1, 20):
  100.  
  101. mana = turn
  102. newcard = deck.pop()
  103. if sapience:
  104. jaxon_discover = [newcard]
  105. if "ele" in jaxon_discover and "ele" not in hand:
  106. newcard = "ele"
  107. elif "sorc" in jaxon_discover and "sorc" not in hand:
  108. newcard = "sorc"
  109. elif "volume" in jaxon_discover and "volume" not in hand:
  110. newcard = "volume"
  111. elif iced_turns == 0 and "ice-search-2mana" in jaxon_discover and "ice" in deck and "ice-search" not in hand:
  112. newcard = "ice-search-2mana"
  113. elif iced_turns == 0 and "ice-search" in jaxon_discover and "ice" in deck and "ice-search" not in hand:
  114. newcard = "ice-search"
  115. elif iced_turns == 0 and "ice-search-2mana-spell" in jaxon_discover and "ice" in deck and "ice-search" not in hand:
  116. newcard = "ice-search-2mana-spell"
  117. elif iced_turns == 0 and "ice" in jaxon_discover and "ice-search" not in hand:
  118. newcard = "ice"
  119. elif newcard in ["evoc", "hotstreak", "reflection"]:
  120. newcard = newcard
  121. else:
  122. deck.append(newcard)
  123. newcard = deck.pop(0)
  124. random.shuffle(deck)
  125. hand.append(newcard)
  126. iced = False
  127. reloop = True
  128.  
  129. if jaxon:
  130. jaxon = False
  131. if turn <= 3:
  132. if random.random() < 0.3:
  133. jaxon = True
  134. elif turn - iced_turns >= 5:
  135. jaxon = True
  136. if not jaxon:
  137. iced_turns += 0.0625 * random.choice([3,3,3,4])
  138.  
  139. if acolyte_hp > 0:
  140. r = random.random()
  141. if r <= 0.1 or turn > 5: # doesnt sink damage
  142. hand.append(deck.pop())
  143. if acolyte_hp > 3:
  144. hand.append(deck.pop())
  145. acolyte_hp -= random.randint(1, 3)
  146. acolyte_hp -= random.randint(1, 3)
  147. else:
  148. hand.append(deck.pop())
  149. prev_hp = acolyte_hp
  150. if acolyte_hp > 2:
  151. acolyte_hp -= random.choice([1, 2, 3, 3, 3, 4])
  152. if acolyte_hp > 1 or prev_hp > 3:
  153. hand.append(deck.pop())
  154. acolyte_hp -= random.choice([1, 1, 2, 2, 2, 3])
  155. if acolyte_hp > 1:
  156. hand.append(deck.pop())
  157. acolyte_hp -= random.choice([1, 2, 2, 3, 3, 1])
  158. if not enemy_is_spells:
  159. iced_turns += 0.0625 * (prev_hp - acolyte_hp)
  160. if acolyte_hp < 0:
  161. acolyte_hp = 0
  162.  
  163. while reloop:
  164. # print(f"{turn} - {mana} -- {hand}")
  165. reloop = False
  166.  
  167. # check for victory
  168. if "ele" in hand and "sorc" in hand:
  169. temp_mana = mana + hand.count("biscuit") * 2 + min(hand.count("evoc") * 2, 5) + hand.count("reflection-discounted")
  170. temp_mana -= 2 # nerf
  171. temp_mana += hand.count("shivering-played")
  172. if going_second:
  173. temp_mana += 1
  174. if temp_mana >= 7:
  175. temp_mana += hand.count("biscuit-maker") * 1
  176.  
  177. if (temp_mana >= 11 and hand.count("sorc") == 2) or \
  178. (temp_mana >= 8 and "hotstreak" in hand and "reflection" in hand) or \
  179. (temp_mana >= 10 and "reflection" in hand) or \
  180. (temp_mana >= 10 and "sorc_copy" in hand):
  181. fire_in_hand_count = sum([hand.count(x) for x in spells_chandler])
  182. fire_in_hand_count += sum([hand.count(x) for x in spells_chandler_expensive])
  183. fire_in_hand_count -= sum([deck.count(x) for x in spells_nonchandler])
  184. if (temp_mana <= 9 and "hotstreak" not in hand) or (temp_mana <= 11):
  185. fire_in_hand_count -= 1 # reflection too expensive
  186. if fire_in_hand_count >= 1:
  187. success = True
  188. break
  189.  
  190. if temp_mana >= 8:
  191. # try with/find hotstreak
  192. fire_in_hand_count = sum([hand.count(x) for x in spells_chandler])
  193. fire_in_hand_count -= sum([deck.count(x) for x in spells_chandler_expensive])
  194. fire_in_hand_count -= sum([deck.count(x) for x in spells_nonchandler])
  195. fire_in_hand_count += hand.count("hotstreak") # yes this works
  196. if temp_mana >= 9: # ignite is playable
  197. fire_in_hand_count += 1
  198. if temp_mana >= 11: # ignite and reflection is playable too
  199. fire_in_hand_count += 1
  200. if fire_in_hand_count >= 1:
  201. success = True
  202. break
  203.  
  204. # auto-draw cards
  205. if "wonder-card" in hand:
  206. hand.remove("wonder-card")
  207. hand.append(deck.pop())
  208. wonder_counter += 1
  209. reloop = True
  210.  
  211.  
  212. if True:
  213. if "rommath" in hand and mana >= 9:
  214. if "ETC" in hand:
  215. iced_turns += 1
  216. success = True
  217. break
  218. mana -= 6
  219. hand.append("ice")
  220. reloop = True
  221.  
  222.  
  223. if not (iceblock_used and enemy_ignores_secrets) and not iced and "ice" in hand and mana >= 3:
  224. hand.remove("ice")
  225. mana -= 3
  226. iced = True
  227. iceblock_used += 1
  228. if not enemy_ignores_secrets:
  229. iced_turns += 1
  230. reloop = True
  231.  
  232. if (iceblock_used == 0 or ("firstflame" in hand and turn >= 4)) and "ice-search-2mana" in hand and mana >= 2 and "ice" in deck:
  233. hand.remove("ice-search-2mana")
  234. num_tradeables = hand.count("tradeable") + 1
  235. if num_tradeables > mana - 2+1:
  236. num_tradeables = mana-2+1
  237. if deck.count("ice") > 1 or random.random() > num_tradeables/len(deck):
  238. deck.remove("ice")
  239. hand.append("ice")
  240. iceblock_used -= 1
  241. mana += 1
  242. else:
  243. mana -= 2
  244. if turn <= 2 and not enemy_is_spells:
  245. iced_turns += 0.125
  246. random.shuffle(deck)
  247. reloop = True
  248. continue
  249. elif (iceblock_used == 0 or ("firstflame" in hand and turn >= 4)) and "ice-search-2mana-spell" in hand and mana >= 2 and "ice" in deck:
  250. hand.remove("ice-search-2mana-spell")
  251. deck.remove("ice")
  252. hand.append("ice")
  253. mana += 1
  254. random.shuffle(deck)
  255. reloop = True
  256. continue
  257. elif (iceblock_used == 0 or turn >= 4) and not (iceblock_used and enemy_ignores_secrets) and not iced and "ice-search" in hand and mana >= 3 and "ice" in deck:
  258. hand.remove("ice-search")
  259. deck.remove("ice")
  260. if iceblock_used:
  261. deck.append("ice-used")
  262. hand.append("ice")
  263. iceblock_used -= 1
  264. random.shuffle(deck)
  265. reloop = True
  266. continue
  267. if not iced and "ice-discount" in hand and mana >= 2 and "ice" in hand:
  268. hand.remove("ice-discount")
  269. mana += 1
  270. reloop = True
  271. continue
  272.  
  273.  
  274. if enemy_destroys_secrets and "rat" in hand:
  275. enemy_destroys_secrets = random.random() > 1/5
  276. hand.remove("rat")
  277. if enemy_is_reno and "albatross" in hand:
  278. enemy_is_reno = random.random() > 4/5
  279. hand.remove("albatross")
  280. enemy_destroys_secrets = enemy_is_reno and enemy_destroys_secrets
  281.  
  282. # search cards
  283. if "volume" in hand and mana >= 4:
  284. hand.remove("volume")
  285. mana -= 4
  286. volume_used = True
  287. dupecard = None
  288. for x in range(3):
  289. for c in deck:
  290. if c in spells:
  291. hand.append(c)
  292. deck.remove(c)
  293. if c == "evoc":
  294. dupecard = "evoc"
  295. if c == "ice" and not dupecard:
  296. dupecard = "ice"
  297. break
  298. if dupecard:
  299. hand.append(dupecard)
  300.  
  301. if "shivering" in hand and mana >= 1 and (turn <= 2):
  302. hand.remove("shivering")
  303. hand.append("shivering-played")
  304. mana -= 1
  305. if turn <= 2 and not enemy_is_spells:
  306. iced_turns += 0.25
  307. if turn == 1 and not enemy_is_spells:
  308. iced_turns += 0.25
  309. if enemy_is_rattable and "rat" in hand and mana >= 2:
  310. success = True
  311. break
  312. if "magister" in hand and iced_turns >= 0.5 and (mana >= 7 or ("biscuit" in hand and mana >= 5)):
  313. hand.remove("magister")
  314. mana -= 4
  315. if "biscuit" in hand:
  316. mana += 2
  317. elif "biscuit-maker" in hand:
  318. hand.remove("biscuit-maker")
  319. hand.append("biscuit")
  320. hand.append("generic-fire")
  321. hand.append("ice")
  322. if volume_used:
  323. hand.append("volume")
  324. mana += 4
  325. reloop = True
  326. continue
  327. if "magister" in hand and iced_turns >= 0.5 and (mana >= 7 or ("biscuit" in hand and mana >= 5)):
  328. hand.remove("sivara")
  329. mana -= 4
  330. hand.append("ice")
  331. reloop = True
  332. continue
  333.  
  334. if (not enemy_is_spells) and "varden" in hand and mana >= 4:
  335. hand.remove("varden")
  336. mana -= 4
  337. iced_turns += 1
  338. if (not enemy_is_spells) and "firesale" in hand and mana >= 4:
  339. hand.remove("firesale")
  340. mana -= 4
  341. success = True
  342. break
  343. if enemy_is_spells and "loatheb" in hand and mana >= 5:
  344. hand.remove("loatheb")
  345. mana -= 5
  346. if random.random() > 0.2:
  347. iced_turns += 1
  348. if "springwater" in hand and mana >= 5:
  349. hand.remove("springwater")
  350. mana -= 4
  351. newcard = deck.pop()
  352. hand.append(newcard)
  353. if newcard in spells:
  354. mana += 2
  355. newcard = deck.pop()
  356. hand.append(newcard)
  357. if newcard in spells:
  358. mana += 2
  359. random.shuffle(deck)
  360. reloop = True
  361. if "ele-search" in hand and mana >= 4 and "ele" not in hand:
  362. hand.remove("ele-search")
  363. mana -= 4
  364. deck.remove("ele")
  365. hand.append("ele")
  366. random.shuffle(deck)
  367. if "sorc-search" in hand and mana >= 4 and "sorc" not in hand:
  368. hand.remove("sorc-search")
  369. mana -= 4
  370. deck.remove("sorc")
  371. hand.append("sorc")
  372. random.shuffle(deck)
  373. if "2manadraw1" in hand and mana >= 2:
  374. hand.remove("2manadraw1")
  375. mana -= 2
  376. hand.append(deck.pop())
  377. random.shuffle(deck)
  378. reloop = True
  379. if "3manadraw2" in hand and mana >= 3:
  380. hand.remove("3manadraw2")
  381. mana -= 3
  382. hand.append(deck.pop())
  383. hand.append(deck.pop())
  384. random.shuffle(deck)
  385. if "acolyte" in hand and mana >= 3:
  386. hand.remove("acolyte")
  387. mana -= 3
  388. acolyte_hp += 3
  389. random.shuffle(deck)
  390. if "spicebaker" in hand and mana >= 4:
  391. hand.remove("spicebaker")
  392. mana -= 4
  393. iced_turns += 0.5
  394. random.shuffle(deck)
  395. if "6manadraw6" in hand and mana >= 6:
  396. hand.remove("6manadraw6")
  397. mana -= 6
  398. hand.append(deck.pop())
  399. hand.append(deck.pop())
  400. hand.append(deck.pop())
  401. hand.append(deck.pop())
  402. hand.append(deck.pop())
  403. hand.append(deck.pop())
  404. random.shuffle(deck)
  405. if "3manaspellsearch" in hand and mana >= 3:
  406. hand.remove("3manaspellsearch")
  407. mana -= 3
  408. newcard = deck.pop(0)
  409. tries = 0
  410. while newcard not in spells:
  411. tries += 1
  412. deck.append(newcard)
  413. if tries > 80:
  414. break
  415. newcard = deck.pop(0)
  416. hand.append(newcard)
  417. random.shuffle(deck)
  418. if newcard == "ice":
  419. iced_turns += 0.5
  420. reloop = True
  421. if "2manaspellsearch" in hand and mana >= 2:
  422. hand.remove("2manaspellsearch")
  423. mana -= 2
  424. newcard = deck.pop(0)
  425. tries = 0
  426. while newcard not in spells:
  427. tries += 1
  428. deck.append(newcard)
  429. if tries > 80:
  430. break
  431. newcard = deck.pop(0)
  432. if newcard in spells:
  433. hand.append(newcard)
  434. random.shuffle(deck)
  435. reloop = True
  436. if "4manaspellsearch" in hand and mana >= 4:
  437. hand.remove("4manaspellsearch")
  438. mana -= 4
  439. newcard = deck.pop(0)
  440. tries = 0
  441. while newcard not in spells:
  442. tries += 1
  443. deck.append(newcard)
  444. if tries > 50:
  445. break
  446. newcard = deck.pop(0)
  447. if newcard in spells:
  448. hand.append(newcard)
  449. random.shuffle(deck)
  450. if "3manadraw2" in hand and mana >= 3:
  451. hand.remove("3manadraw2")
  452. mana -= 3
  453. newcard = deck.pop(0)
  454. hand.append(newcard)
  455. random.shuffle(deck)
  456. reloop = True
  457. if "sapience" in hand and mana >= 1:
  458. hand.remove("sapience")
  459. mana -= 1
  460. sapience = True
  461. if "biscuit-maker" in hand and mana >= 2:
  462. hand.remove("biscuit-maker")
  463. mana -= 2
  464. hand.append("biscuit")
  465. if "wonder-deck" in hand and mana >= 5:
  466. hand.remove("wonder-deck")
  467. mana -= 5
  468. deck.append("wonder-card")
  469. deck.append("wonder-card")
  470. deck.append("wonder-card")
  471. deck.append("wonder-card")
  472. deck.append("wonder-card")
  473. random.shuffle(deck)
  474.  
  475. if "jaxon" in hand and mana >= 3 and hand.count("tradeable") >= 1:
  476. hand.remove("jaxon")
  477. mana -= 2
  478. jaxon = True
  479.  
  480. if "tradeable" in hand and mana > 0:
  481. hand.remove("tradeable")
  482. mana -= 1
  483. if jaxon:
  484. jaxon_discover = [deck[0], deck[1], deck[2]]
  485. if "ele" in jaxon_discover and "ele" not in hand:
  486. newcard = "ele"
  487. elif "sorc" in jaxon_discover and "sorc" not in hand:
  488. newcard = "sorc"
  489. elif "ice-search" in jaxon_discover and "ice" in deck and "ice-search" not in hand:
  490. newcard = "ice-search"
  491. elif "ice" in jaxon_discover and "ice-search" not in hand:
  492. newcard = "ice"
  493. elif "evoc" in jaxon_discover:
  494. newcard = "evoc"
  495. elif "tradeable" in jaxon_discover and mana >= 1:
  496. newcard = "tradeable"
  497. else:
  498. newcard = jaxon_discover[0]
  499. deck.remove(newcard)
  500. else:
  501. newcard = deck.pop(0)
  502. hand.append(newcard)
  503. deck.append("tradeable")
  504. random.shuffle(deck)
  505. reloop = True
  506.  
  507. if "firesale" in hand and mana > 0:
  508. hand.remove("firesale")
  509. mana -= 1
  510. newcard = deck.pop(0)
  511. hand.append(newcard)
  512. deck.append("firesale")
  513. random.shuffle(deck)
  514. reloop = True
  515.  
  516. if reloop is False:
  517. if acolyte_hp > 0 and mana >= 2:
  518. acolyte_hp -= 1
  519. hand.append(deck.pop())
  520.  
  521. if "shivering" in hand and mana >= 1 and ("reflection" in hand or "ignite" in hand):
  522. hand.remove("shivering")
  523. if "reflection" in hand:
  524. hand.append("reflection-discount")
  525. elif "ice" in hand:
  526. hand.append("ice-discount")
  527. elif "ignite" in hand:
  528. hand.remove("ignite")
  529. hand.append("generic-fire")
  530. mana -= 1
  531. if turn <= 2 and not enemy_is_spells:
  532. iced_turns += 0.25
  533. if turn == 1 and not enemy_is_spells:
  534. iced_turns += 0.25
  535. if hand.count("ele") > 1 and mana >= 5:
  536. hand.remove("ele")
  537. mana -= 5
  538. if turn <= 6:
  539. iced_turns += 0.3125
  540. reloop = True
  541. if "sorc-search" in hand and mana >= 4 and "sorc" not in deck:
  542. hand.remove("sorc-search")
  543. mana -= 4
  544. deck.remove("tradeable")
  545. hand.append("tradeable")
  546. random.shuffle(deck)
  547. reloop = True
  548. if "ele-search" in hand and mana >= 4 and "ele" in deck:
  549. # second search
  550. hand.remove("ele-search")
  551. mana -= 4
  552. deck.remove("ele")
  553. hand.append("ele")
  554. random.shuffle(deck)
  555. reloop = True
  556.  
  557. if iceblock_used > 0 and "rewind" in hand and mana >= 2:
  558. hand.remove("rewind")
  559. mana -= 2
  560. hand.append("ice")
  561. reloop = True
  562.  
  563. if success:
  564. if enemy_destroys_secrets:
  565. iced_turns = 0
  566. turns_taken.append(turn - iced_turns)
  567. break
  568.  
  569. win_by_5 = 0
  570. for t in turns_taken:
  571. if t <= 5:
  572. win_by_5 += 1
  573. print("Chance to win if survived to turn 5: ", win_by_5 / len(turns_taken), " - Average turns: ", sum(turns_taken) / len(turns_taken))
  574.  
Advertisement
Add Comment
Please, Sign In to add comment