Advertisement
Guest User

Nadu Sim

a guest
Jul 3rd, 2024
299
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.38 KB | None | 0 0
  1. import random
  2.  
  3. DECK = ["fetch"]*7 + ["arbor"] + ["khalni"]*3 + ["woodland"]*1 + ["ug"]*2 + ["g"]*3 + ["u"] + ["yavimaya"] + ["saga"]*4 + ["tapland"] \
  4. + ["nadu"]*4 + ["nantuko"]*4 + ["chord"]*4 + ["1-drop"]*8 + ["drum"] + ["endurance"]*2 + ["shuko"]*3 + ["ring"] + ["chat"] + ["venser"] + ["outrider"] + ["stormdrake"]*2 + ["mumble"]*4
  5. LANDS = ["fetch", "arbor", "khalni", "woodland", "ug", "g", "u", "yavimaya", "saga", "tapland"]
  6. GREEN_CARDS = ["arbor", "nadu", "chord", "endurance", "mumble", "1-drop", "nantuko"]
  7. ITER = 1000000
  8. PRINT_ITER = 10
  9. INIT_HAND = 4
  10. INIT_CREATURES = 3
  11. INIT_LANDS = [] # type: ignore[var-annotated]
  12. INIT_REMOVE = ["nadu", "shuko", "saga", "ug", "fetch", "g", "ring"]
  13.  
  14. class Iteration:
  15. nantuko: int
  16. triggers: int
  17. creatures: int
  18. untapped: int
  19. yavimaya: bool
  20. lands: list[str]
  21.  
  22. deck: list[str]
  23. hand: list[str]
  24.  
  25. def __init__(self, init_creatures, init_hand, init_lands, init_remove):
  26. self.nantuko = 1
  27. self.triggers = 2*init_creatures
  28. self.creatures = init_creatures
  29. self.untapped = init_creatures
  30. self.yavimaya = False
  31. self.lands = init_lands.copy()
  32.  
  33. self.deck = DECK.copy()
  34. for r in init_remove:
  35. self.deck.remove(r)
  36.  
  37. random.shuffle(self.deck)
  38. self.hand = []
  39.  
  40. for h in range(init_hand):
  41. self.hand.append(self.deck.pop())
  42. if ITER <= PRINT_ITER:
  43. print(self.hand)
  44.  
  45. def add_creature(self):
  46. self.triggers += 2
  47. self.creatures += 1
  48. self.untapped += 1
  49. if ITER <= PRINT_ITER:
  50. print("ADDED CREATURE")
  51.  
  52. def trigger_landfall(self):
  53. self.triggers += self.nantuko*2
  54. self.creatures += self.nantuko
  55. self.untapped += self.nantuko
  56.  
  57. def reset_nadu(self):
  58. self.triggers = self.creatures * 2
  59.  
  60. def resolve_nadu_trigger(self):
  61. # do a trigger
  62. self.triggers -= 1
  63. card = self.deck.pop()
  64. if ITER <= PRINT_ITER:
  65. print(card)
  66. if card in LANDS:
  67. self.trigger_landfall()
  68. if card == "arbor" or card == "khalni":
  69. self.add_creature()
  70. if card != "tapland" and card != "khalni":
  71. self.lands.append(card)
  72. else:
  73. self.hand.append(card)
  74.  
  75. def try_cast_chord(self, n):
  76. if "chord" not in self.hand:
  77. return False
  78.  
  79. can_cast = False
  80. if self.untapped < 3:
  81. if self.try_cast_spell("chord", n, 3-self.untapped, 0, cast=False):
  82. self.untapped = 0
  83. can_cast = True
  84. elif self.untapped <= 3+n:
  85. if self.try_cast_spell("chord", 3+n-self.untapped, 0, 0, cast=False):
  86. self.untapped = 0
  87. can_cast = True
  88. else:
  89. if self.try_cast_spell("chord", 0, 0, 0, cast=False):
  90. self.untapped -= 3+n
  91. can_cast = True
  92.  
  93. if not can_cast and "endurance" in self.hand:
  94. temp_hand = self.hand.copy()
  95. temp_hand.remove("chord")
  96. temp_hand.remove("endurance")
  97.  
  98. pitched = False
  99. for g in GREEN_CARDS:
  100. if g in temp_hand:
  101. temp_hand.remove(g)
  102. pitched = True
  103. break
  104.  
  105. if not pitched:
  106. return False
  107. temp_hand.append("chord")
  108.  
  109. if self.untapped < 2:
  110. if self.try_cast_spell("chord", n, 2-self.untapped, 0, cast=False):
  111. self.untapped = 0
  112. can_cast = True
  113. elif self.untapped <= 2+n:
  114. if self.try_cast_spell("chord", 2+n-self.untapped, 0, 0, cast=False):
  115. self.untapped = 0
  116. can_cast = True
  117. else:
  118. if self.try_cast_spell("chord", 0, 0, 0, cast=False):
  119. self.untapped -= 2+n
  120. can_cast = True
  121.  
  122. if can_cast:
  123. if ITER <= PRINT_ITER:
  124. print("ACTION: pitching endurance")
  125. self.hand = temp_hand
  126. self.untapped += 1
  127.  
  128. if can_cast:
  129. if ITER <= PRINT_ITER:
  130. print("ACTION: chording for", n)
  131.  
  132. if self.untapped < 3+n and "fetch" in self.lands and "arbor" in self.deck:
  133. self.lands.remove("fetch")
  134. self.trigger_landfall()
  135. self.add_creature()
  136.  
  137. while self.untapped < 3+n and "1-drop" in self.hand and self.try_cast_spell("1-drop", 0, 1, 0):
  138. self.add_creature()
  139.  
  140. if self.untapped < 3:
  141. if self.try_cast_spell("chord", n, 3-self.untapped, 0):
  142. self.untapped = 0
  143. elif self.untapped <= 3+n:
  144. if self.try_cast_spell("chord", 3+n-self.untapped, 0, 0):
  145. self.untapped = 0
  146. else:
  147. if self.try_cast_spell("chord", 0, 0, 0):
  148. self.untapped -= 3+n
  149. return True
  150. return False
  151.  
  152. def try_cast_spell(self, name, c_cost, g_cost, u_cost, cast=True):
  153. if name not in self.hand:
  154. return False
  155.  
  156. temp = self.lands.copy()
  157. temp_deck = self.deck.copy()
  158. num_fetched = 0
  159.  
  160. if u_cost > 0:
  161. if "u" in temp:
  162. temp.remove("u")
  163. elif "ug" in temp:
  164. temp.remove("ug")
  165. elif "fetch" in temp and "u" in temp_deck:
  166. temp.remove("fetch")
  167. temp_deck.remove("u")
  168. num_fetched += 1
  169. elif "fetch" in temp and "ug" in temp_deck:
  170. temp.remove("fetch")
  171. temp_deck.remove("ug")
  172. num_fetched += 1
  173. else:
  174. return False
  175.  
  176. if self.yavimaya:
  177. c_cost += g_cost
  178. g_cost = 0
  179.  
  180. for g in range(g_cost):
  181. if "g" in temp:
  182. temp.remove("g")
  183. elif "woodland" in temp:
  184. temp.remove("woodland")
  185. elif "yavimaya" in temp:
  186. temp.remove("yavimaya")
  187. elif "ug" in temp:
  188. temp.remove("ug")
  189. elif "fetch" in temp and "g" in temp_deck:
  190. temp.remove("fetch")
  191. temp_deck.remove("g")
  192. num_fetched += 1
  193. elif "fetch" in temp and "ug" in temp_deck:
  194. temp.remove("fetch")
  195. temp_deck.remove("ug")
  196. num_fetched += 1
  197. else:
  198. return False
  199.  
  200. for c in range(c_cost):
  201. if "saga" in temp:
  202. temp.remove("saga")
  203. elif "g" in temp:
  204. temp.remove("g")
  205. elif "woodland" in temp:
  206. temp.remove("woodland")
  207. elif "yavimaya" in temp:
  208. temp.remove("yavimaya")
  209. elif "fetch" in temp and self.yavimaya:
  210. temp.remove("fetch")
  211. elif "u" in temp:
  212. temp.remove("u")
  213. elif "ug" in temp:
  214. temp.remove("ug")
  215. elif "fetch" in temp and "g" in temp_deck:
  216. temp.remove("fetch")
  217. temp_deck.remove("g")
  218. elif "fetch" in temp and "u" in temp_deck:
  219. temp.remove("fetch")
  220. temp_deck.remove("u")
  221. num_fetched += 1
  222. elif "fetch" in temp and "ug" in temp_deck:
  223. temp.remove("fetch")
  224. temp_deck.remove("ug")
  225. num_fetched += 1
  226. else:
  227. return False
  228.  
  229. if cast:
  230. self.lands = temp
  231. self.deck = temp_deck
  232. for i in range(num_fetched):
  233. self.trigger_landfall()
  234.  
  235. self.hand.remove(name)
  236. if ITER <= PRINT_ITER:
  237. print("ACTION: cast", name)
  238.  
  239. return True
  240.  
  241. def log(self):
  242. if ITER <= PRINT_ITER:
  243. print("remaining deck:", len(self.deck))
  244. print("hand:", self.hand)
  245. print("lands:", self.lands)
  246. print("nantukos:", self.nantuko)
  247. print("untapped:", self.untapped)
  248.  
  249.  
  250. success = 0
  251. for it in range(ITER):
  252. i = Iteration(INIT_CREATURES, INIT_HAND, INIT_LANDS, INIT_REMOVE)
  253.  
  254. while i.triggers > 0 and len(i.deck) > 0:
  255. i.resolve_nadu_trigger()
  256.  
  257. # try generate more triggers
  258. if i.triggers == 0:
  259. # try play nadu
  260. if i.try_cast_spell("nadu", 1, 1, 1):
  261. i.reset_nadu()
  262.  
  263. # try chord for nadu
  264. if "nadu" in i.deck and i.try_cast_chord(3):
  265. i.deck.remove("nadu")
  266. i.reset_nadu()
  267.  
  268. # try play nantuko
  269. if i.try_cast_spell("nantuko", 1, 1, 0):
  270. i.nantuko += 1
  271. i.add_creature()
  272.  
  273. # try chord for nantuko
  274. if "nantuko" in i.deck and i.try_cast_chord(2):
  275. i.deck.remove("nantuko")
  276. i.nantuko += 1
  277. i.add_creature()
  278.  
  279. if i.triggers != 0:
  280. continue
  281.  
  282. # try fetch arbor
  283. if "fetch" in i.lands and "arbor" in i.deck:
  284. if ITER <= PRINT_ITER:
  285. print("ACTION: fetch arbor")
  286. i.deck.remove("arbor")
  287. i.lands.remove("fetch")
  288. i.add_creature()
  289. i.trigger_landfall()
  290. continue
  291.  
  292. # try cast 1-drop
  293. if i.try_cast_spell("1-drop", 0, 1, 0):
  294. i.add_creature()
  295. continue
  296.  
  297. # try cast mumble
  298. if i.try_cast_spell("mumble", 1, 1, 0):
  299. i.add_creature()
  300. i.lands.append("saga")
  301.  
  302. # TODO: SELECTION
  303.  
  304. continue
  305.  
  306. # try cast stormdrake
  307. if i.try_cast_spell("stormdrake", 1, 0, 1):
  308. i.add_creature()
  309. continue
  310.  
  311. # try chord for arbor
  312. if "arbor" in i.deck and i.try_cast_chord(0):
  313. i.deck.remove("arbor")
  314. i.add_creature()
  315. continue
  316.  
  317. # try chord for 1
  318. if "1-drop" in i.deck and i.try_cast_chord(1):
  319. i.deck.remove("1-drop")
  320. i.add_creature()
  321. continue
  322.  
  323. # try cast endurance
  324. if i.try_cast_spell("endurance", 1, 2, 0):
  325. i.add_creature()
  326. continue
  327.  
  328. # try cast outrider
  329. if i.try_cast_spell("outrider", 2, 0, 1):
  330. i.add_creature()
  331. continue
  332.  
  333. # try cast venser
  334. if i.try_cast_spell("venser", 2, 0, 2):
  335. i.add_creature()
  336. continue
  337.  
  338.  
  339.  
  340.  
  341. if len(i.deck) == 0:
  342. success += 1
  343. if ITER <= PRINT_ITER:
  344. print("SUCCESS")
  345. else:
  346. i.log()
  347.  
  348. print(success / ITER)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement