· 9 years ago · Nov 13, 2016, 04:26 PM
1from operator import attrgetter
2import operator
3import random
4from time import ctime
5import copy
6import sqlite3
7import math
8
9class Simulator(object):
10 """Simulator object, contains information on the game"""
11 def __init__(self):
12 """Simulator constructor. Contains game specific information"""
13 #Number of games to run per deck
14 self.simulationLength = 1000
15 #Current turn of the game
16 self.turn = 0
17 #True/false if P1 goes first
18 self.goFirst = 1
19 #Number of Lavamancer activations in a turn
20 self.lavaAct = 0
21 #Deck ID default value for database
22 self.deckID = 0
23 #True/False toggle to print game info to console
24 self.debugmsg = 0
25 #Turn on hand logging (very slow)
26 self.draw = 0
27 #Sets who goes first
28 if self.goFirst == 1:
29 self.curPlayer = P1()
30 self.nAP = P2()
31 self.activePlayer = self.curPlayer.deckName
32 if self.goFirst != 1:
33 self.curPlayer = P2()
34 self.nAP = P1()
35 self.activePlayer = self.curPlayer.deckName
36
37 def switchPlayers(self):
38 """Switch active/non active players"""
39 temp = self.curPlayer
40 self.curPlayer = self.nAP
41 self.nAP = temp
42 self.activePlayer = self.curPlayer.deckName
43 msg = "Active player is " + self.curPlayer.deckName
44 self.debug(msg)
45
46 def setParams(self):
47 """Main loop"""
48 self.buildDB()
49 self.playGames()
50 #Quick and dirty way to que several decks to be played in a batch
51#18 Land, Birds
52 sim.curPlayer.fetchCount = 0
53 sim.curPlayer.landCount = 0
54 sim.curPlayer.ringCount = 0
55 sim.curPlayer.ForgottenCaveCount = 0
56 sim.curPlayer.eidolonCount = 0
57 sim.curPlayer.hellsparkCount = 0
58 sim.curPlayer.swiftspearCount = 0
59 sim.curPlayer.guideCount = 0
60 sim.curPlayer.marauderCount = 0
61 sim.curPlayer.vexingCount = 0
62 sim.curPlayer.riftCount = 0
63 sim.curPlayer.fireblastCount = 0
64 sim.curPlayer.atarkaCount = 0
65 sim.curPlayer.incinerateCount = 0
66 sim.curPlayer.boltCount = 0
67 sim.curPlayer.chainCount = 0
68 sim.curPlayer.firecraftCount = 0
69 sim.curPlayer.vortexCount = 0
70 sim.curPlayer.lavamancerCount = 0
71 sim.curPlayer.serumCount = 0
72 sim.curPlayer.searingCount = 0
73 sim.curPlayer.nacatlCount = 0
74 sim.curPlayer.berserkerCount = 0
75 sim.curPlayer.birdsCount = 0
76 sim.curPlayer.sakuraCount = 0
77 sim.curPlayer.explorerCount = 0
78 sim.curPlayer.truthsCount = 0
79 sim.curPlayer.sigardaCount = 0
80 sim.curPlayer.landCount = 18
81 sim.curPlayer.birdsCount = 4
82 sim.curPlayer.explorerCount = 4
83 sim.curPlayer.sakuraCount = 2
84 sim.curPlayer.truthsCount = 24
85 sim.curPlayer.sigardaCount = 8
86 self.playGames()
87
88#22 Land, No Birds
89 sim.curPlayer.fetchCount = 0
90 sim.curPlayer.landCount = 0
91 sim.curPlayer.ringCount = 0
92 sim.curPlayer.ForgottenCaveCount = 0
93 sim.curPlayer.eidolonCount = 0
94 sim.curPlayer.hellsparkCount = 0
95 sim.curPlayer.swiftspearCount = 0
96 sim.curPlayer.guideCount = 0
97 sim.curPlayer.marauderCount = 0
98 sim.curPlayer.vexingCount = 0
99 sim.curPlayer.riftCount = 0
100 sim.curPlayer.fireblastCount = 0
101 sim.curPlayer.atarkaCount = 0
102 sim.curPlayer.incinerateCount = 0
103 sim.curPlayer.boltCount = 0
104 sim.curPlayer.chainCount = 0
105 sim.curPlayer.firecraftCount = 0
106 sim.curPlayer.vortexCount = 0
107 sim.curPlayer.lavamancerCount = 0
108 sim.curPlayer.serumCount = 0
109 sim.curPlayer.searingCount = 0
110 sim.curPlayer.nacatlCount = 0
111 sim.curPlayer.berserkerCount = 0
112 sim.curPlayer.birdsCount = 0
113 sim.curPlayer.sakuraCount = 0
114 sim.curPlayer.explorerCount = 0
115 sim.curPlayer.truthsCount = 0
116 sim.curPlayer.sigardaCount = 0
117 sim.curPlayer.landCount = 22
118 sim.curPlayer.birdsCount = 0
119 sim.curPlayer.explorerCount = 0
120 sim.curPlayer.sakuraCount = 0
121 sim.curPlayer.truthsCount = 30
122 sim.curPlayer.sigardaCount = 8
123 self.playGames()
124
125#22 Land, Birds
126 sim.curPlayer.fetchCount = 0
127 sim.curPlayer.landCount = 0
128 sim.curPlayer.ringCount = 0
129 sim.curPlayer.ForgottenCaveCount = 0
130 sim.curPlayer.eidolonCount = 0
131 sim.curPlayer.hellsparkCount = 0
132 sim.curPlayer.swiftspearCount = 0
133 sim.curPlayer.guideCount = 0
134 sim.curPlayer.marauderCount = 0
135 sim.curPlayer.vexingCount = 0
136 sim.curPlayer.riftCount = 0
137 sim.curPlayer.fireblastCount = 0
138 sim.curPlayer.atarkaCount = 0
139 sim.curPlayer.incinerateCount = 0
140 sim.curPlayer.boltCount = 0
141 sim.curPlayer.chainCount = 0
142 sim.curPlayer.firecraftCount = 0
143 sim.curPlayer.vortexCount = 0
144 sim.curPlayer.lavamancerCount = 0
145 sim.curPlayer.serumCount = 0
146 sim.curPlayer.searingCount = 0
147 sim.curPlayer.nacatlCount = 0
148 sim.curPlayer.berserkerCount = 0
149 sim.curPlayer.birdsCount = 0
150 sim.curPlayer.sakuraCount = 0
151 sim.curPlayer.explorerCount = 0
152 sim.curPlayer.truthsCount = 0
153 sim.curPlayer.sigardaCount = 0
154 sim.curPlayer.landCount = 22
155 sim.curPlayer.birdsCount = 4
156 sim.curPlayer.explorerCount = 4
157 sim.curPlayer.sakuraCount = 2
158 sim.curPlayer.truthsCount = 20
159 sim.curPlayer.sigardaCount = 8
160 self.playGames()
161
162#26 Land, no Birds
163 sim.curPlayer.fetchCount = 0
164 sim.curPlayer.landCount = 0
165 sim.curPlayer.ringCount = 0
166 sim.curPlayer.ForgottenCaveCount = 0
167 sim.curPlayer.eidolonCount = 0
168 sim.curPlayer.hellsparkCount = 0
169 sim.curPlayer.swiftspearCount = 0
170 sim.curPlayer.guideCount = 0
171 sim.curPlayer.marauderCount = 0
172 sim.curPlayer.vexingCount = 0
173 sim.curPlayer.riftCount = 0
174 sim.curPlayer.fireblastCount = 0
175 sim.curPlayer.atarkaCount = 0
176 sim.curPlayer.incinerateCount = 0
177 sim.curPlayer.boltCount = 0
178 sim.curPlayer.chainCount = 0
179 sim.curPlayer.firecraftCount = 0
180 sim.curPlayer.vortexCount = 0
181 sim.curPlayer.lavamancerCount = 0
182 sim.curPlayer.serumCount = 0
183 sim.curPlayer.searingCount = 0
184 sim.curPlayer.nacatlCount = 0
185 sim.curPlayer.berserkerCount = 0
186 sim.curPlayer.birdsCount = 0
187 sim.curPlayer.sakuraCount = 0
188 sim.curPlayer.explorerCount = 0
189 sim.curPlayer.truthsCount = 0
190 sim.curPlayer.sigardaCount = 0
191 sim.curPlayer.landCount = 26
192 sim.curPlayer.birdsCount = 0
193 sim.curPlayer.explorerCount = 0
194 sim.curPlayer.sakuraCount = 0
195 sim.curPlayer.truthsCount = 26
196 sim.curPlayer.sigardaCount = 8
197 self.playGames()
198
199#26 Land, Birds
200 sim.curPlayer.fetchCount = 0
201 sim.curPlayer.landCount = 0
202 sim.curPlayer.ringCount = 0
203 sim.curPlayer.ForgottenCaveCount = 0
204 sim.curPlayer.eidolonCount = 0
205 sim.curPlayer.hellsparkCount = 0
206 sim.curPlayer.swiftspearCount = 0
207 sim.curPlayer.guideCount = 0
208 sim.curPlayer.marauderCount = 0
209 sim.curPlayer.vexingCount = 0
210 sim.curPlayer.riftCount = 0
211 sim.curPlayer.fireblastCount = 0
212 sim.curPlayer.atarkaCount = 0
213 sim.curPlayer.incinerateCount = 0
214 sim.curPlayer.boltCount = 0
215 sim.curPlayer.chainCount = 0
216 sim.curPlayer.firecraftCount = 0
217 sim.curPlayer.vortexCount = 0
218 sim.curPlayer.lavamancerCount = 0
219 sim.curPlayer.serumCount = 0
220 sim.curPlayer.searingCount = 0
221 sim.curPlayer.nacatlCount = 0
222 sim.curPlayer.berserkerCount = 0
223 sim.curPlayer.birdsCount = 0
224 sim.curPlayer.sakuraCount = 0
225 sim.curPlayer.explorerCount = 0
226 sim.curPlayer.truthsCount = 0
227 sim.curPlayer.sigardaCount = 0
228 sim.curPlayer.landCount = 26
229 sim.curPlayer.birdsCount = 4
230 sim.curPlayer.explorerCount = 4
231 sim.curPlayer.sakuraCount = 2
232 sim.curPlayer.truthsCount = 16
233 sim.curPlayer.sigardaCount = 8
234 self.playGames()
235
236
237 def buildDB(self):
238 """Builds the database"""
239 self.debug("Begin building Database...")
240 conn = sqlite3.connect('burn.db')
241 c = conn.cursor()
242 #Build deck table, contains deck id and deck configuration
243 self.debug("Building Deck table...")
244 #c.execute('''DROP TABLE tableDeck''')
245 c.execute('''CREATE TABLE IF NOT EXISTS tableDeck
246 (deckID INTEGER PRIMARY KEY AUTOINCREMENT,
247 fetch INTEGER NOT NULL,
248 land INTEGER NOT NULL,
249 cave INTEGER NOT NULL,
250 eidolon INTEGER NOT NULL,
251 hellspark INTEGER NOT NULL,
252 swiftspear INTEGER NOT NULL,
253 guide INTEGER NOT NULL,
254 marauder INTEGER NOT NULL,
255 vexing INTEGER NOT NULL,
256 rift INTEGER NOT NULL,
257 fireblast INTEGER NOT NULL,
258 atarka INTEGER NOT NULL,
259 incinerate INTEGER NOT NULL,
260 bolt INTEGER NOT NULL,
261 jet INTEGER NOT NULL,
262 top INTEGER NOT NULL,
263 probe INTEGER NOT NULL,
264 firecraft INTEGER NOT NULL,
265 lavamancer INTEGER NOT NULL,
266 ring INTEGER NOT NULL,
267 vortex INTEGER NOT NULL,
268 serum INTEGER NOT NULL,
269 chain INTEGER NOT NULL,
270 searingblaze INTEGER NOT NULL,
271 berserker INTEGER NOT NULL,
272 nacatl INTEGER NOT NULL,
273 birds INTEGER NOT NULL,
274 explorer INTEGER NOT NULL,
275 sakura INTEGER NOT NULL,
276 sigarda INTEGER NOT NULL,
277 truths INTEGER NOT NULL)''')
278
279 conn.commit()
280 conn.close()
281 #Build games table, contains game info, associated deck
282 conn = sqlite3.connect('burn.db')
283 c = conn.cursor()
284 self.debug("Building Games table...")
285 #c.execute('''DROP TABLE tableGames''')
286 c.execute('''CREATE TABLE IF NOT EXISTS tableGames
287 (gameID INTEGER PRIMARY KEY AUTOINCREMENT,
288 deckID INTEGER NOT NULL,
289 mulligansTaken INTEGER,
290 mulliganNoLand INTEGER,
291 mulliganAllLand INTEGER,
292 mulliganNoCreatures INTEGER,
293 maxTurns INTEGER,
294 FOREIGN KEY(deckID) REFERENCES tableDeck(deckID))''')
295 conn.commit()
296 conn.close()
297 #Build turns table, links turn to game, records turn info
298 conn = sqlite3.connect('burn.db')
299 c = conn.cursor()
300 self.debug("Building Turns table...")
301 #c.execute('''DROP TABLE tableTurns''')
302 c.execute('''CREATE TABLE IF NOT EXISTS tableTurns
303 (turnID INTEGER PRIMARY KEY AUTOINCREMENT,
304 gameID INTEGER NOT NULL,
305 myLife INTEGER,
306 opponentLife INTEGER,
307 maxMana INTEGER,
308 prowess INTEGER,
309 turnNum INTEGER,
310 lavaact INTEGER,
311 opplife INTEGER,
312 FOREIGN KEY(gameID) REFERENCES tableGames(gameID))''')
313 conn.commit()
314 conn.close()
315 #Build hand table, links hand to turnID, contains hand info
316 conn = sqlite3.connect('burn.db')
317 c = conn.cursor()
318
319 self.debug("Building hand table...")
320 #c.execute('''DROP TABLE tableHand''')
321 c.execute('''CREATE TABLE IF NOT EXISTS tableHand
322 (handID INTEGER PRIMARY KEY AUTOINCREMENT,
323 turnID INTEGER NOT NULL,
324 fetch INTEGER NOT NULL,
325 land INTEGER NOT NULL,
326 cave INTEGER NOT NULL,
327 eidolon INTEGER NOT NULL,
328 hellspark INTEGER NOT NULL,
329 swiftspear INTEGER NOT NULL,
330 guide INTEGER NOT NULL,
331 marauder INTEGER NOT NULL,
332 vexing INTEGER NOT NULL,
333 rift INTEGER NOT NULL,
334 fireblast INTEGER NOT NULL,
335 atarka INTEGER NOT NULL,
336 incinerate INTEGER NOT NULL,
337 bolt INTEGER NOT NULL,
338 jet INTEGER NOT NULL,
339 top INTEGER NOT NULL,
340 probe INTEGER NOT NULL,
341 firecraft INTEGER NOT NULL,
342 lavamancer INTEGER NOT NULL,
343 ring INTEGER NOT NULL,
344 vortex INTEGER NOT NULL,
345 serum INTEGER NOT NULL,
346 chain INTEGER NOT NULL,
347 searingblaze INTEGER NOT NULL,
348 berserker INTEGER NOT NULL,
349 nacatl INTEGER NOT NULL,
350 birds INTEGER NOT NULL,
351 explorer INTEGER NOT NULL,
352 sakura INTEGER NOT NULL,
353 truths INTEGER NOT NULL,
354 sigarda INTEGER NOT NULL,
355 FOREIGN KEY(turnID) REFERENCES tableGames(turnID))''')
356 conn.commit()
357 conn.close()
358 #Build board table, links board to turnID, contains board info
359 conn = sqlite3.connect('burn.db')
360 c = conn.cursor()
361
362 self.debug("Building board table")
363 #c.execute('''DROP TABLE tableBoard''')
364 c.execute('''CREATE TABLE IF NOT EXISTS tableBoard
365 (boardID INTEGER PRIMARY KEY AUTOINCREMENT,
366 turnID INTEGER NOT NULL,
367 fetch INTEGER NOT NULL,
368 land INTEGER NOT NULL,
369 cave INTEGER NOT NULL,
370 eidolon INTEGER NOT NULL,
371 hellspark INTEGER NOT NULL,
372 swiftspear INTEGER NOT NULL,
373 guide INTEGER NOT NULL,
374 marauder INTEGER NOT NULL,
375 vexing INTEGER NOT NULL,
376 rift INTEGER NOT NULL,
377 fireblast INTEGER NOT NULL,
378 atarka INTEGER NOT NULL,
379 incinerate INTEGER NOT NULL,
380 bolt INTEGER NOT NULL,
381 jet INTEGER NOT NULL,
382 top INTEGER NOT NULL,
383 probe INTEGER NOT NULL,
384 firecraft INTEGER NOT NULL,
385 lavamancer INTEGER NOT NULL,
386 ring INTEGER NOT NULL,
387 vortex INTEGER NOT NULL,
388 serum INTEGER NOT NULL,
389 chain INTEGER NOT NULL,
390 searingblaze INTEGER NOT NULL,
391 berserker INTEGER NOT NULL,
392 nacatl INTEGER NOT NULL,
393 birds INTEGER NOT NULL,
394 explorer INTEGER NOT NULL,
395 sakura INTEGER NOT NULL,
396 truths INTEGER NOT NULL,
397 sigarda INTEGER NOT NULL,
398 FOREIGN KEY(turnID) REFERENCES tableGames(turnID))''')
399 conn.commit()
400 conn.close()
401 conn = sqlite3.connect('burn.db')
402 c = conn.cursor()
403
404 self.debug("Building draw table...")
405 #c.execute('''DROP TABLE tableDraw''')
406 c.execute('''CREATE TABLE IF NOT EXISTS tableDraw
407 (thingID INTEGER PRIMARY KEY AUTOINCREMENT,
408 gameID INTEGER NOT NULL,
409 fetch INTEGER NOT NULL,
410 land INTEGER NOT NULL,
411 cave INTEGER NOT NULL,
412 eidolon INTEGER NOT NULL,
413 hellspark INTEGER NOT NULL,
414 swiftspear INTEGER NOT NULL,
415 guide INTEGER NOT NULL,
416 marauder INTEGER NOT NULL,
417 vexing INTEGER NOT NULL,
418 rift INTEGER NOT NULL,
419 fireblast INTEGER NOT NULL,
420 atarka INTEGER NOT NULL,
421 incinerate INTEGER NOT NULL,
422 bolt INTEGER NOT NULL,
423 jet INTEGER NOT NULL,
424 top INTEGER NOT NULL,
425 probe INTEGER NOT NULL,
426 firecraft INTEGER NOT NULL,
427 lavamancer INTEGER NOT NULL,
428 ring INTEGER NOT NULL,
429 vortex INTEGER NOT NULL,
430 serum INTEGER NOT NULL,
431 chain INTEGER NOT NULL,
432 searingblaze INTEGER NOT NULL,
433 berserker INTEGER NOT NULL,
434 nacatl INTEGER NOT NULL,
435 birds INTEGER NOT NULL,
436 explorer INTEGER NOT NULL,
437 sakura INTEGER NOT NULL,
438 truths INTEGER NOT NULL,
439 sigarda INTEGER NOT NULL,
440 FOREIGN KEY(gameID) REFERENCES tableGames(turnID))''')
441 self.debug("Database built")
442
443 def recordDeck(self):
444 """Records deck information"""
445 conn = sqlite3.connect('burn.db')
446 c = conn.cursor()
447 #Query for deck config
448 self.debug("Recording deck configuration")
449 cardcount = [(sim.curPlayer.fetchCount, sim.curPlayer.landCount, sim.curPlayer.ForgottenCaveCount, sim.curPlayer.eidolonCount, sim.curPlayer.hellsparkCount, sim.curPlayer.swiftspearCount, sim.curPlayer.guideCount, sim.curPlayer.marauderCount, sim.curPlayer.vexingCount, sim.curPlayer.riftCount, sim.curPlayer.fireblastCount, sim.curPlayer.atarkaCount, sim.curPlayer.incinerateCount, sim.curPlayer.boltCount, sim.curPlayer.jetCount, sim.curPlayer.topCount, sim.curPlayer.probeCount, sim.curPlayer.firecraftCount, sim.curPlayer.lavamancerCount, sim.curPlayer.ringCount, sim.curPlayer.vortexCount, sim.curPlayer.serumCount, sim.curPlayer.chainCount, sim.curPlayer.searingCount, sim.curPlayer.berserkerCount, sim.curPlayer.nacatlCount, sim.curPlayer.birdsCount, sim.curPlayer.explorerCount, sim.curPlayer.sakuraCount, sim.curPlayer.truthsCount, sim.curPlayer.sigardaCount)]
450 c.executemany('INSERT INTO tableDeck VALUES (NULL, ?, ?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)', cardcount)
451 cursor = c.execute('SELECT max(deckID) FROM tableDeck')
452 self.deckID = cursor.fetchone()[0]
453 conn.commit()
454 conn.close()
455
456 def recordDraw(self):
457 """Records draw information"""
458 conn = sqlite3.connect('burn.db')
459 c = conn.cursor()
460 self.debug("Recording draw")
461 game = self.getGameId()
462 self.fetchDraw = self.cardsin(Fetch, sim.curPlayer.myDraw)
463 self.landDraw = self.cardsin(Land, sim.curPlayer.myDraw)
464 self.eidolonDraw = self.cardsin(Eidolon, sim.curPlayer.myDraw)
465 self.hellsparkDraw = self.cardsin(Hellspark, sim.curPlayer.myDraw)
466 self.swiftspearDraw = self.cardsin(Swiftspear, sim.curPlayer.myDraw)
467 self.guideDraw = self.cardsin(Guide, sim.curPlayer.myDraw)
468 self.marauderDraw = self.cardsin(Marauder, sim.curPlayer.myDraw)
469 self.vexingDraw = self.cardsin(Vexing, sim.curPlayer.myDraw)
470 self.riftDraw = self.cardsin(Rift, sim.curPlayer.myDraw)
471 self.fireblastDraw = self.cardsin(Fireblast, sim.curPlayer.myDraw)
472 self.atarkaDraw = self.cardsin(Atarka, sim.curPlayer.myDraw)
473 self.incinerateDraw = self.cardsin(Incinerate, sim.curPlayer.myDraw)
474 self.boltDraw = self.cardsin(Bolt, sim.curPlayer.myDraw)
475 self.jetDraw = self.cardsin(Jet, sim.curPlayer.myDraw)
476 self.topDraw = self.cardsin(Top, sim.curPlayer.myDraw)
477 self.probeDraw = self.cardsin(Probe, sim.curPlayer.myDraw)
478 self.firecraftDraw = self.cardsin(Firecraft, sim.curPlayer.myDraw)
479 self.vortexDraw = self.cardsin(Vortex, sim.curPlayer.myDraw)
480 self.lavamancerDraw = self.cardsin(Lavamancer, sim.curPlayer.myDraw)
481 self.ringDraw = self.cardsin(Ring, sim.curPlayer.myDraw)
482 self.serumDraw = self.cardsin(Serum, sim.curPlayer.myDraw)
483 self.chainDraw = self.cardsin(Chain, sim.curPlayer.myDraw)
484 self.searingDraw = self.cardsin(SearingBlaze, sim.curPlayer.myDraw)
485 self.caveDraw = self.cardsin(ForgottenCave, sim.curPlayer.myDraw)
486 self.berserkerDraw = self.cardsin(Berserker, sim.curPlayer.myDraw)
487 self.nacatlDraw = self.cardsin(Nacatl, sim.curPlayer.myDraw)
488 self.birdsDraw = self.cardsin(Birds, sim.curPlayer.myDraw)
489 self.explorerDraw = self.cardsin(Explorer, sim.curPlayer.myDraw)
490 self.sakuraDraw = self.cardsin(Sakura, sim.curPlayer.myDraw)
491 self.truthsDraw = self.cardsin(Truths, sim.curPlayer.myDraw)
492 self.sigardaDraw = self.cardsin(Sigarda, sim.curPlayer.myDraw)
493 drawinfo = [(self.gameID, self.fetchDraw, self.landDraw, self.caveDraw, self.eidolonDraw, self.hellsparkDraw, self.swiftspearDraw, self.guideDraw, self.marauderDraw, self.vexingDraw, self.riftDraw, self.fireblastDraw, self.atarkaDraw, self.incinerateDraw, self.boltDraw, self.jetDraw, self.topDraw, self.probeDraw, self.firecraftDraw, self.lavamancerDraw, self.ringDraw, self.vortexDraw, self.serumDraw, self.chainDraw, self.searingDraw, self.berserkerDraw , self.nacatlDraw, self.birdsDraw, self.explorerDraw, self.sakuraDraw, self.truthsDraw, self.sigardaDraw)]
494 c.executemany('INSERT INTO tableDraw VALUES (NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', drawinfo)
495 conn.commit()
496 conn.close()
497
498 def recordGame(self):
499 """Records game information"""
500 conn = sqlite3.connect('burn.db')
501 c = conn.cursor()
502 self.debug("Recording game configuration")
503 params = [(self.deckID, sim.curPlayer.mulligansTaken, sim.curPlayer.mulliganNoLand, sim.curPlayer.mulliganAllLand, sim.curPlayer.mulliganNoCreatures, math.floor(self.turn))]
504 deck = [(self.deckID)]
505 c.executemany('INSERT INTO tableGames VALUES (NULL, ?, ?, ?, ?, ?, ?)', params)
506 cursor = c.execute('SELECT max(gameID) FROM tableGames WHERE deckID = ?', (deck))
507 self.gameID = cursor.fetchone()[0]
508 conn.commit()
509 conn.close()
510
511 def recordTurn(self):
512 """Records turn information"""
513 conn = sqlite3.connect('burn.db')
514 c = conn.cursor()
515 self.debug("Recording turn configuration")
516 game = [(self.gameID)]
517 params = [(self.gameID, sim.curPlayer.life, sim.nAP.life, sim.curPlayer.maxMana, sim.curPlayer.prowess, self.turn, sim.curPlayer.lavaAct, sim.nAP.life)]
518 c.executemany('INSERT INTO tableTurns VALUES (NULL, ?, ?, ?, ?, ?, ?, ?, ?)', params)
519 cursor = c.execute('SELECT max(turnID) FROM tableTurns WHERE gameID = ?', (game))
520 self.turnID = cursor.fetchone()[0]
521 self.debug("Updating max turns")
522 c.execute('UPDATE tableGames SET maxTurns = ? WHERE gameID=?', [self.turn, self.gameID])
523 conn.commit()
524 conn.close()
525 if self.curPlayer.deckName == "Burn":
526 self.recordBoard()
527
528 def recordHand(self):
529 """Records hand information"""
530 conn = sqlite3.connect('burn.db')
531 c = conn.cursor()
532 self.debug("Recording hand configuration")
533 self.fetchHand = self.cardsin(Fetch, sim.curPlayer.myHand)
534 self.landHand = self.cardsin(Land, sim.curPlayer.myHand)
535 self.eidolonHand = self.cardsin(Eidolon, sim.curPlayer.myHand)
536 self.hellsparkHand = self.cardsin(Hellspark, sim.curPlayer.myHand)
537 self.swiftspearHand = self.cardsin(Swiftspear, sim.curPlayer.myHand)
538 self.guideHand = self.cardsin(Guide, sim.curPlayer.myHand)
539 self.marauderHand = self.cardsin(Marauder, sim.curPlayer.myHand)
540 self.vexingHand = self.cardsin(Vexing, sim.curPlayer.myHand)
541 self.riftHand = self.cardsin(Rift, sim.curPlayer.myHand)
542 self.fireblastHand = self.cardsin(Fireblast, sim.curPlayer.myHand)
543 self.atarkaHand = self.cardsin(Atarka, sim.curPlayer.myHand)
544 self.incinerateHand = self.cardsin(Incinerate, sim.curPlayer.myHand)
545 self.boltHand = self.cardsin(Bolt, sim.curPlayer.myHand)
546 self.jetHand = self.cardsin(Jet, sim.curPlayer.myHand)
547 self.topHand = self.cardsin(Top, sim.curPlayer.myHand)
548 self.probeHand = self.cardsin(Probe, sim.curPlayer.myHand)
549 self.firecraftHand = self.cardsin(Firecraft, sim.curPlayer.myHand)
550 self.vortexHand = self.cardsin(Vortex, sim.curPlayer.myHand)
551 self.lavamancerHand = self.cardsin(Lavamancer, sim.curPlayer.myHand)
552 self.ringHand = self.cardsin(Ring, sim.curPlayer.myHand)
553 self.serumHand = self.cardsin(Serum, sim.curPlayer.myHand)
554 self.chainHand = self.cardsin(Chain, sim.curPlayer.myHand)
555 self.searingHand = self.cardsin(SearingBlaze, sim.curPlayer.myHand)
556 self.caveHand = self.cardsin(ForgottenCave, sim.curPlayer.myHand)
557 self.berserkerHand = self.cardsin(Berserker, sim.curPlayer.myHand)
558 self.nacatlHand = self.cardsin(Nacatl, sim.curPlayer.myHand)
559 self.birdsHand = self.cardsin(Birds, sim.curPlayer.myHand)
560 self.explorerHand = self.cardsin(Explorer, sim.curPlayer.myHand)
561 self.sakuraHand = self.cardsin(Sakura, sim.curPlayer.myHand)
562 self.truthsHand = self.cardsin(Truths, sim.curPlayer.myHand)
563 self.sigardaHand = self.cardsin(Sigarda, sim.curPlayer.myHand)
564 self.getTurnId()
565 handinfo = [(self.turnID, self.fetchHand, self.landHand, self.caveHand, self.eidolonHand, self.hellsparkHand, self.swiftspearHand, self.guideHand, self.marauderHand, self.vexingHand, self.riftHand, self.fireblastHand, self.atarkaHand, self.incinerateHand, self.boltHand, self.jetHand, self.topHand, self.probeHand, self.firecraftHand, self.lavamancerHand, self.ringHand, self.vortexHand, self.serumHand, self.chainHand, self.searingHand, self.berserkerHand, self.nacatlHand, self.birdsHand, self.explorerHand, self.sakuraHand, self.truthsHand, self.sigardaHand)]
566 turn = [(self.turnID)]
567 c.executemany('INSERT INTO tableHand VALUES (NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', handinfo)
568 cursor = c.execute('SELECT max(handID) FROM tableHand WHERE turnID = ?', (turn))
569 self.handID = cursor.fetchone()[0]
570 conn.commit()
571 conn.close()
572
573 def recordBoard(self):
574 """Records board information"""
575 conn = sqlite3.connect('burn.db')
576 c = conn.cursor()
577 self.debug("Recording board configuration")
578## for x in cardlist:
579## self.cardsin(cardlist, sim.curPlayer.myBoard)
580 self.fetchBoard = self.cardsin(Fetch, sim.curPlayer.myBoard)
581 self.landBoard = self.cardsin(Land, sim.curPlayer.myBoard)
582 self.eidolonBoard = self.cardsin(Eidolon, sim.curPlayer.myBoard)
583 self.hellsparkBoard = self.cardsin(Hellspark, sim.curPlayer.myBoard)
584 self.swiftspearBoard = self.cardsin(Swiftspear, sim.curPlayer.myBoard)
585 self.guideBoard = self.cardsin(Guide, sim.curPlayer.myBoard)
586 self.marauderBoard = self.cardsin(Marauder, sim.curPlayer.myBoard)
587 self.vexingBoard = self.cardsin(Vexing, sim.curPlayer.myBoard)
588 self.riftBoard = self.cardsin(Rift, sim.curPlayer.myBoard)
589 self.fireblastBoard = self.cardsin(Fireblast, sim.curPlayer.myBoard)
590 self.atarkaBoard = self.cardsin(Atarka, sim.curPlayer.myBoard)
591 self.incinerateBoard = self.cardsin(Incinerate, sim.curPlayer.myBoard)
592 self.boltBoard = self.cardsin(Bolt, sim.curPlayer.myBoard)
593 self.jetBoard = self.cardsin(Jet, sim.curPlayer.myBoard)
594 self.topBoard = self.cardsin(Top, sim.curPlayer.myBoard)
595 self.probeBoard = self.cardsin(Probe, sim.curPlayer.myBoard)
596 self.firecraftBoard = self.cardsin(Firecraft, sim.curPlayer.myBoard)
597 self.vortexBoard = self.cardsin(Vortex, sim.curPlayer.myBoard)
598 self.lavamancerBoard = self.cardsin(Lavamancer, sim.curPlayer.myBoard)
599 self.ringBoard = self.cardsin(Ring, sim.curPlayer.myBoard)
600 self.serumBoard = self.cardsin(Serum, sim.curPlayer.myBoard)
601 self.chainBoard = self.cardsin(Chain, sim.curPlayer.myBoard)
602 self.searingBoard = self.cardsin(SearingBlaze, sim.curPlayer.myBoard)
603 self.caveBoard = self.cardsin(ForgottenCave, sim.curPlayer.myBoard)
604 self.nacatlBoard = self.cardsin(Nacatl, sim.curPlayer.myBoard)
605 self.berserkerBoard = self.cardsin(Berserker, sim.curPlayer.myBoard)
606 self.birdsBoard = self.cardsin(Birds, sim.curPlayer.myBoard)
607 self.explorerBoard = self.cardsin(Explorer, sim.curPlayer.myBoard)
608 self.sakuraBoard = self.cardsin(Sakura, sim.curPlayer.myBoard)
609 self.truthsBoard = self.cardsin(Truths, sim.curPlayer.myBoard)
610 self.sigardaBoard = self.cardsin(Sigarda, sim.curPlayer.myBoard)
611 boardinfo = [(self.turnID, self.fetchBoard, self.landBoard, self.caveBoard, self.eidolonBoard, self.hellsparkBoard, self.swiftspearBoard, self.guideBoard, self.marauderBoard, self.vexingBoard, self.riftBoard, self.fireblastBoard, self.atarkaBoard, self.incinerateBoard, self.boltBoard, self.jetBoard, self.topBoard, self.probeBoard, self.firecraftBoard, self.lavamancerBoard, self.ringBoard, self.vortexBoard, self.serumBoard, self.chainBoard, self.searingBoard, self.berserkerBoard, self.nacatlBoard, self.birdsBoard, self.explorerBoard, self.sakuraBoard, self.truthsBoard, self.sigardaBoard)]
612 turn = [(self.turnID)]
613 c.executemany('INSERT INTO tableBoard VALUES (NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', boardinfo)
614 cursor = c.execute('SELECT max(boardID) FROM tableBoard WHERE turnID = ?', (turn))
615 self.boardID = cursor.fetchone()[0]
616 conn.commit()
617 conn.close()
618
619 def getTurnId(self):
620 """Gets self.turnID"""
621 conn = sqlite3.connect('burn.db')
622 c = conn.cursor()
623 cursor = c.execute('SELECT max(turnID) FROM tableTurns')
624 self.turnID = cursor.fetchone()[0]
625 if self.turnID == None:
626 self.turnID = 0
627 return
628
629 def getGameId(self):
630 """Gets self.gameID"""
631 conn = sqlite3.connect('burn.db')
632 c = conn.cursor()
633 cursor = c.execute('SELECT max(gameID) FROM tableGames')
634 self.gameID = cursor.fetchone()[0]
635 if self.gameID == None:
636 self.gameID = 0
637 return
638
639 def cardsin(self, card, zone):
640 """Takes card class and zone, returns number of that class instance in zone"""
641 count = sum(isinstance(x, card) for x in zone)
642 return count
643
644 def getPlayer(self):
645 """Gets current player"""
646 return self.curPlayer
647
648 def debug(self, message):
649 """Prints debug messages to console if enabled"""
650 if (self.debugmsg == 1):
651 print(message)
652
653 def blast(self):
654 """Checks for number of alt cast Fireblast available"""
655 self.debug("Evaluating Fireblast")
656 castBlast = min(self.cardsin(Fireblast, sim.curPlayer.myHand), (self.cardsin(Land, sim.curPlayer.myBoard)//2))
657 castBlast = castBlast * Fireblast().getDamage()
658 return castBlast
659
660 def reset(self):
661 """Resets game variables"""
662## if self.goFirst == 1:
663## self.curPlayer = P1()
664## self.nAP = P2()
665## self.activePlayer = self.curPlayer.deckName
666## if self.goFirst != 1:
667## self.curPlayer = P2()
668## self.nAP = P1()
669## self.activePlayer = self.curPlayer.deckName
670 self.curPlayer.myHand = []
671 self.curPlayer.myBoard = []
672 self.curPlayer.myGrave = []
673 self.curPlayer.myStack = []
674 self.nAP.myHand = []
675 self.nAP.myBoard = []
676 self.nAP.myGrave = []
677 self.nAP.myStack = []
678 sim.curPlayer.life = 20
679 sim.nAP.life = 20
680 self.turn = 0
681 self.curPlayer.openingHand = 7
682 self.nAP.openingHand = 7
683
684 def untapPhase(self):
685 """Untap phase"""
686 self.debug("Turn " + str(math.floor(self.turn)) + " begins for " + str(self.curPlayer.deckName))
687 self.debug("Untap Phase")
688 for card in self.curPlayer.myBoard:
689 if card.sick > 0:
690 card.sick -= 1
691 card.untap()
692 self.curPlayer.prowess = 0
693 self.nAP.prowess = 0
694 self.lavaAct = 0
695 self.topUsed = 0
696
697 def upkeepPhase(self):
698 """Upkeep phase"""
699 self.debug("Upkeep Phase")
700 for card in self.curPlayer.myHand:
701 card.upkeepTrigger()
702 self.curPlayer.resolveStack()
703
704 def drawPhase(self):
705 """Draw phase"""
706 if self.turn > 1 or self.goFirst == 0:
707 self.curPlayer.drawCard()
708 self.debug("New hand is" + str(self.curPlayer.myHand))
709 self.curPlayer.resolveStack()
710 if self.curPlayer.deckName == "Burn":
711 self.recordHand()
712
713 def mainOnePhase(self):
714 """Main one phase"""
715 #Play land and crack fetch
716 self.curPlayer.playLand()
717 self.curPlayer.useFetch()
718 #Determine available mana for the turn
719 self.curPlayer.availableMana = 0
720 for card in self.curPlayer.myBoard:
721 if card.type == "Land" and card.name != "Fetch" and card.tapped == 0:
722 self.curPlayer.availableMana += 1
723 if card.type == "Creature" and card.name == "Birds":
724 self.curPlayer.availableMana += 1
725 message = "Mana is " + str(self.curPlayer.getMana())
726 self.debug(message)
727 self.curPlayer.maxMana = self.curPlayer.availableMana
728 self.debug("New board is")
729 #Find burn in hand
730 self.debug(self.curPlayer.myBoard)
731 burn = self.curPlayer.getBurn()
732 #Loop until there are no plays to make
733 noPlay = False
734 while(noPlay == False):
735 noPlay = True
736 #Create list of most to least favorable plays
737 self.curPlayer.getPlays()
738 for card in self.curPlayer.myHand:
739 #Cycle cards
740 if card.mana <= self.curPlayer.availableMana and card.cycling == 1:
741 self.debug("Cycling cards")
742 card.cycle()
743 self.noPlay = False
744 #Play cards in order
745 if card.mana <= self.curPlayer.availableMana and card.type != "Land":
746 self.debug("Attempting to play cards")
747 card.play()
748 self.noPlay = False
749 self.curPlayer.resolveStack()
750
751 def combatPhase(self):
752 """Combat phase"""
753 sim.debug("Beginning combat...")
754 self.curPlayer.declareAttacks()
755 self.nAP.declareBlocks()
756 self.dealDamage()
757 #Lavamancer extra damage
758 temp = min(len(sim.curPlayer.myGrave)//2, sim.cardsin(Lavamancer, sim.curPlayer.myBoard), sim.curPlayer.availableMana)
759 for x in range(0, temp):
760 sim.curPlayer.myGrave.pop()
761 sim.curPlayer.myGrave.pop()
762 sim.curPlayer.availableMana -= 1
763 sim.nAP.life -= 1
764 sim.curPlayer.lavaAct += 1
765 sim.debug("Combat finished, opponent at " + str(sim.nAP.life))
766 self.curPlayer.resolveStack()
767
768 def dealDamage(self):
769 """Exchange damage in combat"""
770 sim.debug("Exchanging Damage")
771 #Deal Damage
772 for card in sim.curPlayer.blockedAttackers:
773 card.damageTaken += card.blockedBy.damage
774 for card in sim.nAP.blockers:
775 card.damageTaken += card.blocking.damage
776 for card in sim.curPlayer.unblockedAttackers:
777 msg = str(card) + " was unblocked for " + str(card.damage) + " damage"
778 sim.debug(msg)
779 sim.nAP.life -= card.damage
780 #Consolidate combat zones to myBoard
781 for card in sim.nAP.potentialBlockers:
782 sim.nAP.myBoard.append(card)
783 sim.curPlayer.myBoard = []
784 for card in sim.curPlayer.unblockedAttackers:
785 sim.curPlayer.myBoard.append(card)
786 for card in sim.curPlayer.blockedAttackers:
787 sim.curPlayer.myBoard.append(card)
788 for card in sim.curPlayer.otherPermanents:
789 sim.curPlayer.myBoard.append(card)
790 #Kill things
791 for card in sim.curPlayer.myBoard:
792 if card.type == "Creature" and card.damageTaken > card.toughness:
793 card.damageTaken = 0
794 card.die()
795 for card in sim.nAP.myBoard:
796 if card.type == "Creature" and card.damageTaken > card.toughness:
797 card.damageTaken = 0
798 card.die()
799
800 def mainTwoPhase(self):
801 """Main two phase"""
802 x = self.blast()
803 if (x >= sim.nAP.life and sim.curPlayer.life > 0):
804 y = x//4
805 for z in range(0, y + 1):
806 noPlay = False
807 Fireblast.play(self)
808 self.curPlayer.resolveStack()
809
810 def endPhase(self):
811 """End of turn phase"""
812 sim.nAP.life -= self.cardsin(Eidolon, self.curPlayer.myBoard) * 2
813 sim.nAP.life -= self.cardsin(Berserker, self.curPlayer.myBoard) * 2
814 sim.debug(str(self.curPlayer) + " turn ends at " + str(sim.curPlayer.life) + ". " + str(sim.nAP) + " at " + str(sim.nAP.life))
815 self.curPlayer.resolveStack()
816 for card in sim.curPlayer.myBoard:
817 if card.type == "Creature":
818 card.damageTaken = 0
819 card.damage -= sim.curPlayer.prowess * card.prowess
820 card.toughness -= sim.curPlayer.prowess * card.prowess
821 for card in sim.nAP.myBoard:
822 if card.type == "Creature":
823 card.damageTaken = 0
824 card.damage -= sim.nAP.prowess * card.prowess
825 card.toughness -= sim.nAP.prowess * card.prowess
826 if self.curPlayer.deckName == "Burn":
827 self.recordTurn()
828 sim.curPlayer.prowess = 0
829 sim.nAP.prowess = 0
830
831
832 def preGame(self):
833 """Pregame, shuffle, reset deck, mulligan"""
834 self.reset()
835 sim.curPlayer.buildDeck()
836 sim.nAP.buildDeck()
837 self.curPlayer.resolveMulligans()
838 self.nAP.resolveMulligans()
839 if (len(self.curPlayer.myHand) < 7):
840 self.debug("Taking mulligan scry")
841 self.curPlayer.scry(1)
842 if (len(self.nAP.myHand) < 7):
843 self.debug("Taking mulligan scry")
844 self.nAP.scry(1)
845
846 def playGames(self):
847 """Main games loop"""
848 if self.curPlayer.deckName == "Burn":
849 self.recordDeck()
850 self.debug("Playing games")
851 games = 0
852 for games in range(0, self.simulationLength):
853
854 self.debug("Game " + str(games) + " begins")
855 self.preGame()
856 if self.curPlayer.deckName == "Burn":
857 self.recordGame()
858 self.debug("Reseting deck variables")
859#Keep decision made, begin playing
860 while sim.nAP.life > 0 and sim.curPlayer.life > 0:
861 self.turn += 1
862 self.untapPhase()
863 self.upkeepPhase()
864 self.drawPhase()
865 self.mainOnePhase()
866 self.combatPhase()
867 self.mainTwoPhase()
868 self.endPhase()
869 self.switchPlayers()
870#Repeat because turns are dumb
871 self.untapPhase()
872 self.upkeepPhase()
873 self.drawPhase()
874 self.mainOnePhase()
875 self.combatPhase()
876 self.mainTwoPhase()
877 self.endPhase()
878 self.switchPlayers()
879
880class Card:
881 """Card class, constains generalized card functions and lots of card variables"""
882 def __init__(self):
883 self.type = "Land"
884 self.damage = 0
885 self.toughness = 0
886 self.mana = 0
887 self.sick = 1
888 self.name = "Wastes"
889 self.targets = 0
890 self.cardsDrawn = 0
891 self.tapped = 0
892 self.vanishing = 0
893 self.shouldAttack = 0
894 self.shouldBlock = 0
895 self.blocking = None
896 self.blockedBy = None
897 self.owner = sim.curPlayer
898 self.damageTaken = 0
899 self.prowess = 0
900 self.counter = 0
901 self.tgtcreature = 0
902 self.tgtplayer = 0
903 self.target = None
904 self.cycling = 0
905
906 def __str__(self):
907 return str(self.name)
908
909 def getType(self):
910 return self.type
911
912 def setType(self, newtype):
913 self.type = str(newtype)
914
915 def getDamage(self):
916 return self.damage
917
918 def setDamage(self, newdamage):
919 self.damage = int(newdamage)
920
921 def getMana(self):
922 return self.mana
923
924 def setMana(self, newmana):
925 self.mana = int(newmana)
926
927 def getName(self):
928 return self.name
929
930 def setName(self, newname):
931 self.name = str(newname)
932
933 def cycle(self):
934 """Cycle cards"""
935 sim.curPlayer.drawCard()
936 for i, o in enumerate(sim.curPlayer.myHand):
937 if o.name == self.getName():
938 self.owner.myGrave.append(o)
939 del sim.curPlayer.myHand[i]
940 break
941
942 def getTargets(self):
943#Get clocks
944 tgt = sim.curPlayer
945 if self.tgtcreature == 0 and self.tgtplayer == 0:
946 tgt = sim.curPlayer
947
948 if self.tgtcreature > 0 or self.tgtplayer > 0:
949 myPower = 0
950 for card in sim.curPlayer.myBoard:
951 if card.type == "Creature":
952 myPower += card.damage
953 if myPower == 0:
954 myPower = .001
955 myClock = math.ceil((sim.nAP.life - sim.curPlayer.getBurn()) / myPower)
956 oppPower = 0
957 for card in sim.nAP.myBoard:
958 if card.type == "Creature":
959 oppPower += card.damage
960 if oppPower == 0:
961 oppPower = .001
962 oppClock= math.ceil(sim.curPlayer.life / oppPower)
963
964 if self.tgtcreature == 1 and self.tgtplayer == 1 and self.damage > 0 and self.counter == 0:
965
966 #Burn face if myclock > oppclock
967 if myClock > oppClock:
968 target = sim.nAP
969 if myClock <= oppClock:
970 pot = []
971 for card in sim.nAP.myBoard:
972 if card.type == "Creature" and card.toughness <= self.damage:
973 pot.append(card)
974 if len(pot) > 0:
975 pot.sort(key=operator.attrgetter('damage'))
976 tgt = pot[-1]
977 else:
978 tgt = sim.nAP
979 if self.tgtcreature == 1 and self.tgtplayer == 0 and self.damage > 0 and self.counter == 0:
980 #Burn highest power creature
981 pot = []
982 for card in sim.nAP.myBoard:
983 if card.type == "Creature" and card.toughness <= self.damage:
984 pot.append(card)
985 if len(pot) > 0:
986 pot.sort(key=operator.attrgetter('damage'))
987 tgt = pot[-1]
988 #Target player
989 if self.tgtcreature == 0 and self.tgtplayer == 1:
990 tgt = sim.nAP
991
992 #Target biggest creature
993 if self.tgtcreature == 1 and self.tgtplayer == 0 and self.damage == 0 and self.counter == 0:
994 pot = []
995 for card in sim.nAP.myBoard:
996 if card.type == "Creature" and card.toughness <= self.damage:
997 pot.append(card)
998 if len(pot) > 0:
999 pot.sort(key=operator.attrgetter('damage'))
1000 tgt = pot[-1]
1001 self.target = tgt
1002 if self.target == None:
1003 self.target = sim.curPlayer
1004
1005 def setTargets(self, newtargets):
1006 self.targets = int(self.tgtcreature) + int(self.tgtplayer)
1007
1008 def getCardsDrawn(self):
1009 return self.cardsDrawn
1010
1011 def setCardsDrawn(self, newcards):
1012 self.cardsDrawn = int(newcards)
1013
1014 def getTapped(self):
1015 return self.tapped
1016
1017 def tap(self):
1018 self.tapped = 1
1019
1020 def untap(self):
1021 self.tapped = 0
1022
1023 def setVanishing(self, val):
1024 self.vanishing = int(val)
1025
1026 def getVanishing(self):
1027 return self.vanishing
1028
1029 def die(self):
1030 """How a creature dies"""
1031 for i, o in enumerate(self.owner.myBoard):
1032 if o.name == self.getName():
1033 o.diesTrigger()
1034 self.owner.myGrave.append(o)
1035 del self.owner.myBoard[i]
1036 break
1037
1038 def additionalPlay(self):
1039 pass
1040
1041 def play(self):
1042 """Plays a card from hand to the stack"""
1043 x = self.__class__
1044 if self.counter == 1:
1045 if sim.cardsin(x, sim.nAP.myHand) > 0 and sim.nAP.availableMana >= self.getMana():
1046 for i, o in enumerate(sim.nAP.myHand):
1047 if o.name == self.getName():
1048 del sim.nAP.myHand[i]
1049 break
1050 sim.nAP.myGrave.append(self)
1051 sim.nAP.availableMana -= self.getMana()
1052 sim.curPlayer.myStack.sort(key=operator.attrgetter('damage'))
1053 card = sim.curPlayer.myStack.pop()
1054 sim.curPlayer.myGrave.append(card)
1055 self.owner = sim.curPlayer
1056 message = "Using " + str(x) + " to counter " + str(card)
1057 sim.debug(message)
1058 if self.counter == 0:
1059 if sim.cardsin(x, sim.curPlayer.myHand) > 0 and sim.curPlayer.availableMana >= self.getMana():
1060 for i, o in enumerate(sim.curPlayer.myHand):
1061 if o.name == self.getName():
1062 del sim.curPlayer.myHand[i]
1063 break
1064 sim.curPlayer.myStack.append(self)
1065 sim.curPlayer.availableMana -= self.getMana()
1066 self.owner = sim.curPlayer
1067 message = "Appending " + str(self.getName()) + " to stack"
1068 sim.debug(message)
1069 self.additionalPlay()
1070
1071 def upkeepTrigger(self):
1072 pass
1073
1074 def drawTrigger(self):
1075 pass
1076
1077 def endTrigger(self):
1078 pass
1079
1080 def etbTrigger(self):
1081 pass
1082
1083 def diesTrigger(self):
1084 pass
1085
1086class SearingBlaze(Card):
1087 """Searing Blaze"""
1088 def __init__(self):
1089 super(SearingBlaze, self).__init__()
1090 self.type = "Instant"
1091 self.damage = 3
1092 self.mana = 2
1093 self.sick = 0
1094 self.name = "SearingBlaze"
1095 self.tgtcreature = 1
1096 self.tgtplayer = 0
1097
1098 def additionalPlay(self):
1099 self.owner.life -= 3
1100
1101class Eidolon(Card):
1102 """Eidolon of the Great Revel"""
1103 def __init__(self):
1104 super(Eidolon, self).__init__()
1105 self.type = "Creature"
1106 self.damage = 2
1107 self.mana = 2
1108 self.sick = 1
1109 self.name = "Eidolon"
1110 self.toughness = 2
1111
1112class Land(Card):
1113 """Generic rainbow land"""
1114 def __init__(self):
1115 super(Land, self).__init__()
1116 self.type = "Land"
1117 self.name = "Land"
1118
1119class Fireblast(Card):
1120 """Fireblast"""
1121 def __init__(self):
1122 super(Fireblast, self).__init__()
1123 self.type = "Instant"
1124 self.damage = 4
1125 self.mana = 6
1126 self.sick = 0
1127 self.name = "Fireblast"
1128 self.tgtcreature = 1
1129 self.tgtplayer = 1
1130
1131 def play(self):
1132 x = self.__class__
1133 if sim.cardsin(x, sim.curPlayer.myHand) > 0 and sim.cardsin(Land, sim.curPlayer.myBoard) >= 2:
1134 for i, o in enumerate(sim.curPlayer.myHand):
1135 if o.name == self.getName():
1136 del sim.curPlayer.myHand[i]
1137 break
1138 sim.curPlayer.myBoard.append(self)
1139 sim.curPlayer.maxMana -= 2
1140 for i, o in enumerate(sim.curPlayer.myBoard):
1141 if o.name == "Land":
1142 del sim.curPlayer.myBoard[i]
1143 break
1144 for i, o in enumerate(sim.curPlayer.myBoard):
1145 if o.name == "Land":
1146 del sim.curPlayer.myBoard[i]
1147 break
1148 message = "Playing " + str(self.getName())
1149 sim.debug(message)
1150
1151class Fetch(Card):
1152 """Generic Onslaught/Zendikar fetchland"""
1153 def __init__(self):
1154 super(Fetch, self).__init__()
1155 self.type = "Land"
1156 self.name = "Fetch"
1157
1158class ForgottenCave(Card):
1159 """Forgotten Cave"""
1160 def __init__(self):
1161 super(ForgottenCave, self).__init__()
1162 self.type = "Land"
1163 self.name = "ForgottenCave"
1164 self.tapped = 1
1165 self.mana = 1
1166 self.cycling = 1
1167
1168class Ring(Card):
1169 """Barbarian Ring"""
1170 def __init__(self):
1171 super(Ring, self).__init__()
1172 self.type = "Land"
1173 self.name = "Ring"
1174 self.damage = 2
1175 self.tgtcreature = 1
1176 self.tgtplayer = 1
1177
1178 def useRing(self):
1179 if (len(sim.myGrave) >= 7 and sim.availableMana >= 2):
1180 for i, o in enumerate(sim.curPlayer.myBoard):
1181 if o.name == "Ring":
1182 del sim.myBoard[i]
1183 sim.curPlayer.myGrave.append(Ring())
1184 sim.nAP.life -= 2
1185 sim.maxMana -= 1
1186 break
1187
1188class Hellspark(Card):
1189 """Hellspark Elemental"""
1190 def __init__(self):
1191 super(Hellspark, self).__init__()
1192 self.type = "Creature"
1193 self.damage = 3
1194 self.mana = 2
1195 self.sick = 0
1196 self.name = "Hellspark"
1197 self.toughness = 1
1198
1199 def endTrigger(self):
1200 self.die()
1201 sim.curPlayer.myHand.append(HellsparkUnearth())
1202
1203class HellsparkUnearth(Card):
1204 """Hellspark Elemental, unearthed"""
1205 def __init__(self):
1206 super(Hellspark, self).__init__()
1207 self.type = "Creature"
1208 self.damage = 3
1209 self.mana = 2
1210 self.sick = 0
1211 self.name = "Hellspark Unearth"
1212 self.toughness = 1
1213
1214 def endTrigger(self):
1215 self.die()
1216 if sim.cardsin(HellsparkUnearth, sim.curPlayer.myGrave) > 0:
1217 for i, o in enumerate(sim.curPlayer.myGrave):
1218 if o.name == "Hellspark Unearth":
1219 del sim.myBoard[i]
1220 break
1221
1222class Swiftspear(Card):
1223 """Monastery Swiftspear"""
1224 def __init__(self):
1225 super(Swiftspear, self).__init__()
1226 self.type = "Creature"
1227 self.damage = 1
1228 self.mana = 1
1229 self.sick = 0
1230 self.name = "Swiftspear"
1231 self.toughness = 2
1232 self.prowess = 1
1233
1234class Guide(Card):
1235 """Goblin Guide"""
1236 def __init__(self):
1237 super(Guide, self).__init__()
1238 self.type = "Creature"
1239 self.damage = 2
1240 self.mana = 1
1241 self.sick = 0
1242 self.name = "Guide"
1243 self.toughness = 2
1244
1245class Truths(Card):
1246 """Painful Truths"""
1247 def __init__(self):
1248 super(Truths, self).__init__()
1249 self.type = "Sorcery"
1250 self.damage = 0
1251 self.mana = 3
1252 self.sick = 0
1253 self.name = "Truths"
1254 self.targets = 0
1255 self.cardsDrawn = 3
1256
1257 def additionalPlay(self):
1258 sim.curPlayer.life -= 3
1259
1260class Birds(Card):
1261 """Birds of Paradise"""
1262 def __init__(self):
1263 super(Birds, self).__init__()
1264 self.type = "Creature"
1265 self.damage = 0
1266 self.mana = 1
1267 self.sick = 1
1268 self.name = "Birds"
1269 self.toughness = 1
1270
1271class Sakura(Card):
1272 """Sakura-Tribe Elder"""
1273 def __init__(self):
1274 super(Sakura, self).__init__()
1275 self.type = "Creature"
1276 self.damage = 1
1277 self.mana = 2
1278 self.sick = 1
1279 self.name = "Sakura-Tribe Elder"
1280 self.toughness = 1
1281 self.vanishing = 1
1282
1283 def upkeepTrigger(self):
1284 x = self.getVanishing()
1285 x -= 1
1286 self.setVanishing(x)
1287 if self.getVanishing() <= 0:
1288 self.die()
1289
1290 def diesTrigger(self):
1291 if (any(isinstance(x, Fetch) for x in sim.curPlayer.myBoard) and any(isinstance(y, Land) for y in sim.curPlayer.myDeck)):
1292 sim.debug("Searching Land")
1293 for i, o in enumerate(sim.curPlayer.myDeck):
1294 if o.name == "Land":
1295 del sim.curPlayer.myDeck[i]
1296 break
1297 sim.curPlayer.myBoard.append(Land())
1298 sim.curPlayer.availableMana += 1
1299
1300
1301class Explorer(Card):
1302 """Sakura-Tribe Elder"""
1303 def __init__(self):
1304 super(Explorer, self).__init__()
1305 self.type = "Creature"
1306 self.damage = 1
1307 self.mana = 1
1308 self.sick = 1
1309 self.name = "Veteran Explorer"
1310 self.toughness = 1
1311 self.vanishing = 2
1312
1313 def upkeepTrigger(self):
1314 x = self.getVanishing()
1315 x -= 1
1316 self.setVanishing(x)
1317 if self.getVanishing() <= 0:
1318 self.die()
1319
1320 def diesTrigger(self):
1321 if (any(isinstance(x, Fetch) for x in sim.curPlayer.myBoard) and any(isinstance(y, Land) for y in sim.curPlayer.myDeck)):
1322 sim.debug("Searching Land")
1323 for i, o in enumerate(sim.curPlayer.myDeck):
1324 if o.name == "Land":
1325 del sim.curPlayer.myDeck[i]
1326 break
1327 sim.curPlayer.myBoard.append(Land())
1328 sim.curPlayer.availableMana += 1
1329 if (any(isinstance(x, Fetch) for x in sim.curPlayer.myBoard) and any(isinstance(y, Land) for y in sim.curPlayer.myDeck)):
1330 sim.debug("Searching Land")
1331 for i, o in enumerate(sim.curPlayer.myDeck):
1332 if o.name == "Land":
1333 del sim.curPlayer.myDeck[i]
1334 break
1335 sim.curPlayer.myBoard.append(Land())
1336 sim.curPlayer.availableMana += 1
1337
1338 sim.curPlayer.shuffle()
1339
1340class Lavamancer(Card):
1341 """Grim Lavamancer"""
1342 def __init__(self):
1343 super(Lavamancer, self).__init__()
1344 self.type = "Creature"
1345 self.damage = 1
1346 self.mana = 1
1347 self.sick = 1
1348 self.name = "Lavamancer"
1349 self.targets = 1
1350 self.toughness = 1
1351
1352class Marauder(Card):
1353 """Keldon Marauder"""
1354 def __init__(self):
1355 super(Marauder, self).__init__()
1356 self.type = "Creature"
1357 self.damage = 3
1358 self.mana = 2
1359 self.sick = 1
1360 self.name = "Marauder"
1361 self.targets = 1
1362 self.vanishing = 2
1363 self.toughness = 3
1364
1365 def upkeepTrigger(self):
1366 x = self.getVanishing()
1367 x -= 1
1368 self.setVanishing(x)
1369 if self.getVanishing() <= 0:
1370 self.die()
1371
1372 def etbTrigger(self):
1373 sim.nAP.life -= 1
1374
1375 def diesTrigger(self):
1376 sim.nAP.life -= 1
1377
1378class Vexing(Card):
1379 """Vexing Devil"""
1380 def __init__(self):
1381 super(Vexing, self).__init__()
1382 self.type = "Creature"
1383 self.damage = 4
1384 self.mana = 1
1385 self.sick = 1
1386 self.name = "Vexing"
1387 self.toughness = 3
1388
1389 def etbTrigger(self):
1390 if sim.turn <= 2:
1391 sim.nAP.life -= 4
1392 self.die()
1393
1394class Rift(Card):
1395 """Flame Rift"""
1396 def __init__(self):
1397 super(Rift, self).__init__()
1398 self.type = "Sorcery"
1399 self.damage = 4
1400 self.mana = 2
1401 self.sick = 0
1402 self.name = "Rift"
1403
1404 def additionalPlay(self):
1405 sim.curPlayer.life -= 4
1406
1407class Atarka(Card):
1408 """Atarka's Command, 3 damage, +1/+1 modes only"""
1409 def __init__(self):
1410 super(Atarka, self).__init__()
1411 self.type = "Instant"
1412 self.damage = 3
1413 self.mana = 2
1414 self.sick = 0
1415 self.name = "Atarka"
1416 self.tgtplayer = 1
1417
1418 def play(self):
1419 x = self.__class__
1420 if sim.cardsin(x, sim.myHand) > 0 and sim.availableMana >= self.getMana():
1421 for i, o in enumerate(sim.myHand):
1422 if o.name == self.getName():
1423 del sim.myHand[i]
1424 break
1425 sim.myBoard.append(self)
1426 sim.availableMana -= self.getMana()
1427 sim.prowess += 1
1428 creatures = 0
1429 for o in sim.myBoard:
1430 if o.type == "Creature":
1431 creatures += 1
1432 sim.nAP.life -= creatures
1433 message = "Playing " + str(self.getName())
1434 sim.debug(message)
1435
1436
1437class Incinerate(Card):
1438 """Incinerate"""
1439 def __init__(self):
1440 super(Incinerate, self).__init__()
1441 self.type = "Instant"
1442 self.damage = 3
1443 self.mana = 2
1444 self.sick = 0
1445 self.name = "Incinerate"
1446 self.tgtcreature = 1
1447 self.tgtplayer = 1
1448
1449class Bolt(Card):
1450 """Lightning Bolt"""
1451 def __init__(self):
1452 super(Bolt, self).__init__()
1453 self.type = "Instant"
1454 self.damage = 3
1455 self.mana = 1
1456 self.sick = 0
1457 self.name = "Bolt"
1458 self.tgtcreature = 1
1459 self.tgtplayer = 1
1460
1461class Chain(Card):
1462 """Chain Lightning"""
1463 def __init__(self):
1464 super(Chain, self).__init__()
1465 self.type = "Sorcery"
1466 self.damage = 3
1467 self.mana = 1
1468 self.sick = 0
1469 self.name = "Chain"
1470 self.tgtcreature = 1
1471 self.tgtplayer = 1
1472
1473class Probe(Card):
1474 """Gitaxian Probe"""
1475 def __init__(self):
1476 super(Probe, self).__init__()
1477 self.type = "Sorcery"
1478 self.damage = 0
1479 self.mana = 0
1480 self.sick = 0
1481 self.name = "Probe"
1482
1483 def additionalPlay(self):
1484 sim.curPlayer.drawCard()
1485 sim.curPlayer.life -= 2
1486
1487class Serum(Card):
1488 """Serum Visions"""
1489 def __init__(self):
1490 super(Serum, self).__init__()
1491 self.type = "Sorcery"
1492 self.damage = 0
1493 self.mana = 1
1494 self.sick = 0
1495 self.name = "Serum"
1496 self.targets = 0
1497 self.cardsDrawn = 1
1498
1499 def additionalPlay(self):
1500 sim.curPlayer.drawCard()
1501 sim.curPlayer.scry(2)
1502
1503class Jet(Card):
1504 """Magma Jet"""
1505 def __init__(self):
1506 super(Jet, self).__init__()
1507 self.type = "Instant"
1508 self.damage = 2
1509 self.mana = 2
1510 self.sick = 0
1511 self.name = "Jet"
1512 self.tgtcreature = 1
1513 self.tgtplayer = 1
1514
1515 def additionalPlay(self):
1516 sim.scry(2)
1517
1518class Firecraft(Card):
1519 """Exquisite Firecraft"""
1520 def __init__(self):
1521 super(Firecraft, self).__init__()
1522 self.type = "Sorcery"
1523 self.damage = 4
1524 self.mana = 3
1525 self.sick = 0
1526 self.name = "Firecraft"
1527 self.tgtcreature = 1
1528 self.tgtplayer = 1
1529
1530class Vortex(Card):
1531 """Sulfuric Vortex"""
1532 def __init__(self):
1533 super(Vortex, self).__init__()
1534 self.type = "Enchantment"
1535 self.damage = 0
1536 self.mana = 3
1537 self.sick= 0
1538 self.name = "Vortex"
1539 self.tgtplayer = 1
1540
1541 def upkeepTrigger(self):
1542 sim.curPlayer.life -= 2
1543
1544class DelverOfSecrets(Card):
1545 """Delver of Secrets"""
1546 def __init__(self):
1547 super(DelverOfSecrets, self).__init__()
1548 self.damage = 1
1549 self.toughness = 1
1550 self.type = "Creature"
1551 self.sick = 1
1552 self.name = "Delver"
1553 self.mana = 1
1554
1555 def upkeepTrigger(self):
1556 temp = sim.curPlayer.myDeck.pop()
1557 if temp.type == "Instant" or temp.type == "Sorcery":
1558 self.damage = 3
1559 self.toughness = 2
1560 sim.curPlayer.myBoard.append(temp)
1561
1562class StormchaserMage(Card):
1563 """Stormchaser Mage"""
1564 def __init__(self):
1565 super(StormchaserMage, self).__init__()
1566 self.damage = 1
1567 self.toughness = 2
1568 self.type = "Creature"
1569 self.sick = 0
1570 self.name = "Stormchaser"
1571 self.prowess = 1
1572 self.mana = 2
1573
1574class Preordain(Card):
1575 """Preordain"""
1576 def __init__(self):
1577 super(Preordain, self).__init__()
1578 self.type = "Sorcery"
1579 self.damage = 0
1580 self.mana = 1
1581 self.sick = 0
1582 self.name = "Preordain"
1583 self.targets = 0
1584 self.cardsDrawn = 1
1585
1586 def additionalPlay(self):
1587 sim.curPlayer.scry(2)
1588 sim.curPlayer.drawCard()
1589
1590class Counterspell(Card):
1591 """Counterspell"""
1592 def __init__(self):
1593 super(Counterspell, self).__init__()
1594 self.type = "Instant"
1595 self.damage = 0
1596 self.mana = 2
1597 self.sick = 0
1598 self.name = "Force Spike"
1599 self.targets = 1
1600 self.counter = 1
1601
1602class ForceSpike(Card):
1603 """Force Spike, actually hard counters stuff"""
1604 def __init__(self):
1605 super(ForceSpike, self).__init__()
1606 self.type = "Instant"
1607 self.damage = 0
1608 self.mana = 1
1609 self.sick = 0
1610 self.name = "Force Spike"
1611 self.targets = 1
1612 self.counter = 1
1613
1614class Cryptic(Card):
1615 """Cryptic Command, counter/draw only"""
1616 def __init__(self):
1617 super(Cryptic, self).__init__()
1618 self.type = "Instant"
1619 self.damage = 0
1620 self.mana = 4
1621 self.sick = 0
1622 self.name = "Cryptic"
1623 self.targets = 1
1624 self.counter = 1
1625 self.cardsDrawn = 1
1626
1627 def additionalPlay(self):
1628 sim.curPlayer.drawCard()
1629
1630class Berserker(Card):
1631 """Scab-Clan Berserker"""
1632 def __init__(self):
1633 super(Berserker, self).__init__()
1634 self.type = "Creature"
1635 self.damage = 3
1636 self.mana = 3
1637 self.sick = 0
1638 self.name = "Berserker"
1639 self.toughness = 3
1640
1641class Sigarda(Card):
1642 """Sigarda, Host of Herons"""
1643 def __init__(self):
1644 super(Sigarda, self).__init__()
1645 self.type = "Creature"
1646 self.damage = 5
1647 self.mana = 5
1648 self.sick = 0
1649 self.name = "Sigarda"
1650 self.toughness = 5
1651
1652class Nacatl(Card):
1653 """Wild Nacatl"""
1654 def __init__(self):
1655 super(Nacatl, self).__init__()
1656 self.type = "Creature"
1657 self.damage = 3
1658 self.mana = 1
1659 self.sick = 1
1660 self.name = "Nacatl"
1661 self.toughness = 3
1662
1663class Top(object):
1664 """Sensei's Divining Top, doesn't work"""
1665 #This card does not work.
1666 def __init__(self):
1667 self.type = "Top"
1668 self.damage = 0
1669 self.mana = 1
1670 self.sick = 0
1671 self.name = "Top"
1672 self.targets = 0
1673 self.cardsDrawn = 0
1674
1675 def useTop(self):
1676 mode = self.topMode
1677 topList = []
1678 wanted = []
1679 unwanted = []
1680 for x in range(0, 3):
1681 sim.debug(sim.myHand)
1682 topList.append(sim.myDeck.pop())
1683 if (mode == "mana"):
1684 self.debug("Using Top for mana")
1685 sim.myHand.sort(key=lambda x: x.type)
1686 for card in topList:
1687 if (card.type != "Land"):
1688 unwanted.append(card)
1689 if(card.type == "Land"):
1690 wanted.append(card)
1691 for card in unwanted:
1692 sim.knownCards.append(card)
1693 sim.myDeck.append(card)
1694 topList = wanted
1695 wanted = []
1696 unwanted = []
1697 for card in topList:
1698 if card == Land:
1699 unwanted.append(card)
1700 if card == Fetch:
1701 wanted.append(card)
1702 for card in unwanted:
1703 sim.knownCards.append(card)
1704 sim.myDeck.append(card)
1705 for card in wanted:
1706 sim.knownCards.append(card)
1707 sim.myDeck.append(card)
1708
1709 if (mode == "damage"):
1710 self.debug("Using Top for damage")
1711 sim.myHand.sort(key=lambda x: x.type)
1712 for card in topList:
1713 if (card.type == "Land"):
1714 unwanted.append(card)
1715 if(card.type != "Land"):
1716 wanted.append(card)
1717 for card in unwanted:
1718 sim.knownCards.append(card)
1719 sim.myDeck.append(card)
1720 topList = wanted
1721 sim.myHand.sort(key=lambda x: x.damage, reverse = True)
1722 while (len(topList) > 0):
1723 card = topList.pop()
1724 sim.knownCards.append(card)
1725 sim.myDeck.append(card)
1726
1727 def tapTop(self):
1728 if self.cardsin(Top, self.myBoard) > 0:
1729 sim.drawCard()
1730 for i, o in enumerate(self.myBoard):
1731 if o.name == "Top":
1732 del self.myBoard[i]
1733 break
1734 sim.myDeck.append(Top())
1735 sim.knownCards.append(Top())
1736
1737 def play(self):
1738 if (any(isinstance(x, Top) for x in sim.myHand) and sim.availableMana >= Top().mana):
1739 for i, o in enumerate(self.myHand):
1740 if o.name == "Top":
1741 del self.myHand[i]
1742 break
1743 self.myBoard.append(Top())
1744 self.availableMana -= Top().mana
1745 sim.curPlayer.prowess += 1
1746 self.debug("Playing Top")
1747
1748 def getDamage(self):
1749 return self.damage
1750
1751
1752class Player(object):
1753 """Player class, contains data common to both players or to inherit from"""
1754 def __init__(self):
1755 self.life = 20
1756 self.myDeck = []
1757 self.myHand = []
1758 self.myGrave = []
1759 self.myBoard = []
1760 self.myStack = []
1761 self.mulligansTaken = 0
1762 self.mulliganNoLand = 0
1763 self.mulliganAllLand = 0
1764 self.mulliganNoCreatures = 0
1765 self.expensiveHand = 0
1766 self.maxMana = 0
1767 self.availableMana = 0
1768 self.openingHand = 7
1769 self.knownCards = []
1770 self.prowess = 0
1771 self.powerOnBoard = 0
1772 self.lavaAct = 0
1773 self.blockers = []
1774 self.unblockedAttackers = []
1775 self.otherPermanents = []
1776 self.potentialBlockers = []
1777 self.blockedAttackers = []
1778 self.fetchCount = 0
1779 self.landCount = 0
1780 self.ringCount = 0
1781 self.eidolonCount = 0
1782 self.berserkerCount = 0
1783 self.nacatlCount = 0
1784 self.ForgottenCaveCount = 0
1785 self.hellsparkCount = 0
1786 self.swiftspearCount = 0
1787 self.guideCount = 0
1788 self.marauderCount = 0
1789 self.vexingCount = 0
1790 self.riftCount = 0
1791 self.fireblastCount = 0
1792 self.atarkaCount = 0
1793 self.incinerateCount = 0
1794 self.boltCount = 0
1795 self.chainCount = 0
1796 self.jetCount = 0
1797 self.topCount = 0
1798 self.probeCount = 0
1799 self.firecraftCount = 0
1800 self.vortexCount = 0
1801 self.lavamancerCount = 0
1802 self.serumCount = 0
1803 self.crypticCount = 0
1804 self.forcespikeCount = 0
1805 self.counterspellCount = 0
1806 self.preordainCount = 0
1807 self.stormchaserCount = 0
1808 self.searingCount = 0
1809 self.delverCount = 0
1810 self.birdsCount = 0
1811 self.explorerCount = 0
1812 self.truthsCount = 0
1813 self.sakuraCount = 0
1814 self.sigardaCount = 0
1815 self.type = "Player"
1816
1817 def sethellsparkCount(self, new):
1818 self.hellsparkCount = new
1819
1820 def gethellsparkCount(self):
1821 return self.hellsparkCount
1822
1823 def getMana(self):
1824 return self.availableMana
1825
1826 def shuffle(self):
1827 sim.debug("Beginning shuffle...")
1828 random.shuffle(self.myDeck)
1829 self.knownCards = []
1830 sim.debug("Shuffle finished, known cards emptied")
1831
1832 def deckList(self):
1833 pass
1834
1835 def resolveStack(self):
1836#Get opponent counters
1837 counters = 0
1838 for card in sim.nAP.myHand:
1839 if card.counter == 1:
1840 counters += 1
1841 plays = True
1842 while counters > 0 and plays == True:
1843 plays = False
1844 for card in sim.nAP.myHand:
1845 if card.mana <= sim.nAP.availableMana and len(self.myStack) > 0 and card.counter > 0:
1846 card.play()
1847 counters -= 1
1848 plays = True
1849 del sim.curPlayer.myStack[::-1]
1850 for card in sim.curPlayer.myStack:
1851 message = "Resolving " + str(card.getName())
1852 sim.debug(message)
1853 if card.type == "Creature":
1854 sim.curPlayer.myBoard.append(card)
1855 card.etbTrigger()
1856 if card.type == "Sorcery" or card.type == "Instant":
1857 sim.curPlayer.prowess += 1
1858 card.getTargets()
1859 if card.target.type == "Player":
1860 sim.nAP.life -= card.damage
1861 else:
1862 card.damageTaken += card.damage
1863 sim.curPlayer.myGrave.append(card)
1864 if card.type == "Enchantment":
1865 sim.curPlayer.prowess += 1
1866 sim.curPlayer.myBoard.append(card)
1867 sim.curPlayer.myStack = []
1868
1869 def mulligan(self):
1870 sim.debug("Starting mulligan...")
1871 self.mulligansTaken += 1
1872 sim.debug("Returning cards")
1873 for x in range(0, len(self.myHand)):
1874 self.myDeck.append(self.myHand.pop())
1875 self.shuffle()
1876 sim.debug("Shuffling cards")
1877 sim.debug("Mulligan finished")
1878
1879 def getBurn(self):
1880 sim.debug("Calculating burn in hand")
1881 burnInHand = 0
1882 for card in self.myHand:
1883 if card.type == "Sorcery" or card.type == "Instant":
1884 burnInHand += card.damage
1885 sim.debug("Burn in hand is " + str(burnInHand))
1886 return burnInHand
1887
1888 def playLand(self):
1889 sim.debug("Evaluating land drop")
1890 landDrop = 0
1891 if sim.cardsin(Fetch, sim.curPlayer.myHand) > 0 and sim.cardsin(Land, sim.curPlayer.myDeck) > 0 and landDrop == 0:
1892 landDrop += 1
1893 sim.debug("Playing fetch")
1894 for i, o in enumerate(sim.curPlayer.myHand):
1895 if o.name == "Fetch":
1896 del sim.curPlayer.myHand[i]
1897 break
1898 sim.curPlayer.myBoard.append(Fetch())
1899 if sim.cardsin(Land, sim.curPlayer.myHand) > 0 and landDrop == 0:
1900 landDrop += 1
1901 sim.debug("Playing land")
1902 for i, o in enumerate(sim.curPlayer.myHand):
1903 if o.name == "Land":
1904 del sim.curPlayer.myHand[i]
1905 break
1906 sim.curPlayer.myBoard.append(Land())
1907 if sim.cardsin(Ring, sim.curPlayer.myHand) > 0 and landDrop == 0:
1908 landDrop += 1
1909 sim.debug("Playing ring")
1910 for i, o in enumerate(sim.curPlayer.myHand):
1911 if o.name == "Ring":
1912 del sim.curPlayer.myHand[i]
1913 break
1914 sim.curPlayer.myBoard.append(Ring())
1915 if sim.cardsin(ForgottenCave, sim.curPlayer.myHand) > 0 and landDrop == 0:
1916 landDrop += 1
1917 sim.debug("Playing Forgotten Cave")
1918 for i, o in enumerate(sim.curPlayer.myHand):
1919 if o.name == "ForgottenCave":
1920 del sim.curPlayer.myHand[i]
1921 break
1922 sim.curPlayer.myBoard.append(ForgottenCave())
1923
1924 def useFetch(self):
1925 if (any(isinstance(x, Fetch) for x in sim.curPlayer.myBoard) and any(isinstance(y, Land) for y in sim.curPlayer.myDeck)):
1926 sim.debug("Using Fetch for mana")
1927 for i, o in enumerate(sim.curPlayer.myBoard):
1928 if o.name == "Fetch":
1929 del sim.curPlayer.myBoard[i]
1930 break
1931 for i, o in enumerate(sim.curPlayer.myDeck):
1932 if o.name == "Land":
1933 del sim.curPlayer.myDeck[i]
1934 break
1935 sim.curPlayer.myBoard.append(Land())
1936 sim.curPlayer.myGrave.append(Fetch())
1937 sim.curPlayer.availableMana += 1
1938 sim.curPlayer.shuffle()
1939
1940 def drawCard(self):
1941 self.myDraw = []
1942 if(len(self.myDeck) > 0):
1943 self.myDraw.append(self.myDeck.pop())
1944 if sim.curPlayer.deckName == "Burn" and sim.draw == 1:
1945 sim.recordDraw()
1946 if len(self.knownCards) > 0:
1947 thing = self.knownCards.pop()
1948 sim.debug("Drawing card (" + str(self.myDraw[0]) + ")")
1949 sim.debug("Cards remaining: " + str(len(self.myDeck)))
1950 self.myHand.append(self.myDraw[0])
1951
1952 def buildDeck(self):
1953 sim.debug("Beginning deck building")
1954 self.myDeck = []
1955 self.myBoard = []
1956 self.myHand = []
1957 self.myGrave = []
1958 self.myStack = []
1959## for y in range(0, len(cardlist)):
1960## for x in cardlist:
1961## self.myDeck.append(cardlist+"()")
1962 for x in range(0, sim.curPlayer.birdsCount):
1963 self.myDeck.append(Birds())
1964 for x in range(0, sim.curPlayer.topCount):
1965 self.myDeck.append(Top())
1966 for x in range(0, self.fetchCount):
1967 self.myDeck.append(Fetch())
1968 for x in range(0, self.landCount):
1969 self.myDeck.append(Land())
1970 for x in range(0, self.eidolonCount):
1971 self.myDeck.append(Eidolon())
1972 for x in range(0, self.hellsparkCount):
1973 self.myDeck.append(Hellspark())
1974 for x in range(0, self.swiftspearCount):
1975 self.myDeck.append(Swiftspear())
1976 for x in range(0, self.guideCount):
1977 self.myDeck.append(Guide())
1978 for x in range(0, self.marauderCount):
1979 self.myDeck.append(Marauder())
1980 for x in range(0, self.vexingCount):
1981 self.myDeck.append(Vexing())
1982 for x in range(0, self.riftCount):
1983 self.myDeck.append(Rift())
1984 for x in range(0, self.fireblastCount):
1985 self.myDeck.append(Fireblast())
1986 for x in range(0, self.atarkaCount):
1987 self.myDeck.append(Atarka())
1988 for x in range(0, self.incinerateCount):
1989 self.myDeck.append(Incinerate())
1990 for x in range(0, self.boltCount):
1991 self.myDeck.append(Bolt())
1992 for x in range(0, self.chainCount):
1993 self.myDeck.append(Chain())
1994 for x in range(0, self.jetCount):
1995 self.myDeck.append(Jet())
1996 for x in range(0, self.probeCount):
1997 self.myDeck.append(Probe())
1998 for x in range(0, self.ForgottenCaveCount):
1999 self.myDeck.append(ForgottenCave())
2000 for x in range(0, self.firecraftCount):
2001 self.myDeck.append(Firecraft())
2002 for x in range(0, self.vortexCount):
2003 self.myDeck.append(Vortex())
2004 for x in range(0, self.lavamancerCount):
2005 self.myDeck.append(Lavamancer())
2006 for x in range(0, self.ringCount):
2007 self.myDeck.append(Ring())
2008 for x in range(0, self.serumCount):
2009 self.myDeck.append(Serum())
2010 for x in range(0, self.crypticCount):
2011 self.myDeck.append(Cryptic())
2012 for x in range(0, self.forcespikeCount):
2013 self.myDeck.append(ForceSpike())
2014 for x in range(0, self.counterspellCount):
2015 self.myDeck.append(Counterspell())
2016 for x in range(0, self.preordainCount):
2017 self.myDeck.append(Preordain())
2018 for x in range(0, self.stormchaserCount):
2019 self.myDeck.append(StormchaserMage())
2020 for x in range(0, self.delverCount):
2021 self.myDeck.append(DelverOfSecrets())
2022 for x in range(0, self.searingCount):
2023 self.myDeck.append(SearingBlaze())
2024 for x in range(0, self.berserkerCount):
2025 self.myDeck.append(Berserker())
2026 for x in range(0, self.nacatlCount):
2027 self.myDeck.append(Nacatl())
2028 for x in range(0, self.explorerCount):
2029 self.myDeck.append(Explorer())
2030 for x in range(0, self.sakuraCount):
2031 self.myDeck.append(Sakura())
2032 for x in range(0, self.truthsCount):
2033 self.myDeck.append(Truths())
2034
2035 random.shuffle(self.myDeck)
2036 sim.debug("Deck built")
2037
2038 def resolveMulligans(self):
2039 pass
2040
2041 def declareBlocks(self):
2042 """Blocking, I'm sorry"""
2043 #Set up variables
2044 sim.nAP.potentialBlockers = []
2045 sim.curPlayer.blockedAttackers = []
2046 sim.curPlayer.unblockedAttackers = []
2047 blkPwr = []
2048 blkTough = []
2049 defClock = 0
2050 atkPwr = []
2051 atkTough = []
2052 #Find my clock
2053 for card in sim.nAP.myBoard:
2054 if card.type == "Creature":
2055 defClock += card.damage
2056 atkClock = 0
2057 #Find known attacker clock
2058 for card in sim.curPlayer.myBoard:
2059 if card.type == "Creature":
2060 atkClock += card.damage
2061 #Block if opponent will win first
2062 if atkClock > defClock and len(sim.nAP.potentialBlockers) > 0:
2063 sim.nAP.myBoardCpy = sim.nAP.myBoard
2064 #Make list of potential blockers
2065 for card in sim.nAP.myBoardCpy:
2066 if card.type == "Creature" and card.tapped == 0:
2067 sim.nAP.potentialBlockers.append(card)
2068 blkPwr.append(card.damage)
2069 blkTough.append(card.toughness)
2070 sim.nAP.myBoard.remove(card)
2071 for card in sim.curPlayer.attackers:
2072 atkPwr.append(card.power)
2073 atkTough.append(card.toughness)
2074 toblock = []
2075#Highest power blocker on highest toughness attacker it can kill
2076 bigBlockIdx = blkPwr.index(max(blkPwr))
2077 bigBlock = max(blkPwr)
2078 atkIdx = None
2079 #find highest toughness I can trade with, I should use a do/while
2080 highest = 0
2081 for val in range(len(sim.curPlayer.atkTough)):
2082 if sim.curPlayer.atkTough[val] >= highest and highest <= bigBlock:
2083 highest = sim.curPlayer.atkTough[val]
2084 atkIdx = val
2085 while atkIdx != None:
2086 sim.nAP.potentialBlockers[bigBlockIdx].blocking = sim.curPlayer.attackers[atkIdx]
2087 sim.curPlayer.attackers[atkIdx].blockedBy = sim.nAP.potentialBlockers[bigBlockIdx]
2088 sim.nAP.myBoard.append(sim.nAP.potentialBlockers[bigBlockIdx])
2089 del sim.nAP.potentialBlockers[bigBlockIdx]
2090 sim.curPlayer.blockedAttackers.append(sim.curPlayer.attackers[atkIdx])
2091 del sim.curPlayer.attackers[atkIdx]
2092 del sim.curPlayer.atkPwr[atkIdx]
2093 del sim.curPlayer.atkTough[atkIdx]
2094 atkIdx = None
2095 bigBlockIdx = blkPwr.index(max(blkPwr))
2096 bigBlock = max(blkPwr)
2097 highest = 0
2098 #find highest toughness I can trade with
2099 for val in range(len(sim.curPlayer.atkTough)):
2100 if sim.curPlayer.atkTough[val] >= highest and highest <= bigBlock:
2101 highest = sim.curPlayer.atkTough[val]
2102 atkIdx = val
2103
2104#Blockers with toughness > opposing power on remaining attackers, so they bounce vs die
2105 bigBlockIdx = blkTough.index(max(blkTough))
2106 bigBlock = max(blkTough)
2107 atkIdx = None
2108 highest = 0
2109 for val in range(len(sim.curPlayer.atkPwr)):
2110 if sim.curPlayer.atkPwr[val] < highest and highest < bigBlock:
2111 highest = sim.curPlayer.atkPwr[val]
2112 atkIdx = val
2113 while atkIdx != None:
2114 sim.nAP.potentialBlockers[bigBlockIdx].blocking = sim.curPlayer.attackers[atkIdx]
2115 sim.curPlayer.attackers[atkIdx].blockedBy = sim.nAP.potentialBlockers[bigBlockIdx]
2116 sim.nAP.myBoard.append(sim.nAP.potentialBlockers[bigBlockIdx])
2117 del sim.nAP.potentialBlockers[bigBlockIdx]
2118 sim.curPlayer.blockedAttackers.append(sim.curPlayer.attackers[atkIdx])
2119 del sim.curPlayer.attackers[atkIdx]
2120 bigBlockIdx = blkTough.index(max(blkTough))
2121 bigBlock = max(blkTough)
2122 atkIdx = None
2123 highest = 0
2124 for val in range(len(sim.curPlayer.atkPwr)):
2125 if sim.curPlayer.atkPwr[val] < highest and highest < bigBlock:
2126 highest = sim.curPlayer.atkPwr[val]
2127 atkIdx = val
2128#Chump blocks to change clock speed
2129 defDmg = 0
2130 for card in sim.nAP.myBoard:
2131 if card.type == "Creature":
2132 defDmg += card.damage
2133 for card in sim.nAP.potentialBlockers:
2134 defDmg += card.damage
2135 atkDmg = 0
2136 for card in sim.curPlayer.attackers:
2137 atkDmg += card.damage
2138 defClock = math.ceil((sim.curPlayer.life - getBurn()) / defDmg)
2139 atkClock = math.ceil((sim.nAP.life / atkDmg))
2140 lifegain = 0
2141 while atkClock >= defClock and len(sim.curPlayer.attackers) > 0 and len(sim.nAP.potentialBlockers) > 0 and len(atkClock)< 5:
2142 smallBlockIdx = blkPwr.index(min(blkPwr))
2143 smallBlock = min(blkPwr)
2144 atkIdx = None
2145 #find highest power I can chump
2146 atkIdx = sim.curPlayer.atkPwr.index(max(sim.curPlayer.atkPwr))
2147 lifegain += max(sim.curPlayer.atkPwr)
2148 sim.nAP.potentialBlockers[smallBlockIdx].blocking = sim.curPlayer.attackers[atkIdx]
2149 sim.curPlayer.attackers[atkIdx].blockedBy = sim.nAP.potentialBlockers[smallBlockIdx]
2150 sim.nAP.myBoard.append(sim.nAP.potentialBlockers[smallBlockIdx])
2151 del sim.nAP.potentialBlockers[smallBlockIdx]
2152 sim.curPlayer.blockedAttackers.append(sim.curPlayer.attackers[atkIdx])
2153 del sim.curPlayer.attackers[atkIdx]
2154 del sim.curPlayer.atkPwr[atkIdx]
2155 del sim.curPlayer.atkTough[atkIdx]
2156 defDmg = 0
2157 for card in sim.nAP.myBoard:
2158 if card.type == "Creature":
2159 defDmg += card.damage
2160 for card in sim.nAP.potentialBlockers:
2161 defDmg += card.damage
2162 atkDmg = 0
2163 for card in sim.curPlayer.attackers:
2164 atkDmg += card.damage
2165 defClock = math.ceil((sim.curPlayer.life - getBurn()) / defDmg)
2166 atkClock = math.ceil((sim.nAP.life + lifegain)/ atkDmg)
2167 #Move everything not blocked to unblocked attackers
2168 for card in sim.curPlayer.attackers:
2169 sim.curPlayer.unblockedAttackers.append(card)
2170
2171
2172 def declareAttacks(self):
2173 """Declare attacks. I'm so, so, so sorry for this code"""
2174 sim.debug("Declaring Attacks")
2175 sim.debug("Adding Prowess")
2176 #Add prowess
2177 for card in sim.curPlayer.myBoard:
2178 if card.type == "Creature" and card.prowess == 1:
2179 card.damage += sim.curPlayer.prowess
2180 card.toughness += sim.curPlayer.prowess
2181 for card in sim.nAP.myBoard:
2182 if card.type == "Creature" and card.prowess == 1:
2183 card.damage += sim.nAP.prowess
2184 card.toughness += sim.nAP.prowess
2185 #Set up lists
2186 sim.curPlayer.atkPwr = []
2187 sim.curPlayer.potentialAttacks = []
2188 sim.curPlayer.attackers = []
2189 sim.curPlayer.otherPermanents = []
2190
2191 #Get potential attackers/blockers
2192 sim.curPlayer.potentialBlocks = []
2193 for card in sim.nAP.myBoard:
2194 if card.type == "Creature" and card.tapped == 0:
2195 sim.curPlayer.potentialBlocks.append(card)
2196
2197 for card in sim.curPlayer.myBoard:
2198 if card.type == "Creature" and card.tapped == 0 and card.sick < 1:
2199 sim.curPlayer.potentialAttacks.append(card)
2200 msg = card.name + " is potentially attacking"
2201 sim.debug(msg)
2202 sim.curPlayer.atkPwr.append(card.damage)
2203 else:
2204 sim.curPlayer.otherPermanents.append(card)
2205
2206 #Look at impact of all attacking
2207 if sum(sim.curPlayer.atkPwr) > 0:
2208 sim.debug("Attacks are possible")
2209 myClock = math.ceil((sim.nAP.life - sim.curPlayer.getBurn())/sum(sim.curPlayer.atkPwr))
2210 oppPwr = []
2211 for card in sim.nAP.myBoard:
2212 if card.type == "Creature":
2213 oppPwr.append(card.damage)
2214 if sum(oppPwr) == 0:
2215 oppPwr.append(0.001)
2216 oppClock = math.ceil(sim.curPlayer.life/sum(oppPwr))
2217 lifegained = 0
2218#Remove attackers to slow opp clock
2219 while oppClock < myClock and len(sim.curPlayer.atkPwr) > 0:
2220 idx = sim.curPlayer.atkPwr.index(min(sim.curPlayer.atkPwr))
2221 card = sim.curPlayer.potentialAttacks[idx]
2222 msg = card.name + " is not attacking"
2223 sim.debug(msg)
2224 sim.curPlayer.otherPermanents.append(sim.curPlayer.potentialAttacks[idx])
2225 del sim.curPlayer.potentialAttacks[idx]
2226 del sim.curPlayer.atkPwr[idx]
2227 blkIdx = oppPwr.index(max(oppPwr))
2228 lifegained += max(oppPwr)
2229 del oppPwr[blkIdx]
2230 x = sum(sim.curPlayer.atkPwr)
2231 if x == 0:
2232 x = .001
2233 if sum(oppPwr) == 0:
2234 oppPwr.append(0.001)
2235 myClock = math.ceil((sim.nAP.life - sim.curPlayer.getBurn())/x)
2236 oppClock = math.ceil((sim.curPlayer.life + lifegained)/ sum(oppPwr))
2237#Remove attackers if nothing gets through
2238 if len(sim.curPlayer.potentialAttacks) < len(sim.curPlayer.potentialBlockers):
2239 sim.debug("No profitable attacks")
2240 for card in sim.curPlayer.potentialAttacks:
2241 sim.curPlayer.otherPermanents.append(card)
2242 sim.curPlayer.potentialAttacks = []
2243#Finalize attacks
2244 sim.curPlayer.attackers = sim.curPlayer.potentialAttacks
2245 msg = "Attackers are " + str(sim.curPlayer.attackers)
2246 sim.debug(msg)
2247 msg = "Everything else is " + str(sim.curPlayer.otherPermanents)
2248 sim.debug(msg)
2249
2250class P1(Player):
2251 """Player 1"""
2252 def __init__(self):
2253 """P1 variables, basically decklist and life"""
2254 super(P1, self).__init__()
2255 self.life = 20
2256#25 Land, control
2257 self.fetchCount = 0
2258 self.landCount = 26
2259 self.ringCount = 0
2260 self.ForgottenCaveCount = 0
2261 self.eidolonCount = 0
2262 self.hellsparkCount = 0
2263 self.swiftspearCount = 0
2264 self.guideCount = 10
2265 self.marauderCount = 0
2266 self.vexingCount = 0
2267 self.riftCount = 0
2268 self.fireblastCount = 0
2269 self.atarkaCount = 0
2270 self.incinerateCount = 0
2271 self.boltCount = 0
2272 self.chainCount = 0
2273 self.firecraftCount = 0
2274 self.vortexCount = 0
2275 self.lavamancerCount = 0
2276 self.serumCount = 0
2277 self.searingCount = 0
2278 self.nacatlCount = 0
2279 self.berserkerCount = 0
2280 self.birdsCount = 4
2281 self.sakuraCount = 4
2282 self.explorerCount = 4
2283 self.truthsCount = 14
2284 self.sigardaCount = 8
2285 self.deckName = "Burn"
2286
2287 def getBlockers(self):
2288 """Finds number of blockers opponent has"""
2289 blockers = 0
2290 if len(sim.nAP.myBoard) > 0:
2291 for card in sim.nAP.myBoard:
2292 if card.type == "Creature" and card.tapped == 0:
2293 blockers + 1
2294 return blockers
2295
2296 def negs(self):
2297 """Reasons to not play a spell"""
2298#Overextension
2299 blockers = self.getBlockers()
2300 attackers = 0
2301 for x in range(len(sim.curPlayer.myBoard)):
2302 if (sim.curPlayer.myBoard[x].type == "Creature"):
2303 attackers += 1
2304 for x in range(len(self.myHand)):
2305 if attackers - blockers > 2:
2306 if self.myHand[x].type == "Creature":
2307 self.cardScore[x] -= 3
2308
2309 def getClock(self):
2310 """Get my clock"""
2311 clock = 9999
2312 for card in self.myBoard:
2313 if card.type == "Creature":
2314 self.powerOnBoard += card.damage
2315 if self.powerOnBoard != 0:
2316 clock = math.ceil(sim.nAP.life/self.powerOnBoard)
2317 return clock
2318
2319 def getNewClock(self, newcard):
2320 """Get clock if new card played"""
2321 clock = 9999
2322 if newcard.damage > 0:
2323 self.powerOnBoard = 0
2324 for card in self.myBoard:
2325 if card.type == "Creature":
2326 self.powerOnBoard += card.damage * (card.sick + 1)
2327 if newcard.type == "Instant" or newcard.type == "Sorcery":
2328 if self.powerOnBoard != 0:
2329 clock = math.ceil((sim.nAP.life - newcard.damage)/self.powerOnBoard)
2330 if newcard.type == "Creature":
2331 if newcard.sick == 0:
2332 clock = math.ceil(sim.nAP.life/(self.powerOnBoard + newcard.damage))
2333 if newcard.sick == 1:
2334 clock = math.ceil((sim.nAP.life + newcard.damage)/(self.powerOnBoard + newcard.damage))
2335 return clock
2336
2337 def plusses(self):
2338 """Reasons to play a spell"""
2339 #Bonus for number of targets, makes higher value for 2 for 1's
2340 for x in range(len(self.myHand)):
2341 self.cardScore[x] += self.myHand[x].targets
2342 #Bonus for drawing cards, makes cantrips and 2 for 1's better
2343 for x in range(len(self.myHand)):
2344 self.cardScore[x] += self.myHand[x].cardsDrawn
2345 #Bonus for speeding clock
2346 for x in range(len(self.myHand)):
2347 if self.getNewClock(self.myHand[x]) < self.getClock():
2348 self.cardScore[x] += 3
2349 #Bonus for highest impact
2350 highDamage = 0
2351 for card in self.myHand:
2352 if card.damage >= highDamage:
2353 highDamage = card.damage
2354 for x in range(len(self.myHand)):
2355 if self.myHand[x].damage >= highDamage:
2356 self.cardScore[x] += 1
2357 #Bonus for dodging interaction
2358 for x in range(len(self.myHand)):
2359 if self.myHand[x].type != "Creature":
2360 self.cardScore[x] += 1
2361 #Bonus for burning opponent out
2362 burn = sim.curPlayer.getBurn()
2363 for x in range(len(self.myHand)):
2364 if burn >= sim.nAP.life and self.myHand[x].type == "Instant" or burn >= sim.nAP.life and self.myHand[x].type == "Sorcery":
2365 self.cardScore[x] += 5
2366 #Bonus for early creature
2367 if sim.turn <= 2:
2368 for x in range(len(self.myHand)):
2369 if self.myHand[x].type == "Creature":
2370 self.cardScore[x] += 1
2371 #Bonus for cycling land
2372 if sim.curPlayer.availableMana >= 3:
2373 for x in range(len(self.myHand)):
2374 if self.myHand[x].cycling == 1:
2375 self.cardScore[x] += 1
2376 #Bonus for mana dork
2377 if sim.turn <= 2:
2378 for x in range(len(self.myHand)):
2379 if self.myHand[x].name == "Birds":
2380 self.cardScore[x] += 3
2381 def findCurve(self):
2382 """Builds mana curve, creates bonus for positive tempo"""
2383 #Uses all mana
2384 for x in range(len(self.myHand)):
2385 if self.myHand[x].mana == self.availableMana:
2386 self.cardScore[x] += 1
2387 #Cast 2 2's
2388 if self.availableMana == 4 and self.manaList[2] >= 2:
2389 for x in range(len(self.myHand)):
2390 if self.myHand[x].mana == 2:
2391 self.cardScore[x] += 3
2392 #Cast 2 1's
2393 if self.availableMana == 2 and self.manaList[1] >= 2:
2394 for x in range(len(self.myHand)):
2395 if self.myHand[x].mana == 1:
2396 self.cardScore[x] += 3
2397 #Cast 0's
2398 for x in range(len(self.myHand)):
2399 if self.myHand[x].mana == 0:
2400 self.cardScore[x] += 10
2401
2402 def buildManaList(self):
2403 """2d array of cards in hand by cost"""
2404 self.manaList = [0] * 15
2405 for card in self.myHand:
2406 self.manaList[card.mana] += 1
2407
2408 def join(self, hand):
2409 """Joins cards with card score to sort by rank"""
2410 joins = []
2411 for x in range(len(hand)):
2412 tup = self.myHand[x], self.cardScore[x]
2413 joins.append(tup)
2414 joins = sorted(joins, key=lambda x: x[1], reverse = True)
2415 self.myHand = []
2416 self.cardScore = []
2417 for x in range(len(joins)):
2418 self.myHand.append(joins[x][0])
2419 self.cardScore.append(joins[x][1])
2420
2421 def getPlays(self):
2422 """Create play list and score list"""
2423 self.cardScore = None
2424 self.cardScore = [0] * len(self.myHand)
2425 self.buildManaList()
2426 self.findCurve()
2427 self.plusses()
2428 self.negs()
2429 self.join(self.myHand)
2430 sim.debug(self.myHand)
2431 sim.debug(self.cardScore)
2432
2433 def scry(self, value):
2434 """Scry"""
2435 sim.debug("Scry " + str(value))
2436 mana = 0
2437 scryList = []
2438 self.myHand.sort(key=operator.attrgetter('type'))
2439 for card in self.myHand:
2440 if(card.type == "Land"):
2441 mana += 1
2442 mana += self.maxMana
2443 for x in range(0, value):
2444 scryList.append(self.myDeck.pop())
2445 scryList.sort(key=operator.attrgetter('damage'))
2446 for x in range(0, value):
2447 card = scryList.pop(0)
2448 if (card.damage == 0 and mana > 3):
2449 sim.debug(card.name)
2450 sim.debug("Scry to bottom")
2451 self.myDeck.insert(0, card)
2452 if (card.damage > 0):
2453 sim.debug(card.name)
2454 sim.debug("Scry to top")
2455 self.knownCards.append(card)
2456 self.myDeck.append(card)
2457 if (card.damage == 0 and self.maxMana <= 3):
2458 sim.debug(card.name)
2459 sim.debug("Scry to top")
2460 self.knownCards.append(card)
2461 self.myDeck.append(card)
2462
2463 def resolveMulligans(self):
2464 """Mulligan logic"""
2465 mulliganReasons = 1
2466 while(mulliganReasons > 0):
2467 mulliganReasons = 0
2468 sim.debug("P1: Determining mulligan")
2469 for x in range(self.openingHand):
2470 self.drawCard()
2471 recurring = 0
2472 land = 0
2473 spells = 0
2474 top = 0
2475 mana = 0
2476 for card in self.myHand:
2477 if card.type == "Creature":
2478 recurring += 1
2479 if card.type == "Land":
2480 land += 1
2481 if card.type == "Instant" or card.type == "Sorcery":
2482 spells += 1
2483 if card.type == "Top":
2484 top += 1
2485 mana += card.mana
2486#7 card decision
2487 if (len(self.myHand) == 7):
2488 sim.debug("P1: Evaluating 7 card keep")
2489 if (land < 2):
2490 sim.debug("P1: Mulligan no land")
2491 mulliganReasons += 1
2492 self.mulliganNoLand += 1
2493 if(land > 4):
2494 sim.debug("P1: Mulligan mana flood")
2495 mulliganReasons += 1
2496 self.mulliganAllLand += 1
2497 if (recurring < 1):
2498 sim.debug("P1: Mulligan no creatures")
2499 mulliganReasons += 1
2500 self.mulliganNoCreatures += 1
2501 if(top > 2):
2502 sim.debug("P1: Mulligan top flood")
2503 mulliganReasons += 1
2504 self.topFlood += 1
2505 x = 14 + (sim.cardsin(Fireblast, self.myHand) * 6)
2506 if(mana > x):
2507 sim.debug("P1: Mulligan expensive hand")
2508 mulliganReasons += 1
2509 self.expensiveHand += 1
2510
2511#6 card decision
2512 if (len(self.myHand) == 6):
2513 sim.debug("P1: Evaluating 6 card keep")
2514 if (land < 2):
2515 sim.debug("P1: Mulligan no land")
2516 mulliganReasons += 1
2517 self.mulliganNoLand += 1
2518 if(land > 3):
2519 sim.debug("P1: Mulligan mana flood")
2520 mulliganReasons += 1
2521 self.mulliganAllLand += 1
2522 if (recurring < 1):
2523 sim.debug("P1: Mulligan no creatures")
2524 mulliganReasons += 1
2525 self.mulliganNoCreatures += 1
2526 if(top > 2):
2527 sim.debug("P1: Mulligan top flood")
2528 mulliganReasons += 1
2529 self.topFlood += 1
2530 x = 13 + (sim.cardsin(Fireblast, self.myHand) * 6)
2531 if(mana > x):
2532 sim.debug("P1: Mulligan expensive hand")
2533 mulliganReasons += 1
2534 self.expensiveHand += 1
2535
2536#5 card decision
2537 if (len(self.myHand) == 5):
2538 sim.debug("P1: Evaluating 5 card keep")
2539 if (land < 1):
2540 sim.debug("P1: Mulligan no land")
2541 mulliganReasons += 1
2542 self.mulliganNoLand += 1
2543 if(land > 2):
2544 sim.debug("P1: Mulligan mana flood")
2545 mulliganReasons += 1
2546 self.mulliganAllLand += 1
2547 if (recurring < 1):
2548 sim.debug("P1: Mulligan no creatures")
2549 mulliganReasons += 1
2550 self.mulliganNoCreatures += 1
2551 if(top > 1):
2552 sim.debug("P1: Mulligan top flood")
2553 mulliganReasons += 1
2554 self.topFlood += 1
2555
2556#4 card decision
2557 if (len(self.myHand) == 4):
2558 sim.debug("P1: Evaluating 4 card keep")
2559 if (land < 1):
2560 sim.debug("P1: Mulligan no land")
2561 mulliganReasons += 1
2562 self.mulliganNoLand += 1
2563 if(land >= 4):
2564 sim.debug("P1: Mulligan mana flood")
2565 mulliganReasons += 1
2566 self.mulliganAllLand += 1
2567 if (recurring < 1):
2568 sim.debug("P1: Mulligan no creatures")
2569 mulliganReasons += 1
2570 self.mulliganNoCreatures += 1
2571 if(top > 2):
2572 sim.debug("P1: Mulligan top flood")
2573 mulliganReasons += 1
2574 self.topFlood += 1
2575
2576#3 card decision
2577 if (len(self.myHand) == 3):
2578 sim.debug("P1: Evaluating 3 card keep")
2579 if (land < 1):
2580 sim.debug("P1: Mulligan no land")
2581 mulliganReasons += 1
2582 self.mulliganNoLand += 1
2583 if(land >= 3):
2584 sim.debug("P1: Mulligan mana flood")
2585 mulliganReasons += 1
2586 self.mulliganAllLand += 1
2587 if (recurring < 1):
2588 sim.debug("P1: Mulligan no creatures")
2589 mulliganReasons += 1
2590 self.mulliganNoCreatures += 1
2591
2592 if (len(self.myHand) < 3):
2593 sim.debug("P1: Forced to keep 2 card hand")
2594
2595 if (mulliganReasons > 0):
2596 self.mulligan()
2597 self.openingHand -= 1
2598
2599class P2(Player):
2600 """See P1"""
2601 def __init__(self):
2602 super(P2, self).__init__()
2603 self.fetchCount = 0
2604 self.landCount = 60
2605 self.swiftspearCount = 0
2606 self.stormchaserCount = 0
2607 self.delverCount = 0
2608 self.riftCount = 0
2609 self.fireblastCount = 0
2610 self.boltCount = 0
2611 self.chainCount = 0
2612 self.probeCount = 0
2613 self.preordainCount = 0
2614 self.serumCount = 0
2615 self.firecraftCount = 0
2616 self.crypticCount = 0
2617 self.counterspellCount = 0
2618 self.forcespikeCount = 0
2619 self.deckName = "Delver"
2620
2621 def resolveMulligans(self):
2622 mulliganReasons = 1
2623 while(mulliganReasons != 0):
2624 mulliganReasons = 0
2625 sim.debug("P2: Determining mulligan")
2626 for x in range(self.openingHand):
2627 self.drawCard()
2628 recurring = 0
2629 land = 0
2630 removal = 0
2631 cantrip = 0
2632 counter = 0
2633 mana = 0
2634
2635 for card in self.myHand:
2636 if card.type == "Creature":
2637 recurring += 1
2638 if card.type == "Land":
2639 land += 1
2640 if card.type == "Instant" or card.type == "Sorcery":
2641 if card.damage > 0:
2642 removal += 1
2643 if card.cardsDrawn > 0:
2644 cantrip += 1
2645 if card.targets > 0 and card.damage <= 0:
2646 counter += 1
2647 mana += card.mana
2648
2649#7 card decision
2650 if (len(self.myHand) == 7):
2651 sim.debug("P2: Evaluating 7 card keep")
2652 if (recurring < 1):
2653 sim.debug("P2: Mulligan no creatures")
2654 mulliganReasons += 1
2655 self.mulliganNoCreatures += 1
2656 if (counter <1):
2657 sim.debug("P2: Mulligan no counters")
2658 mulliganReasons += 1
2659 if (land < 1):
2660 sim.debug("P2: Mulligan no land")
2661 mulliganReasons += 1
2662 self.mulliganNoLand += 1
2663 if(land > 3):
2664 sim.debug("P2: Mulligan mana flood")
2665 mulliganReasons += 1
2666 self.mulliganAllLand += 1
2667 if(cantrip < 1):
2668 sim.debug("P2: Mulligan no cantrips")
2669 mulliganReasons += 1
2670 if (removal < 1):
2671 sim.debug("P2: Mulligan no removal")
2672 mulliganReasons += 1
2673 x = 9 + (sim.cardsin(Fireblast, self.myHand) * 6)
2674 if(mana > x):
2675 sim.debug("P2: Mulligan expensive hand")
2676 mulliganReasons += 1
2677 self.expensiveHand += 1
2678
2679 #6 card decision
2680 if (len(self.myHand) == 6):
2681 sim.debug("P2: Evaluating 6 card keep")
2682 if (recurring < 1):
2683 sim.debug("P2: Mulligan no creatures")
2684 mulliganReasons += 1
2685 self.mulliganNoCreatures += 1
2686 if (counter <1):
2687 sim.debug("P2: Mulligan no counters")
2688 mulliganReasons += 1
2689 if (land < 1):
2690 sim.debug("P2: Mulligan no land")
2691 mulliganReasons += 1
2692 self.mulliganNoLand += 1
2693 if(land > 3):
2694 sim.debug("P2: Mulligan mana flood")
2695 mulliganReasons += 1
2696 self.mulliganAllLand += 1
2697 if(cantrip < 1):
2698 sim.debug("P2: Mulligan no cantrips")
2699 mulliganReasons += 1
2700 if (removal < 1):
2701 sim.debug("P2: Mulligan no removal")
2702 mulliganReasons += 1
2703 x = 8 + (sim.cardsin(Fireblast, self.myHand) * 6)
2704 if(mana > x):
2705 sim.debug("P2: Mulligan expensive hand")
2706 mulliganReasons += 1
2707 self.expensiveHand += 1
2708
2709 #5 card decision
2710 if (len(self.myHand) == 5):
2711 sim.debug("P2: Evaluating 5 card keep")
2712 if (recurring < 1):
2713 sim.debug("P2: Mulligan no creatures")
2714 mulliganReasons += 1
2715 self.mulliganNoCreatures += 1
2716 if (land < 1):
2717 sim.debug("P2: Mulligan no land")
2718 mulliganReasons += 1
2719 self.mulliganNoLand += 1
2720 if(land > 3):
2721 sim.debug("P2: Mulligan mana flood")
2722 mulliganReasons += 1
2723 self.mulliganAllLand += 1
2724 x = 7 + (sim.cardsin(Fireblast, self.myHand) * 6)
2725 if(mana > x):
2726 sim.debug("P2: Mulligan expensive hand")
2727 mulliganReasons += 1
2728 self.expensiveHand += 1
2729
2730 #4 card decision
2731 if (len(self.myHand) == 4):
2732 sim.debug("P2: Evaluating 4 card keep")
2733 if (land < 1):
2734 sim.debug("P2: Mulligan no land")
2735 mulliganReasons += 1
2736 self.mulliganNoLand += 1
2737 x = 6 + (sim.cardsin(Fireblast, self.myHand) * 6)
2738 if(mana > x):
2739 sim.debug("P2: Mulligan expensive hand")
2740 mulliganReasons += 1
2741 self.expensiveHand += 1
2742
2743 #3 card decision
2744 if (len(self.myHand) == 3):
2745 sim.debug("P2: Evaluating 3 card keep")
2746 if (land < 1 and cantrip < 1):
2747 sim.debug("P2: Mulligan no land")
2748 mulliganReasons += 1
2749 self.mulliganNoLand += 1
2750
2751 if (len(self.myHand) < 3):
2752 sim.debug("P2: Forced to keep 2 card hand")
2753
2754 if (mulliganReasons > 0):
2755 self.mulligan()
2756 self.openingHand -= 1
2757
2758 def scry(self, value):
2759 sim.debug("Scry " + str(value))
2760 mana = 0
2761 scryList = []
2762 self.myHand.sort(key=operator.attrgetter('type'))
2763 for card in self.myHand:
2764 if(card.type == "Land"):
2765 mana += 1
2766 mana += self.maxMana
2767 for x in range(0, value):
2768 scryList.append(self.myDeck.pop())
2769 for x in range(0, value):
2770 card = scryList.pop(0)
2771 if (card.type != "Land"):
2772 self.knownCards.append(card)
2773 self.myDeck.append(card)
2774 sim.debug(card.name)
2775 sim.debug("Scry to top")
2776 else:
2777 sim.debug(card.name)
2778 sim.debug("Scry to bottom")
2779 self.myDeck.insert(0, card)
2780
2781
2782 def getBlockers(self):
2783 blockers = 0
2784 if len(sim.nAP.myBoard) > 0:
2785 for card in sim.nAP.myBoard:
2786 if card.type == "Creature" and card.tapped == 0:
2787 blockers + 1
2788 return blockers
2789
2790 def negs(self):
2791#Overextension
2792 blockers = self.getBlockers()
2793 attackers = 0
2794 for x in range(len(self.myBoard)):
2795 if (self.myBoard[x].type == "Creature"):
2796 attackers += 1
2797 for x in range(len(self.myHand)):
2798 if attackers - blockers > 2:
2799 if self.myHand[x].type == "Creature":
2800 self.cardScore[x] -= 3
2801
2802 def getClock(self):
2803 clock = 9999
2804 for card in self.myBoard:
2805 if card.type == "Creature":
2806 self.powerOnBoard += card.damage
2807 if self.powerOnBoard != 0:
2808 clock = math.ceil(sim.nAP.life/self.powerOnBoard)
2809 return clock
2810
2811 def getNewClock(self, newcard):
2812 clock = 9999
2813 self.powerOnBoard = 0
2814 for card in self.myBoard:
2815 if card.type == "Creature":
2816 self.powerOnBoard += card.damage * (card.sick + 1)
2817 if newcard.type == "Instant" or newcard.type == "Sorcery":
2818 if self.powerOnBoard != 0:
2819 clock = math.ceil((sim.nAP.life - newcard.damage)/self.powerOnBoard)
2820 if newcard.type == "Creature":
2821 if newcard.sick == 0:
2822 clock = math.ceil(sim.nAP.life/(self.powerOnBoard + newcard.damage))
2823 if newcard.sick == 1:
2824 if newcard.damage == 0:
2825 newcard.damage = .00001
2826 clock = math.ceil((sim.nAP.life + newcard.damage)/(self.powerOnBoard + newcard.damage))
2827 return clock
2828
2829 def plusses(self):
2830 #Bonus for number of targets, makes higher value for 2 for 1's
2831 for x in range(len(self.myHand)):
2832 self.cardScore[x] += self.myHand[x].targets
2833 #Bonus for drawing cards, makes cantrips and 2 for 1's better
2834 for x in range(len(self.myHand)):
2835 self.cardScore[x] += self.myHand[x].cardsDrawn
2836 #Bonus for speeding clock
2837 for x in range(len(self.myHand)):
2838 if self.getNewClock(self.myHand[x]) < self.getClock():
2839 self.cardScore[x] += 3
2840 #Bonus for highest impact
2841 highDamage = 0
2842 for card in self.myHand:
2843 if card.damage >= highDamage:
2844 highDamage = card.damage
2845 for x in range(len(self.myHand)):
2846 if self.myHand[x].damage >= highDamage:
2847 self.cardScore[x] += 1
2848 #Bonus for dodging interaction
2849 for x in range(len(self.myHand)):
2850 if self.myHand[x].type != "Creature":
2851 self.cardScore[x] += 1
2852 #Bonus for burning opponent out
2853 burn = sim.curPlayer.getBurn()
2854 for x in range(len(self.myHand)):
2855 if burn >= sim.nAP.life and self.myHand[x].type == "Instant" or burn >= sim.nAP.life and self.myHand[x].type == "Sorcery":
2856 self.cardScore[x] += 5
2857 #Bonus for early creature
2858 if sim.turn <= 2:
2859 for x in range(len(self.myHand)):
2860 if self.myHand[x].type == "Creature":
2861 self.cardScore[x] += 1
2862 #Bonus for cycling land
2863 if sim.curPlayer.availableMana >= 3:
2864 for x in range(len(self.myHand)):
2865 if self.myHand[x].cycling == 1:
2866 self.cardScore[x] += 1
2867
2868 def findCurve(self):
2869 #Uses all mana
2870 for x in range(len(self.myHand)):
2871 if self.myHand[x].mana == self.availableMana:
2872 self.cardScore[x] += 1
2873 #Cast 2 2's
2874 if self.availableMana == 4 and self.manaList[2] >= 2:
2875 for x in range(len(self.myHand)):
2876 if self.myHand[x].mana == 2:
2877 self.cardScore[x] += 3
2878 #Cast 2 1's
2879 if self.availableMana == 2 and self.manaList[1] >= 2:
2880 for x in range(len(self.myHand)):
2881 if self.myHand[x].mana == 1:
2882 self.cardScore[x] += 3
2883 #Cast 0's
2884 for x in range(len(self.myHand)):
2885 if self.myHand[x].mana == 0:
2886 self.cardScore[x] += 10
2887
2888 def buildManaList(self):
2889 self.manaList = [0] * 15
2890 for card in self.myHand:
2891 self.manaList[card.mana] += 1
2892
2893 def join(self, hand):
2894 joins = []
2895 for x in range(len(hand)):
2896 tup = self.myHand[x], self.cardScore[x]
2897 joins.append(tup)
2898 joins = sorted(joins, key=lambda x: x[1], reverse = True)
2899 self.myHand = []
2900 self.cardScore = []
2901 for x in range(len(joins)):
2902 self.myHand.append(joins[x][0])
2903 self.cardScore.append(joins[x][1])
2904
2905 def getPlays(self):
2906 #Create play list and score list
2907 self.cardScore = None
2908 self.cardScore = [0] * len(self.myHand)
2909 self.buildManaList()
2910 self.findCurve()
2911 self.plusses()
2912 self.negs()
2913 self.join(self.myHand)
2914 sim.debug(self.myHand)
2915 sim.debug(self.cardScore)
2916
2917
2918#Main program
2919print(ctime())
2920print("Running simulation, check back later")
2921sim = Simulator()
2922sim.setParams()
2923print("Simulation finished")
2924print(ctime())