├── .gitignore ├── LICENSE ├── Makefile ├── card.c ├── card.h ├── inc ├── asmlib.h └── asmlibran.h ├── lib ├── asmlib.zip └── libacof64o.lib ├── partial.c ├── partial.h ├── project.clj ├── readme.md ├── soot.c ├── src └── soot │ ├── cards.clj │ ├── game.clj │ └── game_helpers.clj ├── state.h ├── support.c ├── support.h ├── test └── soot │ └── game_test.clj └── thing.h /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /classes 3 | /checkouts 4 | pom.xml 5 | pom.xml.asc 6 | *.jar 7 | *.class 8 | /.lein-* 9 | /.nrepl-port 10 | *.exe 11 | *.s 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Robert Nix 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS += -Wall -Werror -Wextra 2 | CFLAGS += -Wmissing-prototypes 3 | CFLAGS += -Wstrict-prototypes 4 | CFLAGS += -Wmissing-declarations 5 | CFLAGS += -Wl,-e_main -lkernel32 -ladvapi32 -static 6 | CFLAGS += -Llib -Iinc 7 | # agner's asmlib 8 | CFLAGS += -llibacof64o 9 | CFLAGS += -std=c99 -O3 -flto -m64 -march=corei7 -nostdlib #yolo 10 | 11 | all: soot 12 | 13 | soot: soot.c state.h card.h card.c thing.h partial.h partial.c support.h support.c 14 | ${CC} -o $@ card.c partial.c support.c soot.c ${CFLAGS} ${LDFLAGS} 15 | 16 | clean: 17 | rm -f soot *.o 18 | -------------------------------------------------------------------------------- /card.c: -------------------------------------------------------------------------------- 1 | #include "card.h" 2 | 3 | Card cards[] = {{ 4 | "Chicken", 552, 5 | Free, Debug, 0, Minion, 6 | Beast, 0, 1, 1, 7 | nil, nil, nil, nil, nil, nil, nil, nil 8 | }, { 9 | "Excess Mana", 520, 10 | Free, Basic, Druid, Spell, 11 | 0, 0, 0, 0, 12 | nil, nil, nil, nil, nil, nil, nil, nil 13 | }, { 14 | "Flames of Azzinoth", 349, 15 | Free, Missions, 0, Hero_power, 16 | 0, 2, 0, 0, 17 | nil, nil, nil, nil, nil, nil, nil, nil 18 | }, { 19 | "I Am Murloc", 714, 20 | Free, Reward, 0, Spell, 21 | 0, 0, 0, 0, 22 | nil, nil, nil, nil, nil, nil, nil, nil 23 | }, { 24 | "Illidan Stormrage", 223, 25 | Free, Missions, Hunter, Hero, 26 | 0, 0, 0, 30, 27 | nil, nil, nil, nil, nil, nil, nil, nil 28 | }, { 29 | "Lorewalker Cho", 655, 30 | Free, Missions, 0, Hero, 31 | 0, 0, 0, 25, 32 | nil, nil, nil, nil, nil, nil, nil, nil 33 | }, { 34 | "Murloc", 715, 35 | Free, Reward, 0, Minion, 36 | Beast, 1, 1, 1, 37 | nil, nil, nil, nil, nil, nil, nil, nil 38 | }, { 39 | "NOOOOOOOOOOOO", 687, 40 | Free, Basic, 0, Spell, 41 | 0, 2, 0, 0, 42 | nil, nil, nil, nil, nil, nil, nil, nil 43 | }, { 44 | "Power of the Horde", 717, 45 | Free, Reward, 0, Spell, 46 | 0, 0, 0, 0, 47 | nil, nil, nil, nil, nil, nil, nil, nil 48 | }, { 49 | "Rogues Do It...", 716, 50 | Free, Reward, 0, Spell, 51 | 0, 0, 0, 0, 52 | nil, nil, nil, nil, nil, nil, nil, nil 53 | }, { 54 | "The Coin", 141, 55 | Free, Basic, 0, Spell, 56 | 0, 0, 0, 0, 57 | nil, nil, nil, nil, nil, nil, nil, nil 58 | }, { 59 | "Al'Akir the Windlord", 335, 60 | Legendary, Expert, Shaman, Minion, 61 | 0, 8, 3, 5, 62 | nil, nil, nil, nil, nil, nil, nil, nil 63 | }, { 64 | "Alexstrasza", 303, 65 | Legendary, Expert, 0, Minion, 66 | Dragon, 9, 8, 8, 67 | nil, nil, nil, nil, nil, nil, nil, nil 68 | }, { 69 | "Archmage Antonidas", 220, 70 | Legendary, Expert, Mage, Minion, 71 | 0, 7, 5, 7, 72 | nil, nil, nil, nil, nil, nil, nil, nil 73 | }, { 74 | "Ashbringer", 53, 75 | Legendary, Expert, Paladin, Weapon, 76 | 0, 5, 5, 5, 77 | nil, nil, nil, nil, nil, nil, nil, nil 78 | }, { 79 | "Baine Bloodhoof", 359, 80 | Legendary, Expert, 0, Minion, 81 | 0, 4, 4, 5, 82 | nil, nil, nil, nil, nil, nil, nil, nil 83 | }, { 84 | "Baron Geddon", 539, 85 | Legendary, Expert, 0, Minion, 86 | 0, 7, 7, 5, 87 | nil, nil, nil, nil, nil, nil, nil, nil 88 | }, { 89 | "Bloodmage Thalnos", 525, 90 | Legendary, Expert, 0, Minion, 91 | 0, 2, 1, 1, 92 | nil, nil, nil, nil, nil, nil, nil, nil 93 | }, { 94 | "Cairne Bloodhoof", 498, 95 | Legendary, Expert, 0, Minion, 96 | 0, 6, 4, 5, 97 | nil, nil, nil, nil, nil, nil, nil, nil 98 | }, { 99 | "Captain Greenskin", 267, 100 | Legendary, Expert, 0, Minion, 101 | Pirate, 5, 5, 4, 102 | nil, nil, nil, nil, nil, nil, nil, nil 103 | }, { 104 | "Cenarius", 605, 105 | Legendary, Expert, Druid, Minion, 106 | 0, 9, 5, 8, 107 | nil, nil, nil, nil, nil, nil, nil, nil 108 | }, { 109 | "Deathwing", 474, 110 | Legendary, Expert, 0, Minion, 111 | Dragon, 10, 12, 12, 112 | nil, nil, nil, nil, nil, nil, nil, nil 113 | }, { 114 | "Edwin VanCleef", 3, 115 | Legendary, Expert, Rogue, Minion, 116 | 0, 3, 2, 2, 117 | nil, nil, nil, nil, nil, nil, nil, nil 118 | }, { 119 | "Elite Tauren Chieftan", 682, 120 | Legendary, Reward, 0, Minion, 121 | 0, 5, 5, 5, 122 | nil, nil, nil, nil, nil, nil, nil, nil 123 | }, { 124 | "Finkle Einhorn", 541, 125 | Legendary, Expert, 0, Minion, 126 | 0, 2, 3, 3, 127 | nil, nil, nil, nil, nil, nil, nil, nil 128 | }, { 129 | "Gelbin Mekkatorque", 251, 130 | Legendary, Reward, 0, Minion, 131 | 0, 6, 6, 6, 132 | nil, nil, nil, nil, nil, nil, nil, nil 133 | }, { 134 | "Grommash Hellscream", 643, 135 | Legendary, Expert, Warrior, Minion, 136 | 0, 8, 4, 9, 137 | nil, nil, nil, nil, nil, nil, nil, nil 138 | }, { 139 | "Gruul", 18, 140 | Legendary, Expert, 0, Minion, 141 | 0, 8, 7, 7, 142 | nil, nil, nil, nil, nil, nil, nil, nil 143 | }, { 144 | "Harrison Jones", 602, 145 | Legendary, Expert, 0, Minion, 146 | 0, 5, 5, 4, 147 | nil, nil, nil, nil, nil, nil, nil, nil 148 | }, { 149 | "Hogger", 39, 150 | Legendary, Expert, 0, Minion, 151 | 0, 6, 4, 4, 152 | nil, nil, nil, nil, nil, nil, nil, nil 153 | }, { 154 | "Illidan Stormrage", 203, 155 | Legendary, Expert, 0, Minion, 156 | Demon, 6, 7, 5, 157 | nil, nil, nil, nil, nil, nil, nil, nil 158 | }, { 159 | "King Krush", 194, 160 | Legendary, Expert, Hunter, Minion, 161 | Beast, 9, 8, 8, 162 | nil, nil, nil, nil, nil, nil, nil, nil 163 | }, { 164 | "King Mukla", 373, 165 | Legendary, Expert, 0, Minion, 166 | Beast, 3, 5, 5, 167 | nil, nil, nil, nil, nil, nil, nil, nil 168 | }, { 169 | "Leeroy Jenkins", 674, 170 | Legendary, Expert, 0, Minion, 171 | 0, 4, 6, 2, 172 | nil, nil, nil, nil, nil, nil, nil, nil 173 | }, { 174 | "Lord Jaraxxus", 482, 175 | Legendary, Expert, Warlock, Minion, 176 | Demon, 9, 3, 15, 177 | nil, nil, nil, nil, nil, nil, nil, nil 178 | }, { 179 | "Lord Jaraxxus", 406, 180 | Legendary, Expert, Warlock, Hero, 181 | 0, 0, 0, 15, 182 | nil, nil, nil, nil, nil, nil, nil, nil 183 | }, { 184 | "Lorewalker Cho", 456, 185 | Legendary, Expert, 0, Minion, 186 | 0, 2, 0, 4, 187 | nil, nil, nil, nil, nil, nil, nil, nil 188 | }, { 189 | "Malygos", 241, 190 | Legendary, Expert, 0, Minion, 191 | Dragon, 9, 4, 12, 192 | nil, nil, nil, nil, nil, nil, nil, nil 193 | }, { 194 | "Millhouse Manastorm", 339, 195 | Legendary, Expert, 0, Minion, 196 | 0, 2, 4, 4, 197 | nil, nil, nil, nil, nil, nil, nil, nil 198 | }, { 199 | "Nat Pagle", 19, 200 | Legendary, Expert, 0, Minion, 201 | 0, 2, 0, 4, 202 | nil, nil, nil, nil, nil, nil, nil, nil 203 | }, { 204 | "Nozdormu", 285, 205 | Legendary, Expert, 0, Minion, 206 | Dragon, 9, 8, 8, 207 | nil, nil, nil, nil, nil, nil, nil, nil 208 | }, { 209 | "Old Murk-Eye", 217, 210 | Legendary, Reward, 0, Minion, 211 | Murloc, 4, 2, 4, 212 | nil, nil, nil, nil, nil, nil, nil, nil 213 | }, { 214 | "Onyxia", 432, 215 | Legendary, Expert, 0, Minion, 216 | Dragon, 9, 8, 8, 217 | nil, nil, nil, nil, nil, nil, nil, nil 218 | }, { 219 | "Prophet Velen", 228, 220 | Legendary, Expert, Priest, Minion, 221 | 0, 7, 7, 7, 222 | nil, nil, nil, nil, nil, nil, nil, nil 223 | }, { 224 | "Ragnaros the Firelord", 503, 225 | Legendary, Expert, 0, Minion, 226 | 0, 8, 8, 8, 227 | nil, nil, nil, nil, nil, nil, nil, nil 228 | }, { 229 | "Sylvanas Windrunner", 33, 230 | Legendary, Expert, 0, Minion, 231 | 0, 5, 5, 5, 232 | nil, nil, nil, nil, nil, nil, nil, nil 233 | }, { 234 | "The Beast", 179, 235 | Legendary, Expert, 0, Minion, 236 | Beast, 6, 9, 7, 237 | nil, nil, nil, nil, nil, nil, nil, nil 238 | }, { 239 | "The Black Knight", 396, 240 | Legendary, Expert, 0, Minion, 241 | 0, 6, 4, 5, 242 | nil, nil, nil, nil, nil, nil, nil, nil 243 | }, { 244 | "Tinkmaster Overspark", 245, 245 | Legendary, Expert, 0, Minion, 246 | 0, 3, 2, 2, 247 | nil, nil, nil, nil, nil, nil, nil, nil 248 | }, { 249 | "Tirion Fordring", 391, 250 | Legendary, Expert, Paladin, Minion, 251 | 0, 8, 6, 6, 252 | nil, nil, nil, nil, nil, nil, nil, nil 253 | }, { 254 | "Ysera", 495, 255 | Legendary, Expert, 0, Minion, 256 | 0, 9, 4, 12, 257 | nil, nil, nil, nil, nil, nil, nil, nil 258 | }, { 259 | "Adrenaline Rush", 180, 260 | Epic, Expert, Rogue, Spell, 261 | 0, 1, 0, 0, 262 | nil, nil, nil, nil, nil, nil, nil, nil 263 | }, { 264 | "Ancient of Lore", 34, 265 | Epic, Expert, Druid, Minion, 266 | 0, 7, 5, 5, 267 | nil, nil, nil, nil, nil, nil, nil, nil 268 | }, { 269 | "Ancient of War", 242, 270 | Epic, Expert, Druid, Minion, 271 | 0, 7, 5, 5, 272 | nil, nil, nil, nil, nil, nil, nil, nil 273 | }, { 274 | "Avenging Wrath", 142, 275 | Epic, Expert, Paladin, Spell, 276 | 0, 6, 0, 0, 277 | nil, nil, nil, nil, nil, nil, nil, nil 278 | }, { 279 | "Bane of Doom", 670, 280 | Epic, Expert, Warlock, Spell, 281 | 0, 5, 0, 0, 282 | nil, nil, nil, nil, nil, nil, nil, nil 283 | }, { 284 | "Bestial Wrath", 304, 285 | Epic, Expert, Hunter, Spell, 286 | 0, 1, 0, 0, 287 | nil, nil, nil, nil, nil, nil, nil, nil 288 | }, { 289 | "Big Game Hunter", 73, 290 | Epic, Expert, 0, Minion, 291 | 0, 3, 4, 2, 292 | nil, nil, nil, nil, nil, nil, nil, nil 293 | }, { 294 | "Blood Knight", 75, 295 | Epic, Expert, 0, Minion, 296 | 0, 3, 3, 3, 297 | nil, nil, nil, nil, nil, nil, nil, nil 298 | }, { 299 | "Brawl", 297, 300 | Epic, Expert, Warrior, Spell, 301 | 0, 5, 0, 0, 302 | nil, nil, nil, nil, nil, nil, nil, nil 303 | }, { 304 | "Cabal Shadow Priest", 147, 305 | Epic, Expert, Priest, Minion, 306 | 0, 6, 4, 5, 307 | nil, nil, nil, nil, nil, nil, nil, nil 308 | }, { 309 | "Captain's Parrot", 559, 310 | Epic, Reward, 0, Minion, 311 | Beast, 2, 1, 1, 312 | nil, nil, nil, nil, nil, nil, nil, nil 313 | }, { 314 | "Doomhammer", 172, 315 | Epic, Expert, Shaman, Weapon, 316 | 0, 5, 2, 8, 317 | nil, nil, nil, nil, nil, nil, nil, nil 318 | }, { 319 | "Doomsayer", 467, 320 | Epic, Expert, 0, Minion, 321 | 0, 2, 0, 7, 322 | nil, nil, nil, nil, nil, nil, nil, nil 323 | }, { 324 | "Earth Elemental", 124, 325 | Epic, Expert, Shaman, Minion, 326 | 0, 5, 7, 8, 327 | nil, nil, nil, nil, nil, nil, nil, nil 328 | }, { 329 | "Faceless Manipulator", 450, 330 | Epic, Expert, 0, Minion, 331 | 0, 5, 3, 3, 332 | nil, nil, nil, nil, nil, nil, nil, nil 333 | }, { 334 | "Far Sight", 107, 335 | Epic, Expert, Shaman, Spell, 336 | 0, 3, 0, 0, 337 | nil, nil, nil, nil, nil, nil, nil, nil 338 | }, { 339 | "Force of Nature", 237, 340 | Epic, Expert, Druid, Spell, 341 | 0, 6, 0, 0, 342 | nil, nil, nil, nil, nil, nil, nil, nil 343 | }, { 344 | "Gladiator's Longbow", 278, 345 | Epic, Expert, Hunter, Weapon, 346 | 0, 7, 5, 2, 347 | nil, nil, nil, nil, nil, nil, nil, nil 348 | }, { 349 | "Gorehowl", 96, 350 | Epic, Expert, Warrior, Weapon, 351 | 0, 7, 7, 1, 352 | nil, nil, nil, nil, nil, nil, nil, nil 353 | }, { 354 | "Hungry Crab", 660, 355 | Epic, Expert, 0, Minion, 356 | Beast, 1, 1, 2, 357 | nil, nil, nil, nil, nil, nil, nil, nil 358 | }, { 359 | "Ice Block", 28, 360 | Epic, Expert, Mage, Secret, 361 | 0, 3, 0, 0, 362 | nil, nil, nil, nil, nil, nil, nil, nil 363 | }, { 364 | "Kidnapper", 562, 365 | Epic, Expert, Rogue, Minion, 366 | 0, 6, 5, 5, 367 | nil, nil, nil, nil, nil, nil, nil, nil 368 | }, { 369 | "Lay on Hands", 506, 370 | Epic, Expert, Paladin, Spell, 371 | 0, 8, 0, 0, 372 | nil, nil, nil, nil, nil, nil, nil, nil 373 | }, { 374 | "Mindgames", 301, 375 | Epic, Expert, Priest, Spell, 376 | 0, 4, 0, 0, 377 | nil, nil, nil, nil, nil, nil, nil, nil 378 | }, { 379 | "Molten Giant", 94, 380 | Epic, Expert, 0, Minion, 381 | 0, 31, 8, 8, 382 | nil, nil, nil, nil, nil, nil, nil, nil 383 | }, { 384 | "Mountain Giant", 264, 385 | Epic, Expert, 0, Minion, 386 | 0, 31, 8, 8, 387 | nil, nil, nil, nil, nil, nil, nil, nil 388 | }, { 389 | "Murloc Warleader", 222, 390 | Epic, Expert, 0, Minion, 391 | Murloc, 3, 3, 3, 392 | nil, nil, nil, nil, nil, nil, nil, nil 393 | }, { 394 | "Patient Assassin", 14, 395 | Epic, Expert, Rogue, Minion, 396 | 0, 2, 1, 1, 397 | nil, nil, nil, nil, nil, nil, nil, nil 398 | }, { 399 | "Pit Lord", 402, 400 | Epic, Expert, Warlock, Minion, 401 | Demon, 4, 5, 6, 402 | nil, nil, nil, nil, nil, nil, nil, nil 403 | }, { 404 | "Placeholder Card", 102, 405 | Epic, None, Mage, Minion, 406 | 0, 9, 6, 8, 407 | nil, nil, nil, nil, nil, nil, nil, nil 408 | }, { 409 | "Preparation", 364, 410 | Epic, Expert, Rogue, Spell, 411 | 0, 0, 0, 0, 412 | nil, nil, nil, nil, nil, nil, nil, nil 413 | }, { 414 | "Pyroblast", 496, 415 | Epic, Expert, Mage, Spell, 416 | 0, 8, 0, 0, 417 | nil, nil, nil, nil, nil, nil, nil, nil 418 | }, { 419 | "Sea Giant", 614, 420 | Epic, Expert, 0, Minion, 421 | 0, 31, 8, 8, 422 | nil, nil, nil, nil, nil, nil, nil, nil 423 | }, { 424 | "Shadow of Nothing", 582, 425 | Epic, Expert, Priest, Minion, 426 | 0, 0, 0, 1, 427 | nil, nil, nil, nil, nil, nil, nil, nil 428 | }, { 429 | "Shadowform", 421, 430 | Epic, Expert, Priest, Spell, 431 | 0, 3, 0, 0, 432 | nil, nil, nil, nil, nil, nil, nil, nil 433 | }, { 434 | "Shield Slam", 50, 435 | Epic, Expert, Warrior, Spell, 436 | 0, 1, 0, 0, 437 | nil, nil, nil, nil, nil, nil, nil, nil 438 | }, { 439 | "Snake Trap", 210, 440 | Epic, Expert, Hunter, Secret, 441 | 0, 2, 0, 0, 442 | nil, nil, nil, nil, nil, nil, nil, nil 443 | }, { 444 | "Southsea Captain", 324, 445 | Epic, Expert, 0, Minion, 446 | Pirate, 3, 3, 3, 447 | nil, nil, nil, nil, nil, nil, nil, nil 448 | }, { 449 | "Spellbender", 309, 450 | Epic, Expert, Mage, Secret, 451 | 0, 3, 0, 0, 452 | nil, nil, nil, nil, nil, nil, nil, nil 453 | }, { 454 | "Spellbender", 645, 455 | Epic, Expert, Mage, Minion, 456 | 0, 0, 1, 3, 457 | nil, nil, nil, nil, nil, nil, nil, nil 458 | }, { 459 | "Sword of Justice", 567, 460 | Epic, Expert, Paladin, Weapon, 461 | 0, 3, 1, 3, 462 | nil, nil, nil, nil, nil, nil, nil, nil 463 | }, { 464 | "Twisting Nether", 398, 465 | Epic, Expert, Warlock, Spell, 466 | 0, 8, 0, 0, 467 | nil, nil, nil, nil, nil, nil, nil, nil 468 | }, { 469 | "Abomination", 597, 470 | Rare, Expert, 0, Minion, 471 | 0, 5, 4, 4, 472 | nil, nil, nil, nil, nil, nil, nil, nil 473 | }, { 474 | "Alarm-o-Bot", 425, 475 | Rare, Expert, 0, Minion, 476 | 0, 3, 0, 3, 477 | nil, nil, nil, nil, nil, nil, nil, nil 478 | }, { 479 | "Aldor Peacekeeper", 23, 480 | Rare, Expert, Paladin, Minion, 481 | 0, 3, 3, 3, 482 | nil, nil, nil, nil, nil, nil, nil, nil 483 | }, { 484 | "Ancestral Spirit", 526, 485 | Rare, Expert, Shaman, Spell, 486 | 0, 2, 0, 0, 487 | nil, nil, nil, nil, nil, nil, nil, nil 488 | }, { 489 | "Ancient Mage", 176, 490 | Rare, Expert, 0, Minion, 491 | 0, 4, 2, 5, 492 | nil, nil, nil, nil, nil, nil, nil, nil 493 | }, { 494 | "Ancient Watcher", 153, 495 | Rare, Expert, 0, Minion, 496 | 0, 2, 4, 5, 497 | nil, nil, nil, nil, nil, nil, nil, nil 498 | }, { 499 | "Angry Chicken", 57, 500 | Rare, Expert, 0, 0, 501 | 0, 1, 0, 0, 502 | nil, nil, nil, nil, nil, nil, nil, nil 503 | }, { 504 | "Arcane Golem", 97, 505 | Rare, Expert, 0, Minion, 506 | 0, 3, 4, 2, 507 | nil, nil, nil, nil, nil, nil, nil, nil 508 | }, { 509 | "Argent Commander", 463, 510 | Rare, Expert, 0, Minion, 511 | 0, 6, 4, 2, 512 | nil, nil, nil, nil, nil, nil, nil, nil 513 | }, { 514 | "Armorsmith", 644, 515 | Rare, Expert, Warrior, Minion, 516 | 0, 2, 1, 4, 517 | nil, nil, nil, nil, nil, nil, nil, nil 518 | }, { 519 | "Auchenai Soulpriest", 656, 520 | Rare, Expert, Priest, Minion, 521 | 0, 4, 3, 5, 522 | nil, nil, nil, nil, nil, nil, nil, nil 523 | }, { 524 | "Azure Drake", 280, 525 | Rare, Expert, 0, Minion, 526 | Dragon, 5, 4, 4, 527 | nil, nil, nil, nil, nil, nil, nil, nil 528 | }, { 529 | "Bite", 266, 530 | Rare, Expert, Druid, Spell, 531 | 0, 4, 0, 0, 532 | nil, nil, nil, nil, nil, nil, nil, nil 533 | }, { 534 | "Blade Flurry", 244, 535 | Rare, Expert, Rogue, Spell, 536 | 0, 2, 0, 0, 537 | nil, nil, nil, nil, nil, nil, nil, nil 538 | }, { 539 | "Blessed Champion", 7, 540 | Rare, Expert, Paladin, Spell, 541 | 0, 5, 0, 0, 542 | nil, nil, nil, nil, nil, nil, nil, nil 543 | }, { 544 | "Blizzard", 276, 545 | Rare, Expert, Mage, Spell, 546 | 0, 6, 0, 0, 547 | nil, nil, nil, nil, nil, nil, nil, nil 548 | }, { 549 | "Bloodsail Corsair", 453, 550 | Rare, Expert, 0, Minion, 551 | Pirate, 1, 1, 2, 552 | nil, nil, nil, nil, nil, nil, nil, nil 553 | }, { 554 | "Coldlight Oracle", 88, 555 | Rare, Expert, 0, Minion, 556 | Murloc, 3, 2, 2, 557 | nil, nil, nil, nil, nil, nil, nil, nil 558 | }, { 559 | "Coldlight Seer", 424, 560 | Rare, Expert, 0, Minion, 561 | Murloc, 3, 2, 3, 562 | nil, nil, nil, nil, nil, nil, nil, nil 563 | }, { 564 | "Commanding Shout", 166, 565 | Rare, Expert, Warrior, Spell, 566 | 0, 2, 0, 0, 567 | nil, nil, nil, nil, nil, nil, nil, nil 568 | }, { 569 | "Counterspell", 531, 570 | Rare, Expert, Mage, Secret, 571 | 0, 3, 0, 0, 572 | nil, nil, nil, nil, nil, nil, nil, nil 573 | }, { 574 | "Crazed Alchemist", 612, 575 | Rare, Expert, 0, Minion, 576 | 0, 2, 2, 2, 577 | nil, nil, nil, nil, nil, nil, nil, nil 578 | }, { 579 | "Defender of Argus", 542, 580 | Rare, Expert, 0, Minion, 581 | 0, 4, 3, 3, 582 | nil, nil, nil, nil, nil, nil, nil, nil 583 | }, { 584 | "Demolisher", 212, 585 | Rare, Expert, 0, Minion, 586 | 0, 3, 1, 4, 587 | nil, nil, nil, nil, nil, nil, nil, nil 588 | }, { 589 | "Divine Favor", 581, 590 | Rare, Expert, Paladin, Spell, 591 | 0, 3, 0, 0, 592 | nil, nil, nil, nil, nil, nil, nil, nil 593 | }, { 594 | "Doomguard", 507, 595 | Rare, Expert, Warlock, Minion, 596 | Demon, 5, 5, 7, 597 | nil, nil, nil, nil, nil, nil, nil, nil 598 | }, { 599 | "Eaglehorn Bow", 363, 600 | Rare, Expert, Hunter, Weapon, 601 | 0, 3, 3, 2, 602 | nil, nil, nil, nil, nil, nil, nil, nil 603 | }, { 604 | "Emperor Cobra", 625, 605 | Rare, Expert, 0, Minion, 606 | Beast, 3, 2, 3, 607 | nil, nil, nil, nil, nil, nil, nil, nil 608 | }, { 609 | "Equality", 383, 610 | Rare, Expert, Paladin, Spell, 611 | 0, 2, 0, 0, 612 | nil, nil, nil, nil, nil, nil, nil, nil 613 | }, { 614 | "Ethereal Arcanist", 125, 615 | Rare, Expert, Mage, Minion, 616 | 0, 4, 3, 3, 617 | nil, nil, nil, nil, nil, nil, nil, nil 618 | }, { 619 | "Explosive Shot", 114, 620 | Rare, Expert, Hunter, Spell, 621 | 0, 5, 0, 0, 622 | nil, nil, nil, nil, nil, nil, nil, nil 623 | }, { 624 | "Felguard", 236, 625 | Rare, Expert, Warlock, Minion, 626 | Demon, 3, 3, 5, 627 | nil, nil, nil, nil, nil, nil, nil, nil 628 | }, { 629 | "Feral Spirit", 214, 630 | Rare, Expert, Shaman, Spell, 631 | 0, 3, 0, 0, 632 | nil, nil, nil, nil, nil, nil, nil, nil 633 | }, { 634 | "Flare", 630, 635 | Rare, Expert, Hunter, Spell, 636 | 0, 1, 0, 0, 637 | nil, nil, nil, nil, nil, nil, nil, nil 638 | }, { 639 | "Frothing Berserker", 69, 640 | Rare, Expert, Warrior, Minion, 641 | 0, 3, 2, 4, 642 | nil, nil, nil, nil, nil, nil, nil, nil 643 | }, { 644 | "Gadgetzan Auctioneer", 131, 645 | Rare, Expert, 0, Minion, 646 | 0, 5, 4, 4, 647 | nil, nil, nil, nil, nil, nil, nil, nil 648 | }, { 649 | "Headcrack", 135, 650 | Rare, Expert, Rogue, Spell, 651 | 0, 3, 0, 0, 652 | nil, nil, nil, nil, nil, nil, nil, nil 653 | }, { 654 | "Holy Fire", 457, 655 | Rare, Expert, Priest, Spell, 656 | 0, 6, 0, 0, 657 | nil, nil, nil, nil, nil, nil, nil, nil 658 | }, { 659 | "Holy Wrath", 355, 660 | Rare, Expert, Paladin, Spell, 661 | 0, 5, 0, 0, 662 | nil, nil, nil, nil, nil, nil, nil, nil 663 | }, { 664 | "Hyena", 689, 665 | Rare, Expert, Hunter, Minion, 666 | Beast, 2, 2, 2, 667 | nil, nil, nil, nil, nil, nil, nil, nil 668 | }, { 669 | "Imp", 321, 670 | Rare, Expert, 0, Minion, 671 | Demon, 1, 1, 1, 672 | nil, nil, nil, nil, nil, nil, nil, nil 673 | }, { 674 | "Imp Master", 178, 675 | Rare, Expert, 0, Minion, 676 | 0, 3, 1, 5, 677 | nil, nil, nil, nil, nil, nil, nil, nil 678 | }, { 679 | "Injured Blademaster", 209, 680 | Rare, Expert, 0, Minion, 681 | 0, 3, 4, 7, 682 | nil, nil, nil, nil, nil, nil, nil, nil 683 | }, { 684 | "Keeper of the Grove", 459, 685 | Rare, Expert, Druid, Minion, 686 | 0, 4, 2, 4, 687 | nil, nil, nil, nil, nil, nil, nil, nil 688 | }, { 689 | "Kirin Tor Mage", 411, 690 | Rare, Expert, Mage, Minion, 691 | 0, 3, 4, 3, 692 | nil, nil, nil, nil, nil, nil, nil, nil 693 | }, { 694 | "Knife Juggler", 422, 695 | Rare, Expert, 0, Minion, 696 | 0, 2, 3, 2, 697 | nil, nil, nil, nil, nil, nil, nil, nil 698 | }, { 699 | "Lava Burst", 679, 700 | Rare, Expert, Shaman, Spell, 701 | 0, 3, 0, 0, 702 | nil, nil, nil, nil, nil, nil, nil, nil 703 | }, { 704 | "Lightning Storm", 676, 705 | Rare, Expert, Shaman, Spell, 706 | 0, 3, 0, 0, 707 | nil, nil, nil, nil, nil, nil, nil, nil 708 | }, { 709 | "Lightwarden", 436, 710 | Rare, Expert, 0, Minion, 711 | 0, 1, 1, 2, 712 | nil, nil, nil, nil, nil, nil, nil, nil 713 | }, { 714 | "Lightwell", 117, 715 | Rare, Expert, Priest, Minion, 716 | 0, 2, 0, 5, 717 | nil, nil, nil, nil, nil, nil, nil, nil 718 | }, { 719 | "Mana Addict", 67, 720 | Rare, Expert, 0, Minion, 721 | 0, 2, 1, 3, 722 | nil, nil, nil, nil, nil, nil, nil, nil 723 | }, { 724 | "Mana Tide Totem", 613, 725 | Rare, Expert, Shaman, Minion, 726 | Totem, 3, 0, 3, 727 | nil, nil, nil, nil, nil, nil, nil, nil 728 | }, { 729 | "Mana Wraith", 197, 730 | Rare, Expert, 0, Minion, 731 | 0, 2, 2, 2, 732 | nil, nil, nil, nil, nil, nil, nil, nil 733 | }, { 734 | "Mass Dispel", 249, 735 | Rare, Expert, Priest, Spell, 736 | 0, 4, 0, 0, 737 | nil, nil, nil, nil, nil, nil, nil, nil 738 | }, { 739 | "Master of Disguise", 127, 740 | Rare, Expert, Rogue, Minion, 741 | 0, 4, 4, 4, 742 | nil, nil, nil, nil, nil, nil, nil, nil 743 | }, { 744 | "Master Swordsmith", 584, 745 | Rare, Expert, 0, Minion, 746 | 0, 2, 1, 3, 747 | nil, nil, nil, nil, nil, nil, nil, nil 748 | }, { 749 | "Mind Control Tech", 368, 750 | Rare, Expert, 0, Minion, 751 | 0, 3, 3, 3, 752 | nil, nil, nil, nil, nil, nil, nil, nil 753 | }, { 754 | "Misdirection", 447, 755 | Rare, Expert, Hunter, Secret, 756 | 0, 2, 0, 0, 757 | nil, nil, nil, nil, nil, nil, nil, nil 758 | }, { 759 | "Mortal Strike", 345, 760 | Rare, Expert, Warrior, Spell, 761 | 0, 4, 0, 0, 762 | nil, nil, nil, nil, nil, nil, nil, nil 763 | }, { 764 | "Murloc Tidecaller", 420, 765 | Rare, Expert, 0, Minion, 766 | Murloc, 1, 1, 2, 767 | nil, nil, nil, nil, nil, nil, nil, nil 768 | }, { 769 | "Nourish", 120, 770 | Rare, Expert, Druid, Spell, 771 | 0, 5, 0, 0, 772 | nil, nil, nil, nil, nil, nil, nil, nil 773 | }, { 774 | "Perdition's Blade", 82, 775 | Rare, Expert, Rogue, Weapon, 776 | 0, 3, 2, 2, 777 | nil, nil, nil, nil, nil, nil, nil, nil 778 | }, { 779 | "Pint-Sized Summoner", 54, 780 | Rare, Expert, 0, Minion, 781 | 0, 2, 2, 2, 782 | nil, nil, nil, nil, nil, nil, nil, nil 783 | }, { 784 | "Questing Adventurer", 157, 785 | Rare, Expert, 0, Minion, 786 | 0, 3, 2, 2, 787 | nil, nil, nil, nil, nil, nil, nil, nil 788 | }, { 789 | "Ravenholdt Assassin", 518, 790 | Rare, Expert, 0, Minion, 791 | 0, 7, 7, 5, 792 | nil, nil, nil, nil, nil, nil, nil, nil 793 | }, { 794 | "Savagery", 148, 795 | Rare, Expert, Druid, Spell, 796 | 0, 1, 0, 0, 797 | nil, nil, nil, nil, nil, nil, nil, nil 798 | }, { 799 | "Savannah Highmane", 8, 800 | Rare, Expert, Hunter, Minion, 801 | Beast, 6, 6, 5, 802 | nil, nil, nil, nil, nil, nil, nil, nil 803 | }, { 804 | "Secretkeeper", 483, 805 | Rare, Expert, 0, Minion, 806 | 0, 1, 1, 2, 807 | nil, nil, nil, nil, nil, nil, nil, nil 808 | }, { 809 | "Shadow Madness", 442, 810 | Rare, Expert, Priest, Spell, 811 | 0, 4, 0, 0, 812 | nil, nil, nil, nil, nil, nil, nil, nil 813 | }, { 814 | "Shadowflame", 673, 815 | Rare, Expert, Warlock, Spell, 816 | 0, 4, 0, 0, 817 | nil, nil, nil, nil, nil, nil, nil, nil 818 | }, { 819 | "SI7 Agent", 286, 820 | Rare, Expert, Rogue, Minion, 821 | 0, 3, 3, 3, 822 | nil, nil, nil, nil, nil, nil, nil, nil 823 | }, { 824 | "Siphon Soul", 573, 825 | Rare, Expert, Warlock, Spell, 826 | 0, 6, 0, 0, 827 | nil, nil, nil, nil, nil, nil, nil, nil 828 | }, { 829 | "Spirit Wolf", 451, 830 | Rare, Expert, Shaman, Minion, 831 | 0, 2, 2, 3, 832 | nil, nil, nil, nil, nil, nil, nil, nil 833 | }, { 834 | "Stampeding Kodo", 389, 835 | Rare, Expert, 0, Minion, 836 | Beast, 5, 3, 5, 837 | nil, nil, nil, nil, nil, nil, nil, nil 838 | }, { 839 | "Starfall", 464, 840 | Rare, Expert, Druid, Spell, 841 | 0, 5, 0, 0, 842 | nil, nil, nil, nil, nil, nil, nil, nil 843 | }, { 844 | "Sunfury Protector", 372, 845 | Rare, Expert, 0, Minion, 846 | 0, 2, 2, 3, 847 | nil, nil, nil, nil, nil, nil, nil, nil 848 | }, { 849 | "Sunwalker", 221, 850 | Rare, Expert, 0, Minion, 851 | 0, 6, 4, 5, 852 | nil, nil, nil, nil, nil, nil, nil, nil 853 | }, { 854 | "Twilight Drake", 360, 855 | Rare, Expert, 0, Minion, 856 | Dragon, 4, 4, 1, 857 | nil, nil, nil, nil, nil, nil, nil, nil 858 | }, { 859 | "Upgrade!", 638, 860 | Rare, Expert, Warrior, Spell, 861 | 0, 1, 0, 0, 862 | nil, nil, nil, nil, nil, nil, nil, nil 863 | }, { 864 | "Vaporize", 160, 865 | Rare, Expert, Mage, Secret, 866 | 0, 3, 0, 0, 867 | nil, nil, nil, nil, nil, nil, nil, nil 868 | }, { 869 | "Violet Teacher", 523, 870 | Rare, Expert, 0, Minion, 871 | 0, 4, 3, 5, 872 | nil, nil, nil, nil, nil, nil, nil, nil 873 | }, { 874 | "Void Terror", 119, 875 | Rare, Expert, Warlock, Minion, 876 | Demon, 3, 3, 3, 877 | nil, nil, nil, nil, nil, nil, nil, nil 878 | }, { 879 | "Wild Pyromancer", 25, 880 | Rare, Expert, 0, Minion, 881 | 0, 2, 3, 2, 882 | nil, nil, nil, nil, nil, nil, nil, nil 883 | }, { 884 | "Young Priestess", 123, 885 | Rare, Expert, 0, Minion, 886 | 0, 1, 2, 1, 887 | nil, nil, nil, nil, nil, nil, nil, nil 888 | }, { 889 | "Abusive Sergeant", 577, 890 | Common, Expert, 0, Minion, 891 | 0, 1, 2, 1, 892 | nil, nil, nil, nil, nil, nil, nil, nil 893 | }, { 894 | "Acolyte of Pain", 428, 895 | Common, Expert, 0, Minion, 896 | 0, 3, 1, 3, 897 | nil, nil, nil, nil, nil, nil, nil, nil 898 | }, { 899 | "Amani Berserker", 641, 900 | Common, Expert, 0, Minion, 901 | 0, 2, 2, 3, 902 | nil, nil, nil, nil, nil, nil, nil, nil 903 | }, { 904 | "Ancient Brewmaster", 572, 905 | Common, Expert, 0, Minion, 906 | 0, 4, 5, 4, 907 | nil, nil, nil, nil, nil, nil, nil, nil 908 | }, { 909 | "Ancient Secrets", 243, 910 | Free, Expert, Druid, Spell, 911 | 0, 0, 0, 0, 912 | nil, nil, nil, nil, nil, nil, nil, nil 913 | }, { 914 | "Ancient Teachings", 517, 915 | Free, Expert, Druid, Spell, 916 | 0, 0, 0, 0, 917 | nil, nil, nil, nil, nil, nil, nil, nil 918 | }, { 919 | "Arathi Weaponsmith", 504, 920 | Common, Expert, Warrior, Minion, 921 | 0, 4, 3, 3, 922 | nil, nil, nil, nil, nil, nil, nil, nil 923 | }, { 924 | "Argent Protector", 191, 925 | Common, Expert, Paladin, Minion, 926 | 0, 2, 2, 2, 927 | nil, nil, nil, nil, nil, nil, nil, nil 928 | }, { 929 | "Argent Squire", 473, 930 | Common, Expert, 0, Minion, 931 | 0, 1, 1, 1, 932 | nil, nil, nil, nil, nil, nil, nil, nil 933 | }, { 934 | "Bananas", 231, 935 | Free, Expert, 0, Spell, 936 | 0, 1, 0, 0, 937 | nil, nil, nil, nil, nil, nil, nil, nil 938 | }, { 939 | "Battle Axe", 403, 940 | Free, Expert, Warrior, Weapon, 941 | 0, 1, 2, 2, 942 | nil, nil, nil, nil, nil, nil, nil, nil 943 | }, { 944 | "Battle Rage", 664, 945 | Common, Expert, Warrior, Spell, 946 | 0, 2, 0, 0, 947 | nil, nil, nil, nil, nil, nil, nil, nil 948 | }, { 949 | "Bear Form", 662, 950 | Common, Expert, Druid, Spell, 951 | 0, 0, 0, 0, 952 | nil, nil, nil, nil, nil, nil, nil, nil 953 | }, { 954 | "Betrayal", 198, 955 | Common, Expert, Rogue, Spell, 956 | 0, 2, 0, 0, 957 | nil, nil, nil, nil, nil, nil, nil, nil 958 | }, { 959 | "Blessing of Wisdom", 100, 960 | Common, Expert, Paladin, Spell, 961 | 0, 1, 0, 0, 962 | nil, nil, nil, nil, nil, nil, nil, nil 963 | }, { 964 | "Blood Fury", 669, 965 | Free, Expert, Warlock, Weapon, 966 | 0, 3, 3, 8, 967 | nil, nil, nil, nil, nil, nil, nil, nil 968 | }, { 969 | "Blood Imp", 196, 970 | Common, Expert, Warlock, Minion, 971 | Demon, 1, 1, 1, 972 | nil, nil, nil, nil, nil, nil, nil, nil 973 | }, { 974 | "Bloodsail Raider", 637, 975 | Common, Expert, 0, Minion, 976 | Pirate, 2, 2, 3, 977 | nil, nil, nil, nil, nil, nil, nil, nil 978 | }, { 979 | "Cat Form", 287, 980 | Common, Expert, Druid, Spell, 981 | 0, 0, 0, 0, 982 | nil, nil, nil, nil, nil, nil, nil, nil 983 | }, { 984 | "Circle of Healing", 38, 985 | Common, Expert, Priest, Spell, 986 | 0, 0, 0, 0, 987 | nil, nil, nil, nil, nil, nil, nil, nil 988 | }, { 989 | "Cold Blood", 92, 990 | Common, Expert, Rogue, Spell, 991 | 0, 1, 0, 0, 992 | nil, nil, nil, nil, nil, nil, nil, nil 993 | }, { 994 | "Conceal", 284, 995 | Common, Expert, Rogue, Spell, 996 | 0, 1, 0, 0, 997 | nil, nil, nil, nil, nil, nil, nil, nil 998 | }, { 999 | "Cone of Cold", 26, 1000 | Common, Expert, Mage, Spell, 1001 | 0, 4, 0, 0, 1002 | nil, nil, nil, nil, nil, nil, nil, nil 1003 | }, { 1004 | "Cruel Taskmaster", 328, 1005 | Common, Expert, Warrior, Minion, 1006 | 0, 2, 2, 2, 1007 | nil, nil, nil, nil, nil, nil, nil, nil 1008 | }, { 1009 | "Cult Master", 140, 1010 | Common, Expert, 0, Minion, 1011 | 0, 4, 4, 2, 1012 | nil, nil, nil, nil, nil, nil, nil, nil 1013 | }, { 1014 | "Damaged Golem", 200, 1015 | Common, Expert, 0, Minion, 1016 | 0, 1, 2, 1, 1017 | nil, nil, nil, nil, nil, nil, nil, nil 1018 | }, { 1019 | "Dark Iron Dwarf", 128, 1020 | Common, Expert, 0, Minion, 1021 | 0, 4, 4, 4, 1022 | nil, nil, nil, nil, nil, nil, nil, nil 1023 | }, { 1024 | "Deadly Shot", 239, 1025 | Common, Expert, Hunter, Spell, 1026 | 0, 3, 0, 0, 1027 | nil, nil, nil, nil, nil, nil, nil, nil 1028 | }, { 1029 | "Defender", 318, 1030 | Common, Expert, Paladin, Minion, 1031 | 0, 1, 2, 1, 1032 | nil, nil, nil, nil, nil, nil, nil, nil 1033 | }, { 1034 | "Defias Bandit", 9, 1035 | Free, Expert, Rogue, Minion, 1036 | 0, 1, 2, 1, 1037 | nil, nil, nil, nil, nil, nil, nil, nil 1038 | }, { 1039 | "Defias Ringleader", 417, 1040 | Common, Expert, Rogue, Minion, 1041 | 0, 2, 2, 2, 1042 | nil, nil, nil, nil, nil, nil, nil, nil 1043 | }, { 1044 | "Demigod's Favor", 358, 1045 | Free, Expert, Druid, Spell, 1046 | 0, 0, 0, 0, 1047 | nil, nil, nil, nil, nil, nil, nil, nil 1048 | }, { 1049 | "Demonfire", 452, 1050 | Common, Expert, Warlock, Spell, 1051 | 0, 2, 0, 0, 1052 | nil, nil, nil, nil, nil, nil, nil, nil 1053 | }, { 1054 | "Devilsaur", 354, 1055 | Common, Expert, 0, Minion, 1056 | Beast, 5, 5, 5, 1057 | nil, nil, nil, nil, nil, nil, nil, nil 1058 | }, { 1059 | "Dire Wolf Alpha", 305, 1060 | Common, Expert, 0, Minion, 1061 | Beast, 2, 2, 2, 1062 | nil, nil, nil, nil, nil, nil, nil, nil 1063 | }, { 1064 | "Dispel", 524, 1065 | Free, Expert, Druid, Spell, 1066 | 0, 0, 0, 0, 1067 | nil, nil, nil, nil, nil, nil, nil, nil 1068 | }, { 1069 | "Dread Corsair", 261, 1070 | Common, Expert, 0, Minion, 1071 | Pirate, 31, 3, 3, 1072 | nil, nil, nil, nil, nil, nil, nil, nil 1073 | }, { 1074 | "Dream", 561, 1075 | Free, Expert, 0, Spell, 1076 | 0, 0, 0, 0, 1077 | nil, nil, nil, nil, nil, nil, nil, nil 1078 | }, { 1079 | "Druid of the Claw", 587, 1080 | Common, Expert, Druid, Minion, 1081 | 0, 5, 4, 4, 1082 | nil, nil, nil, nil, nil, nil, nil, nil 1083 | }, { 1084 | "Druid of the Claw", 408, 1085 | Common, Expert, Druid, Minion, 1086 | 0, 5, 4, 4, 1087 | nil, nil, nil, nil, nil, nil, nil, nil 1088 | }, { 1089 | "Druid of the Claw", 45, 1090 | Common, Expert, Druid, Minion, 1091 | 0, 5, 4, 6, 1092 | nil, nil, nil, nil, nil, nil, nil, nil 1093 | }, { 1094 | "Dust Devil", 129, 1095 | Common, Expert, Shaman, Minion, 1096 | 0, 1, 3, 1, 1097 | nil, nil, nil, nil, nil, nil, nil, nil 1098 | }, { 1099 | "Earth Shock", 77, 1100 | Common, Expert, Shaman, Spell, 1101 | 0, 1, 0, 0, 1102 | nil, nil, nil, nil, nil, nil, nil, nil 1103 | }, { 1104 | "Earthen Ring Farseer", 557, 1105 | Common, Expert, 0, Minion, 1106 | 0, 3, 3, 3, 1107 | nil, nil, nil, nil, nil, nil, nil, nil 1108 | }, { 1109 | "Emerald Drake", 534, 1110 | Free, Expert, 0, Minion, 1111 | Dragon, 4, 7, 6, 1112 | nil, nil, nil, nil, nil, nil, nil, nil 1113 | }, { 1114 | "Eviscerate", 382, 1115 | Common, Expert, Rogue, Spell, 1116 | 0, 2, 0, 0, 1117 | nil, nil, nil, nil, nil, nil, nil, nil 1118 | }, { 1119 | "Explosive Trap", 344, 1120 | Common, Expert, Hunter, Secret, 1121 | 0, 2, 0, 0, 1122 | nil, nil, nil, nil, nil, nil, nil, nil 1123 | }, { 1124 | "Eye for an Eye", 206, 1125 | Common, Expert, Paladin, Secret, 1126 | 0, 1, 0, 0, 1127 | nil, nil, nil, nil, nil, nil, nil, nil 1128 | }, { 1129 | "Faerie Dragon", 213, 1130 | Common, Expert, 0, Minion, 1131 | Dragon, 2, 3, 2, 1132 | nil, nil, nil, nil, nil, nil, nil, nil 1133 | }, { 1134 | "Fen Creeper", 476, 1135 | Common, Expert, 0, Minion, 1136 | 0, 5, 3, 6, 1137 | nil, nil, nil, nil, nil, nil, nil, nil 1138 | }, { 1139 | "Flame Imp", 85, 1140 | Common, Expert, Warlock, Minion, 1141 | Demon, 1, 3, 2, 1142 | nil, nil, nil, nil, nil, nil, nil, nil 1143 | }, { 1144 | "Flame of Azzinoth", 685, 1145 | Free, Expert, 0, Minion, 1146 | 0, 1, 2, 1, 1147 | nil, nil, nil, nil, nil, nil, nil, nil 1148 | }, { 1149 | "Flesheating Ghoul", 610, 1150 | Common, Expert, 0, Minion, 1151 | 0, 3, 2, 3, 1152 | nil, nil, nil, nil, nil, nil, nil, nil 1153 | }, { 1154 | "Forked Lightning", 530, 1155 | Common, Expert, Shaman, Spell, 1156 | 0, 1, 0, 0, 1157 | nil, nil, nil, nil, nil, nil, nil, nil 1158 | }, { 1159 | "Freezing Trap", 99, 1160 | Common, Expert, Hunter, Secret, 1161 | 0, 2, 0, 0, 1162 | nil, nil, nil, nil, nil, nil, nil, nil 1163 | }, { 1164 | "Frost Elemental", 598, 1165 | Common, Expert, 0, Minion, 1166 | 0, 6, 5, 5, 1167 | nil, nil, nil, nil, nil, nil, nil, nil 1168 | }, { 1169 | "Gnoll", 565, 1170 | Free, Expert, 0, Minion, 1171 | 0, 2, 2, 2, 1172 | nil, nil, nil, nil, nil, nil, nil, nil 1173 | }, { 1174 | "Harvest Golem", 386, 1175 | Common, Expert, 0, Minion, 1176 | 0, 3, 2, 3, 1177 | nil, nil, nil, nil, nil, nil, nil, nil 1178 | }, { 1179 | "Heavy Axe", 583, 1180 | Free, Expert, Warrior, Weapon, 1181 | 0, 1, 1, 3, 1182 | nil, nil, nil, nil, nil, nil, nil, nil 1183 | }, { 1184 | "Ice Barrier", 672, 1185 | Common, Expert, Mage, Secret, 1186 | 0, 3, 0, 0, 1187 | nil, nil, nil, nil, nil, nil, nil, nil 1188 | }, { 1189 | "Ice Lance", 188, 1190 | Common, Expert, Mage, Spell, 1191 | 0, 1, 0, 0, 1192 | nil, nil, nil, nil, nil, nil, nil, nil 1193 | }, { 1194 | "Infernal", 121, 1195 | Common, Expert, Warlock, Minion, 1196 | Demon, 6, 6, 6, 1197 | nil, nil, nil, nil, nil, nil, nil, nil 1198 | }, { 1199 | "INFERNO!", 83, 1200 | Free, Expert, Warlock, Hero_power, 1201 | 0, 2, 0, 0, 1202 | nil, nil, nil, nil, nil, nil, nil, nil 1203 | }, { 1204 | "Inner Fire", 207, 1205 | Common, Expert, Priest, Spell, 1206 | 0, 1, 0, 0, 1207 | nil, nil, nil, nil, nil, nil, nil, nil 1208 | }, { 1209 | "Inner Rage", 366, 1210 | Common, Expert, Warrior, Spell, 1211 | 0, 0, 0, 0, 1212 | nil, nil, nil, nil, nil, nil, nil, nil 1213 | }, { 1214 | "Ironbeak Owl", 500, 1215 | Common, Expert, 0, Minion, 1216 | Beast, 2, 2, 1, 1217 | nil, nil, nil, nil, nil, nil, nil, nil 1218 | }, { 1219 | "Jungle Panther", 392, 1220 | Common, Expert, 0, Minion, 1221 | Beast, 3, 4, 2, 1222 | nil, nil, nil, nil, nil, nil, nil, nil 1223 | }, { 1224 | "Laughing Sister", 116, 1225 | Free, Expert, 0, Minion, 1226 | 0, 3, 3, 5, 1227 | nil, nil, nil, nil, nil, nil, nil, nil 1228 | }, { 1229 | "Leader of the Pack", 204, 1230 | Free, Expert, Druid, Spell, 1231 | 0, 0, 0, 0, 1232 | nil, nil, nil, nil, nil, nil, nil, nil 1233 | }, { 1234 | "Leper Gnome", 513, 1235 | Common, Expert, 0, Minion, 1236 | 0, 1, 2, 1, 1237 | nil, nil, nil, nil, nil, nil, nil, nil 1238 | }, { 1239 | "Lightning Bolt", 10, 1240 | Common, Expert, Shaman, Spell, 1241 | 0, 1, 0, 0, 1242 | nil, nil, nil, nil, nil, nil, nil, nil 1243 | }, { 1244 | "Lightspawn", 192, 1245 | Common, Expert, Priest, Minion, 1246 | 0, 4, 0, 5, 1247 | nil, nil, nil, nil, nil, nil, nil, nil 1248 | }, { 1249 | "Loot Hoarder", 395, 1250 | Common, Expert, 0, Minion, 1251 | 0, 2, 2, 1, 1252 | nil, nil, nil, nil, nil, nil, nil, nil 1253 | }, { 1254 | "Mad Bomber", 80, 1255 | Common, Expert, 0, Minion, 1256 | 0, 2, 3, 2, 1257 | nil, nil, nil, nil, nil, nil, nil, nil 1258 | }, { 1259 | "Mana Wyrm", 263, 1260 | Common, Expert, Mage, Minion, 1261 | 0, 1, 1, 3, 1262 | nil, nil, nil, nil, nil, nil, nil, nil 1263 | }, { 1264 | "Mark of Nature", 149, 1265 | Common, Expert, Druid, Spell, 1266 | 0, 3, 0, 0, 1267 | nil, nil, nil, nil, nil, nil, nil, nil 1268 | }, { 1269 | "Mark of Nature", 430, 1270 | Free, Expert, Druid, Spell, 1271 | 0, 0, 0, 0, 1272 | nil, nil, nil, nil, nil, nil, nil, nil 1273 | }, { 1274 | "Mark of Nature", 133, 1275 | Free, Expert, Druid, Spell, 1276 | 0, 0, 0, 0, 1277 | nil, nil, nil, nil, nil, nil, nil, nil 1278 | }, { 1279 | "Mind Shatter", 229, 1280 | Free, Expert, Priest, Hero_power, 1281 | 0, 2, 0, 0, 1282 | nil, nil, nil, nil, nil, nil, nil, nil 1283 | }, { 1284 | "Mind Spike", 70, 1285 | Free, Expert, Priest, Hero_power, 1286 | 0, 2, 0, 0, 1287 | nil, nil, nil, nil, nil, nil, nil, nil 1288 | }, { 1289 | "Mirror Entity", 569, 1290 | Common, Expert, Mage, Secret, 1291 | 0, 3, 0, 0, 1292 | nil, nil, nil, nil, nil, nil, nil, nil 1293 | }, { 1294 | "Mogu'shan Warden", 346, 1295 | Common, Expert, 0, Minion, 1296 | 0, 4, 1, 7, 1297 | nil, nil, nil, nil, nil, nil, nil, nil 1298 | }, { 1299 | "Moonfire", 111, 1300 | Free, Expert, Druid, Spell, 1301 | 0, 0, 0, 0, 1302 | nil, nil, nil, nil, nil, nil, nil, nil 1303 | }, { 1304 | "Naturalize", 154, 1305 | Common, Expert, Druid, Spell, 1306 | 0, 1, 0, 0, 1307 | nil, nil, nil, nil, nil, nil, nil, nil 1308 | }, { 1309 | "Nightmare", 334, 1310 | Free, Expert, 0, Spell, 1311 | 0, 0, 0, 0, 1312 | nil, nil, nil, nil, nil, nil, nil, nil 1313 | }, { 1314 | "Noble Sacrifice", 158, 1315 | Common, Expert, Paladin, Secret, 1316 | 0, 1, 0, 0, 1317 | nil, nil, nil, nil, nil, nil, nil, nil 1318 | }, { 1319 | "Nourish", 58, 1320 | Free, Expert, Druid, Spell, 1321 | 0, 0, 0, 0, 1322 | nil, nil, nil, nil, nil, nil, nil, nil 1323 | }, { 1324 | "Nourish", 485, 1325 | Free, Expert, Druid, Spell, 1326 | 0, 0, 0, 0, 1327 | nil, nil, nil, nil, nil, nil, nil, nil 1328 | }, { 1329 | "Panther", 190, 1330 | Common, Expert, Druid, Minion, 1331 | Beast, 2, 3, 2, 1332 | nil, nil, nil, nil, nil, nil, nil, nil 1333 | }, { 1334 | "Power of the Wild", 165, 1335 | Common, Expert, Druid, Spell, 1336 | 0, 2, 0, 0, 1337 | nil, nil, nil, nil, nil, nil, nil, nil 1338 | }, { 1339 | "Power Overwhelming", 170, 1340 | Common, Expert, Warlock, Spell, 1341 | 0, 1, 0, 0, 1342 | nil, nil, nil, nil, nil, nil, nil, nil 1343 | }, { 1344 | "Priestess of Elune", 138, 1345 | Common, Expert, 0, Minion, 1346 | 0, 6, 5, 4, 1347 | nil, nil, nil, nil, nil, nil, nil, nil 1348 | }, { 1349 | "Raging Worgen", 95, 1350 | Common, Expert, 0, Minion, 1351 | 0, 3, 3, 3, 1352 | nil, nil, nil, nil, nil, nil, nil, nil 1353 | }, { 1354 | "Rampage", 454, 1355 | Common, Expert, Warrior, Spell, 1356 | 0, 2, 0, 0, 1357 | nil, nil, nil, nil, nil, nil, nil, nil 1358 | }, { 1359 | "Redemption", 657, 1360 | Common, Expert, Paladin, Secret, 1361 | 0, 1, 0, 0, 1362 | nil, nil, nil, nil, nil, nil, nil, nil 1363 | }, { 1364 | "Repentance", 642, 1365 | Common, Expert, Paladin, Secret, 1366 | 0, 1, 0, 0, 1367 | nil, nil, nil, nil, nil, nil, nil, nil 1368 | }, { 1369 | "Rooted", 375, 1370 | Free, Expert, Druid, Spell, 1371 | 0, 0, 0, 0, 1372 | nil, nil, nil, nil, nil, nil, nil, nil 1373 | }, { 1374 | "Scarlet Crusader", 475, 1375 | Common, Expert, 0, Minion, 1376 | 0, 3, 3, 1, 1377 | nil, nil, nil, nil, nil, nil, nil, nil 1378 | }, { 1379 | "Scavenging Hyena", 279, 1380 | Common, Expert, Hunter, Minion, 1381 | Beast, 2, 2, 2, 1382 | nil, nil, nil, nil, nil, nil, nil, nil 1383 | }, { 1384 | "Sense Demons", 327, 1385 | Common, Expert, Warlock, Spell, 1386 | 0, 3, 0, 0, 1387 | nil, nil, nil, nil, nil, nil, nil, nil 1388 | }, { 1389 | "Shadowstep", 550, 1390 | Common, Expert, Rogue, Spell, 1391 | 0, 0, 0, 0, 1392 | nil, nil, nil, nil, nil, nil, nil, nil 1393 | }, { 1394 | "Shan'do's Lesson", 159, 1395 | Free, Expert, Druid, Spell, 1396 | 0, 0, 0, 0, 1397 | nil, nil, nil, nil, nil, nil, nil, nil 1398 | }, { 1399 | "Shieldbearer", 24, 1400 | Common, Expert, 0, Minion, 1401 | 0, 1, 0, 4, 1402 | nil, nil, nil, nil, nil, nil, nil, nil 1403 | }, { 1404 | "Silence", 544, 1405 | Common, Expert, Priest, Spell, 1406 | 0, 0, 0, 0, 1407 | nil, nil, nil, nil, nil, nil, nil, nil 1408 | }, { 1409 | "Silver Hand Knight", 648, 1410 | Common, Expert, 0, Minion, 1411 | 0, 5, 4, 4, 1412 | nil, nil, nil, nil, nil, nil, nil, nil 1413 | }, { 1414 | "Silvermoon Guardian", 634, 1415 | Common, Expert, 0, Minion, 1416 | 0, 4, 3, 3, 1417 | nil, nil, nil, nil, nil, nil, nil, nil 1418 | }, { 1419 | "Skeleton", 255, 1420 | Free, Expert, 0, Minion, 1421 | 0, 3, 3, 3, 1422 | nil, nil, nil, nil, nil, nil, nil, nil 1423 | }, { 1424 | "Slam", 215, 1425 | Common, Expert, Warrior, Spell, 1426 | 0, 2, 0, 0, 1427 | nil, nil, nil, nil, nil, nil, nil, nil 1428 | }, { 1429 | "Snake", 512, 1430 | Common, Expert, Hunter, Minion, 1431 | Beast, 0, 1, 1, 1432 | nil, nil, nil, nil, nil, nil, nil, nil 1433 | }, { 1434 | "Snipe", 553, 1435 | Common, Expert, Hunter, Secret, 1436 | 0, 2, 0, 0, 1437 | nil, nil, nil, nil, nil, nil, nil, nil 1438 | }, { 1439 | "Sorcerer's Apprentice", 4, 1440 | Common, Expert, Mage, Minion, 1441 | 0, 2, 3, 2, 1442 | nil, nil, nil, nil, nil, nil, nil, nil 1443 | }, { 1444 | "Soul of the Forest", 311, 1445 | Common, Expert, Druid, Spell, 1446 | 0, 4, 0, 0, 1447 | nil, nil, nil, nil, nil, nil, nil, nil 1448 | }, { 1449 | "Southsea Deckhand", 103, 1450 | Common, Expert, 0, Minion, 1451 | Pirate, 1, 2, 1, 1452 | nil, nil, nil, nil, nil, nil, nil, nil 1453 | }, { 1454 | "Spellbreaker", 42, 1455 | Common, Expert, 0, Minion, 1456 | 0, 4, 4, 3, 1457 | nil, nil, nil, nil, nil, nil, nil, nil 1458 | }, { 1459 | "Spiteful Smith", 627, 1460 | Common, Expert, Warrior, Minion, 1461 | 0, 5, 4, 6, 1462 | nil, nil, nil, nil, nil, nil, nil, nil 1463 | }, { 1464 | "Squire", 21, 1465 | Common, Expert, 0, Minion, 1466 | 0, 1, 2, 2, 1467 | nil, nil, nil, nil, nil, nil, nil, nil 1468 | }, { 1469 | "Squirrel", 469, 1470 | Common, Expert, 0, Minion, 1471 | Beast, 1, 1, 1, 1472 | nil, nil, nil, nil, nil, nil, nil, nil 1473 | }, { 1474 | "Starfall", 653, 1475 | Free, Expert, Druid, Spell, 1476 | 0, 0, 0, 0, 1477 | nil, nil, nil, nil, nil, nil, nil, nil 1478 | }, { 1479 | "Starfall", 195, 1480 | Common, 0, Druid, Spell, 1481 | 0, 0, 0, 0, 1482 | nil, nil, nil, nil, nil, nil, nil, nil 1483 | }, { 1484 | "Stormforged Axe", 152, 1485 | Common, Expert, Shaman, Weapon, 1486 | 0, 2, 2, 3, 1487 | nil, nil, nil, nil, nil, nil, nil, nil 1488 | }, { 1489 | "Stranglethorn Tiger", 338, 1490 | Common, Expert, 0, Minion, 1491 | Beast, 5, 5, 5, 1492 | nil, nil, nil, nil, nil, nil, nil, nil 1493 | }, { 1494 | "Summon a Panther", 219, 1495 | Free, Expert, Druid, Spell, 1496 | 0, 0, 0, 0, 1497 | nil, nil, nil, nil, nil, nil, nil, nil 1498 | }, { 1499 | "Summoning Portal", 566, 1500 | Common, Expert, Warlock, Minion, 1501 | 0, 4, 0, 4, 1502 | nil, nil, nil, nil, nil, nil, nil, nil 1503 | }, { 1504 | "Tauren Warrior", 477, 1505 | Common, Expert, 0, Minion, 1506 | 0, 3, 2, 3, 1507 | nil, nil, nil, nil, nil, nil, nil, nil 1508 | }, { 1509 | "Temple Enforcer", 232, 1510 | Common, Expert, Priest, Minion, 1511 | 0, 6, 6, 6, 1512 | nil, nil, nil, nil, nil, nil, nil, nil 1513 | }, { 1514 | "Thoughtsteal", 62, 1515 | Common, Expert, Priest, Spell, 1516 | 0, 3, 0, 0, 1517 | nil, nil, nil, nil, nil, nil, nil, nil 1518 | }, { 1519 | "Thrallmar Farseer", 265, 1520 | Common, Expert, 0, Minion, 1521 | 0, 3, 2, 3, 1522 | nil, nil, nil, nil, nil, nil, nil, nil 1523 | }, { 1524 | "Treant", 272, 1525 | Free, Expert, Druid, Minion, 1526 | 0, 1, 2, 2, 1527 | nil, nil, nil, nil, nil, nil, nil, nil 1528 | }, { 1529 | "Treant", 337, 1530 | Common, Expert, Druid, Minion, 1531 | 0, 1, 2, 2, 1532 | nil, nil, nil, nil, nil, nil, nil, nil 1533 | }, { 1534 | "Treant", 181, 1535 | Free, Expert, Druid, Minion, 1536 | 0, 1, 2, 2, 1537 | nil, nil, nil, nil, nil, nil, nil, nil 1538 | }, { 1539 | "Unbound Elemental", 51, 1540 | Common, Expert, Shaman, Minion, 1541 | 0, 3, 2, 4, 1542 | nil, nil, nil, nil, nil, nil, nil, nil 1543 | }, { 1544 | "Unleash the Hounds", 317, 1545 | Common, Expert, Hunter, Spell, 1546 | 0, 4, 0, 0, 1547 | nil, nil, nil, nil, nil, nil, nil, nil 1548 | }, { 1549 | "Uproot", 262, 1550 | Free, Expert, Druid, Spell, 1551 | 0, 0, 0, 0, 1552 | nil, nil, nil, nil, nil, nil, nil, nil 1553 | }, { 1554 | "Venture Co. Mercenary", 509, 1555 | Common, Expert, 0, Minion, 1556 | 0, 5, 7, 6, 1557 | nil, nil, nil, nil, nil, nil, nil, nil 1558 | }, { 1559 | "Violet Apprentice", 63, 1560 | Free, Expert, 0, Minion, 1561 | 0, 0, 1, 1, 1562 | nil, nil, nil, nil, nil, nil, nil, nil 1563 | }, { 1564 | "Whelp", 527, 1565 | Free, Expert, 0, Minion, 1566 | Dragon, 1, 1, 1, 1567 | nil, nil, nil, nil, nil, nil, nil, nil 1568 | }, { 1569 | "Windfury Harpy", 675, 1570 | Common, Expert, 0, Minion, 1571 | 0, 6, 4, 5, 1572 | nil, nil, nil, nil, nil, nil, nil, nil 1573 | }, { 1574 | "Wisp", 273, 1575 | Common, Expert, 0, Minion, 1576 | 0, 0, 1, 1, 1577 | nil, nil, nil, nil, nil, nil, nil, nil 1578 | }, { 1579 | "Worgen Infiltrator", 112, 1580 | Common, Expert, 0, Minion, 1581 | 0, 1, 2, 1, 1582 | nil, nil, nil, nil, nil, nil, nil, nil 1583 | }, { 1584 | "Worthless Imp", 230, 1585 | Common, Expert, Warlock, Minion, 1586 | Demon, 1, 1, 1, 1587 | nil, nil, nil, nil, nil, nil, nil, nil 1588 | }, { 1589 | "Wrath", 633, 1590 | Common, Expert, Druid, Spell, 1591 | 0, 2, 0, 0, 1592 | nil, nil, nil, nil, nil, nil, nil, nil 1593 | }, { 1594 | "Wrath", 234, 1595 | Free, Expert, Druid, Spell, 1596 | 0, 0, 0, 0, 1597 | nil, nil, nil, nil, nil, nil, nil, nil 1598 | }, { 1599 | "Wrath", 501, 1600 | Free, Expert, Druid, Spell, 1601 | 0, 0, 0, 0, 1602 | nil, nil, nil, nil, nil, nil, nil, nil 1603 | }, { 1604 | "Young Dragonhawk", 629, 1605 | Common, Expert, 0, Minion, 1606 | Beast, 1, 1, 1, 1607 | nil, nil, nil, nil, nil, nil, nil, nil 1608 | }, { 1609 | "Youthful Brewmaster", 247, 1610 | Common, Expert, 0, Minion, 1611 | 0, 2, 3, 2, 1612 | nil, nil, nil, nil, nil, nil, nil, nil 1613 | }, { 1614 | "Ysera Awakens", 235, 1615 | Free, Expert, 0, Spell, 1616 | 0, 2, 0, 0, 1617 | nil, nil, nil, nil, nil, nil, nil, nil 1618 | }, { 1619 | "Acidic Swamp Ooze", 74, 1620 | Common, Basic, 0, Minion, 1621 | 0, 2, 3, 2, 1622 | nil, nil, nil, nil, nil, nil, nil, nil 1623 | }, { 1624 | "Animal Companion", 578, 1625 | Common, Basic, Hunter, Spell, 1626 | 0, 3, 0, 0, 1627 | nil, nil, nil, nil, nil, nil, nil, nil 1628 | }, { 1629 | "Arcanite Reaper", 182, 1630 | Common, Basic, Warrior, Weapon, 1631 | 0, 5, 5, 2, 1632 | nil, nil, nil, nil, nil, nil, nil, nil 1633 | }, { 1634 | "Archmage", 545, 1635 | Common, Basic, 0, Minion, 1636 | 0, 6, 4, 7, 1637 | nil, nil, nil, nil, nil, nil, nil, nil 1638 | }, { 1639 | "Assassin's Blade", 433, 1640 | Common, Basic, Rogue, Weapon, 1641 | 0, 5, 3, 4, 1642 | nil, nil, nil, nil, nil, nil, nil, nil 1643 | }, { 1644 | "Bananas", 156, 1645 | Common, Missions, 0, Spell, 1646 | 0, 1, 0, 0, 1647 | nil, nil, nil, nil, nil, nil, nil, nil 1648 | }, { 1649 | "Barrel", 376, 1650 | Common, Missions, 0, Minion, 1651 | 0, 0, 0, 2, 1652 | nil, nil, nil, nil, nil, nil, nil, nil 1653 | }, { 1654 | "Barrel Toss", 606, 1655 | Common, Missions, 0, Spell, 1656 | 0, 1, 0, 0, 1657 | nil, nil, nil, nil, nil, nil, nil, nil 1658 | }, { 1659 | "Blessing of Kings", 29, 1660 | Common, Basic, Paladin, Spell, 1661 | 0, 4, 0, 0, 1662 | nil, nil, nil, nil, nil, nil, nil, nil 1663 | }, { 1664 | "Bloodlust", 256, 1665 | Common, Basic, Shaman, Spell, 1666 | 0, 5, 0, 0, 1667 | nil, nil, nil, nil, nil, nil, nil, nil 1668 | }, { 1669 | "Bluegill Warrior", 289, 1670 | Common, Basic, 0, Minion, 1671 | Murloc, 2, 2, 1, 1672 | nil, nil, nil, nil, nil, nil, nil, nil 1673 | }, { 1674 | "Boar", 65, 1675 | Common, Basic, 0, Minion, 1676 | Beast, 1, 1, 1, 1677 | nil, nil, nil, nil, nil, nil, nil, nil 1678 | }, { 1679 | "Booty Bay Bodyguard", 27, 1680 | Common, Basic, 0, Minion, 1681 | 0, 5, 5, 4, 1682 | nil, nil, nil, nil, nil, nil, nil, nil 1683 | }, { 1684 | "Brewmaster", 397, 1685 | Common, Missions, 0, Minion, 1686 | 0, 4, 4, 4, 1687 | nil, nil, nil, nil, nil, nil, nil, nil 1688 | }, { 1689 | "Chillwind Yeti", 31, 1690 | Common, Basic, 0, Minion, 1691 | 0, 4, 4, 5, 1692 | nil, nil, nil, nil, nil, nil, nil, nil 1693 | }, { 1694 | "Cleave", 81, 1695 | Common, Basic, Warrior, Spell, 1696 | 0, 2, 0, 0, 1697 | nil, nil, nil, nil, nil, nil, nil, nil 1698 | }, { 1699 | "Consecration", 260, 1700 | Common, Basic, Paladin, Spell, 1701 | 0, 4, 0, 0, 1702 | nil, nil, nil, nil, nil, nil, nil, nil 1703 | }, { 1704 | "Core Hound", 173, 1705 | Common, Basic, 0, Minion, 1706 | Beast, 7, 9, 5, 1707 | nil, nil, nil, nil, nil, nil, nil, nil 1708 | }, { 1709 | "Corruption", 252, 1710 | Common, Basic, Warlock, Spell, 1711 | 0, 1, 0, 0, 1712 | nil, nil, nil, nil, nil, nil, nil, nil 1713 | }, { 1714 | "Crazed Hunter", 377, 1715 | Common, Missions, 0, Minion, 1716 | 0, 1, 1, 1, 1717 | nil, nil, nil, nil, nil, nil, nil, nil 1718 | }, { 1719 | "Crazy Monkey", 393, 1720 | Common, Missions, 0, Minion, 1721 | 0, 1, 1, 2, 1722 | nil, nil, nil, nil, nil, nil, nil, nil 1723 | }, { 1724 | "Dalaran Mage", 388, 1725 | Common, Basic, 0, Minion, 1726 | 0, 3, 1, 4, 1727 | nil, nil, nil, nil, nil, nil, nil, nil 1728 | }, { 1729 | "Darkscale Healer", 84, 1730 | Common, Basic, 0, Minion, 1731 | 0, 4, 4, 5, 1732 | nil, nil, nil, nil, nil, nil, nil, nil 1733 | }, { 1734 | "Divine Spirit", 554, 1735 | Common, Basic, Priest, Spell, 1736 | 0, 2, 0, 0, 1737 | nil, nil, nil, nil, nil, nil, nil, nil 1738 | }, { 1739 | "Dragonling Mechanic", 472, 1740 | Common, Basic, 0, Minion, 1741 | 0, 4, 2, 4, 1742 | nil, nil, nil, nil, nil, nil, nil, nil 1743 | }, { 1744 | "Dread Infernal", 36, 1745 | Common, Basic, Warlock, Minion, 1746 | Demon, 6, 6, 6, 1747 | nil, nil, nil, nil, nil, nil, nil, nil 1748 | }, { 1749 | "Dual Warglaives", 599, 1750 | Common, Missions, 0, Weapon, 1751 | 0, 6, 4, 2, 1752 | nil, nil, nil, nil, nil, nil, nil, nil 1753 | }, { 1754 | "Elven Archer", 356, 1755 | Common, Basic, 0, Minion, 1756 | 0, 1, 1, 1, 1757 | nil, nil, nil, nil, nil, nil, nil, nil 1758 | }, { 1759 | "Emboldener 3000", 240, 1760 | Common, Reward, 0, Minion, 1761 | 0, 1, 0, 4, 1762 | nil, nil, nil, nil, nil, nil, nil, nil 1763 | }, { 1764 | "Fan of Knives", 378, 1765 | Common, Basic, Rogue, Spell, 1766 | 0, 3, 0, 0, 1767 | nil, nil, nil, nil, nil, nil, nil, nil 1768 | }, { 1769 | "Fire Elemental", 636, 1770 | Common, Basic, 0, Minion, 1771 | 0, 6, 6, 5, 1772 | nil, nil, nil, nil, nil, nil, nil, nil 1773 | }, { 1774 | "Flame Burst", 622, 1775 | Common, Missions, 0, Spell, 1776 | 0, 3, 0, 0, 1777 | nil, nil, nil, nil, nil, nil, nil, nil 1778 | }, { 1779 | "Flame of Azzinoth", 455, 1780 | Common, Missions, 0, Minion, 1781 | 0, 1, 2, 1, 1782 | nil, nil, nil, nil, nil, nil, nil, nil 1783 | }, { 1784 | "Flamestrike", 44, 1785 | Common, Basic, Mage, Spell, 1786 | 0, 7, 0, 0, 1787 | nil, nil, nil, nil, nil, nil, nil, nil 1788 | }, { 1789 | "Flametongue Totem", 390, 1790 | Common, Basic, Shaman, Minion, 1791 | Totem, 2, 0, 3, 1792 | nil, nil, nil, nil, nil, nil, nil, nil 1793 | }, { 1794 | "Frog", 115, 1795 | Common, Basic, 0, Minion, 1796 | Beast, 0, 0, 1, 1797 | nil, nil, nil, nil, nil, nil, nil, nil 1798 | }, { 1799 | "Frost Nova", 49, 1800 | Common, Basic, Mage, Spell, 1801 | 0, 3, 0, 0, 1802 | nil, nil, nil, nil, nil, nil, nil, nil 1803 | }, { 1804 | "Frostbolt", 177, 1805 | Common, Basic, Mage, Spell, 1806 | 0, 2, 0, 0, 1807 | nil, nil, nil, nil, nil, nil, nil, nil 1808 | }, { 1809 | "Frostwolf Grunt", 663, 1810 | Common, Basic, 0, Minion, 1811 | 0, 2, 2, 2, 1812 | nil, nil, nil, nil, nil, nil, nil, nil 1813 | }, { 1814 | "Frostwolf Warlord", 604, 1815 | Common, Basic, 0, Minion, 1816 | 0, 5, 4, 4, 1817 | nil, nil, nil, nil, nil, nil, nil, nil 1818 | }, { 1819 | "Gnoll", 381, 1820 | Common, Missions, 0, Minion, 1821 | 0, 1, 1, 1, 1822 | nil, nil, nil, nil, nil, nil, nil, nil 1823 | }, { 1824 | "Gnomish Inventor", 246, 1825 | Common, Basic, 0, Minion, 1826 | 0, 4, 2, 4, 1827 | nil, nil, nil, nil, nil, nil, nil, nil 1828 | }, { 1829 | "Goldshire Footman", 564, 1830 | Common, Basic, 0, Minion, 1831 | 0, 1, 1, 2, 1832 | nil, nil, nil, nil, nil, nil, nil, nil 1833 | }, { 1834 | "Grimscale Oracle", 510, 1835 | Common, Basic, 0, Minion, 1836 | Murloc, 1, 1, 1, 1837 | nil, nil, nil, nil, nil, nil, nil, nil 1838 | }, { 1839 | "Guardian of Kings", 283, 1840 | Common, Basic, Paladin, Minion, 1841 | 0, 7, 5, 6, 1842 | nil, nil, nil, nil, nil, nil, nil, nil 1843 | }, { 1844 | "Gurubashi Berserker", 624, 1845 | Common, Basic, 0, Minion, 1846 | 0, 5, 2, 7, 1847 | nil, nil, nil, nil, nil, nil, nil, nil 1848 | }, { 1849 | "Hemet Nesingwary", 470, 1850 | Common, Missions, 0, Hero, 1851 | 0, 0, 0, 20, 1852 | nil, nil, nil, nil, nil, nil, nil, nil 1853 | }, { 1854 | "Hidden Gnome", 387, 1855 | Common, Missions, 0, Minion, 1856 | 0, 2, 1, 3, 1857 | nil, nil, nil, nil, nil, nil, nil, nil 1858 | }, { 1859 | "Hogger", 490, 1860 | Common, Missions, 0, Hero, 1861 | 0, 0, 0, 10, 1862 | nil, nil, nil, nil, nil, nil, nil, nil 1863 | }, { 1864 | "Hogger SMASH!", 443, 1865 | Common, Missions, 0, Spell, 1866 | 0, 3, 0, 0, 1867 | nil, nil, nil, nil, nil, nil, nil, nil 1868 | }, { 1869 | "Holy Nova", 671, 1870 | Common, Basic, Priest, Spell, 1871 | 0, 5, 0, 0, 1872 | nil, nil, nil, nil, nil, nil, nil, nil 1873 | }, { 1874 | "Homing Chicken", 423, 1875 | Common, Reward, 0, Minion, 1876 | 0, 1, 0, 1, 1877 | nil, nil, nil, nil, nil, nil, nil, nil 1878 | }, { 1879 | "Huffer", 369, 1880 | Common, Basic, Hunter, Minion, 1881 | Beast, 3, 4, 2, 1882 | nil, nil, nil, nil, nil, nil, nil, nil 1883 | }, { 1884 | "Humility", 189, 1885 | Common, Basic, Paladin, Spell, 1886 | 0, 1, 0, 0, 1887 | nil, nil, nil, nil, nil, nil, nil, nil 1888 | }, { 1889 | "Hunter's Mark", 22, 1890 | Common, Basic, Hunter, Spell, 1891 | 0, 0, 0, 0, 1892 | nil, nil, nil, nil, nil, nil, nil, nil 1893 | }, { 1894 | "Ironbark Protector", 238, 1895 | Common, Basic, Druid, Minion, 1896 | 0, 8, 8, 8, 1897 | nil, nil, nil, nil, nil, nil, nil, nil 1898 | }, { 1899 | "Ironforge Rifleman", 41, 1900 | Common, Basic, 0, Minion, 1901 | 0, 3, 2, 2, 1902 | nil, nil, nil, nil, nil, nil, nil, nil 1903 | }, { 1904 | "Ironfur Grizzly", 519, 1905 | Common, Basic, 0, Minion, 1906 | Beast, 3, 3, 3, 1907 | nil, nil, nil, nil, nil, nil, nil, nil 1908 | }, { 1909 | "Jaina Proudmoore", 139, 1910 | Common, Missions, Mage, Hero, 1911 | 0, 0, 0, 27, 1912 | nil, nil, nil, nil, nil, nil, nil, nil 1913 | }, { 1914 | "Kill Command", 488, 1915 | Common, Basic, Hunter, Spell, 1916 | 0, 3, 0, 0, 1917 | nil, nil, nil, nil, nil, nil, nil, nil 1918 | }, { 1919 | "King Mukla", 444, 1920 | Common, Missions, 0, Hero, 1921 | 0, 0, 0, 26, 1922 | nil, nil, nil, nil, nil, nil, nil, nil 1923 | }, { 1924 | "Kobold Geomancer", 479, 1925 | Common, Basic, 0, Minion, 1926 | 0, 2, 2, 2, 1927 | nil, nil, nil, nil, nil, nil, nil, nil 1928 | }, { 1929 | "Kor'kron Elite", 130, 1930 | Common, Basic, Warrior, Minion, 1931 | 0, 4, 4, 3, 1932 | nil, nil, nil, nil, nil, nil, nil, nil 1933 | }, { 1934 | "Legacy of the Emperor", 441, 1935 | Common, Missions, 0, Spell, 1936 | 0, 3, 0, 0, 1937 | nil, nil, nil, nil, nil, nil, nil, nil 1938 | }, { 1939 | "Leokk", 32, 1940 | Common, Basic, Hunter, Minion, 1941 | 0, 3, 2, 4, 1942 | nil, nil, nil, nil, nil, nil, nil, nil 1943 | }, { 1944 | "Lord of the Arena", 414, 1945 | Common, Basic, 0, Minion, 1946 | 0, 6, 6, 5, 1947 | nil, nil, nil, nil, nil, nil, nil, nil 1948 | }, { 1949 | "Massive Gnoll", 137, 1950 | Common, Missions, 0, Minion, 1951 | 0, 4, 5, 2, 1952 | nil, nil, nil, nil, nil, nil, nil, nil 1953 | }, { 1954 | "Mechanical Dragonling", 680, 1955 | Common, Basic, 0, Minion, 1956 | 0, 1, 2, 1, 1957 | nil, nil, nil, nil, nil, nil, nil, nil 1958 | }, { 1959 | "Metamorphosis", 592, 1960 | Common, Missions, 0, Spell, 1961 | 0, 6, 0, 0, 1962 | nil, nil, nil, nil, nil, nil, nil, nil 1963 | }, { 1964 | "Millhouse Manastorm", 330, 1965 | Common, Missions, Mage, Hero, 1966 | 0, 0, 0, 20, 1967 | nil, nil, nil, nil, nil, nil, nil, nil 1968 | }, { 1969 | "Mind Control", 401, 1970 | Common, Basic, Priest, Spell, 1971 | 0, 10, 0, 0, 1972 | nil, nil, nil, nil, nil, nil, nil, nil 1973 | }, { 1974 | "Mind Vision", 438, 1975 | Common, Basic, Priest, Spell, 1976 | 0, 1, 0, 0, 1977 | nil, nil, nil, nil, nil, nil, nil, nil 1978 | }, { 1979 | "Mirror Image", 30, 1980 | Common, Basic, Mage, Spell, 1981 | 0, 1, 0, 0, 1982 | nil, nil, nil, nil, nil, nil, nil, nil 1983 | }, { 1984 | "Mirror Image", 650, 1985 | Common, Basic, Mage, Minion, 1986 | 0, 0, 0, 2, 1987 | nil, nil, nil, nil, nil, nil, nil, nil 1988 | }, { 1989 | "Misha", 593, 1990 | Common, Basic, Hunter, Minion, 1991 | Beast, 3, 4, 4, 1992 | nil, nil, nil, nil, nil, nil, nil, nil 1993 | }, { 1994 | "Moonfire", 619, 1995 | Common, Basic, Druid, Spell, 1996 | 0, 0, 0, 0, 1997 | nil, nil, nil, nil, nil, nil, nil, nil 1998 | }, { 1999 | "Mortal Coil", 43, 2000 | Common, Basic, Warlock, Spell, 2001 | 0, 1, 0, 0, 2002 | nil, nil, nil, nil, nil, nil, nil, nil 2003 | }, { 2004 | "Mukla's Big Brother", 404, 2005 | Common, Missions, 0, Minion, 2006 | 0, 6, 10, 10, 2007 | nil, nil, nil, nil, nil, nil, nil, nil 2008 | }, { 2009 | "Murloc Scout", 486, 2010 | Common, Basic, 0, Minion, 2011 | Murloc, 0, 1, 1, 2012 | nil, nil, nil, nil, nil, nil, nil, nil 2013 | }, { 2014 | "Murloc Tidehunter", 357, 2015 | Common, Basic, 0, Minion, 2016 | Murloc, 2, 2, 1, 2017 | nil, nil, nil, nil, nil, nil, nil, nil 2018 | }, { 2019 | "Naga Myrmidon", 16, 2020 | Common, Missions, 0, Minion, 2021 | 0, 1, 1, 1, 2022 | nil, nil, nil, nil, nil, nil, nil, nil 2023 | }, { 2024 | "Ogre Magi", 659, 2025 | Common, Basic, 0, Minion, 2026 | 0, 4, 4, 4, 2027 | nil, nil, nil, nil, nil, nil, nil, nil 2028 | }, { 2029 | "Pandaren Scout", 399, 2030 | Common, Missions, 0, Minion, 2031 | 0, 1, 1, 1, 2032 | nil, nil, nil, nil, nil, nil, nil, nil 2033 | }, { 2034 | "Poultryizer", 405, 2035 | Common, Reward, 0, Minion, 2036 | 0, 1, 0, 3, 2037 | nil, nil, nil, nil, nil, nil, nil, nil 2038 | }, { 2039 | "Razorfen Hunter", 47, 2040 | Common, Basic, 0, Minion, 2041 | 0, 3, 2, 3, 2042 | nil, nil, nil, nil, nil, nil, nil, nil 2043 | }, { 2044 | "Repair Bot", 439, 2045 | Common, Reward, 0, Minion, 2046 | 0, 1, 0, 3, 2047 | nil, nil, nil, nil, nil, nil, nil, nil 2048 | }, { 2049 | "Riverpaw Gnoll", 678, 2050 | Common, Missions, 0, Minion, 2051 | 0, 1, 2, 1, 2052 | nil, nil, nil, nil, nil, nil, nil, nil 2053 | }, { 2054 | "Sacrificial Pact", 348, 2055 | Common, Basic, Warlock, Spell, 2056 | 0, 0, 0, 0, 2057 | nil, nil, nil, nil, nil, nil, nil, nil 2058 | }, { 2059 | "Savage Roar", 329, 2060 | Common, Basic, Druid, Spell, 2061 | 0, 3, 0, 0, 2062 | nil, nil, nil, nil, nil, nil, nil, nil 2063 | }, { 2064 | "Shado-Pan Monk", 288, 2065 | Common, Missions, 0, Minion, 2066 | 0, 2, 2, 2, 2067 | nil, nil, nil, nil, nil, nil, nil, nil 2068 | }, { 2069 | "Shadow Word: Death", 547, 2070 | Common, Basic, Priest, Spell, 2071 | 0, 3, 0, 0, 2072 | nil, nil, nil, nil, nil, nil, nil, nil 2073 | }, { 2074 | "Shattered Sun Cleric", 434, 2075 | Common, Basic, 0, Minion, 2076 | 0, 3, 3, 2, 2077 | nil, nil, nil, nil, nil, nil, nil, nil 2078 | }, { 2079 | "Sheep", 218, 2080 | Common, Basic, 0, Minion, 2081 | Beast, 0, 1, 1, 2082 | nil, nil, nil, nil, nil, nil, nil, nil 2083 | }, { 2084 | "Shield Block", 493, 2085 | Common, Basic, Warrior, Spell, 2086 | 0, 3, 0, 0, 2087 | nil, nil, nil, nil, nil, nil, nil, nil 2088 | }, { 2089 | "Shiv", 164, 2090 | Common, Basic, Rogue, Spell, 2091 | 0, 2, 0, 0, 2092 | nil, nil, nil, nil, nil, nil, nil, nil 2093 | }, { 2094 | "Shotgun Blast", 580, 2095 | Common, Missions, Hunter, Hero_power, 2096 | 0, 2, 0, 0, 2097 | nil, nil, nil, nil, nil, nil, nil, nil 2098 | }, { 2099 | "Silverback Patriarch", 611, 2100 | Common, Basic, 0, Minion, 2101 | 0, 3, 1, 4, 2102 | nil, nil, nil, nil, nil, nil, nil, nil 2103 | }, { 2104 | "Soulfire", 529, 2105 | Common, Basic, Warlock, Spell, 2106 | 0, 0, 0, 0, 2107 | nil, nil, nil, nil, nil, nil, nil, nil 2108 | }, { 2109 | "Sprint", 90, 2110 | Common, Basic, Rogue, Spell, 2111 | 0, 7, 0, 0, 2112 | nil, nil, nil, nil, nil, nil, nil, nil 2113 | }, { 2114 | "Starfire", 667, 2115 | Common, Basic, Druid, Spell, 2116 | 0, 6, 0, 0, 2117 | nil, nil, nil, nil, nil, nil, nil, nil 2118 | }, { 2119 | "Starving Buzzard", 101, 2120 | Common, Basic, Hunter, Minion, 2121 | Beast, 2, 2, 1, 2122 | nil, nil, nil, nil, nil, nil, nil, nil 2123 | }, { 2124 | "Stomp", 105, 2125 | Common, Missions, 0, Spell, 2126 | 0, 2, 0, 0, 2127 | nil, nil, nil, nil, nil, nil, nil, nil 2128 | }, { 2129 | "Stormpike Commando", 325, 2130 | Common, Basic, 0, Minion, 2131 | 0, 5, 4, 2, 2132 | nil, nil, nil, nil, nil, nil, nil, nil 2133 | }, { 2134 | "Stormwind Champion", 310, 2135 | Common, Basic, 0, Minion, 2136 | 0, 7, 6, 6, 2137 | nil, nil, nil, nil, nil, nil, nil, nil 2138 | }, { 2139 | "Stormwind Knight", 603, 2140 | Common, Basic, 0, Minion, 2141 | 0, 4, 2, 5, 2142 | nil, nil, nil, nil, nil, nil, nil, nil 2143 | }, { 2144 | "Swipe", 620, 2145 | Common, Basic, Druid, Spell, 2146 | 0, 4, 0, 0, 2147 | nil, nil, nil, nil, nil, nil, nil, nil 2148 | }, { 2149 | "Totemic Might", 367, 2150 | Common, Basic, Shaman, Spell, 2151 | 0, 0, 0, 0, 2152 | nil, nil, nil, nil, nil, nil, nil, nil 2153 | }, { 2154 | "Transcendence", 299, 2155 | Common, Missions, 0, Spell, 2156 | 0, 1, 0, 0, 2157 | nil, nil, nil, nil, nil, nil, nil, nil 2158 | }, { 2159 | "Truesilver Champion", 293, 2160 | Common, Basic, Paladin, Weapon, 2161 | 0, 4, 4, 2, 2162 | nil, nil, nil, nil, nil, nil, nil, nil 2163 | }, { 2164 | "Tundra Rhino", 162, 2165 | Common, Basic, Hunter, Minion, 2166 | Beast, 5, 2, 5, 2167 | nil, nil, nil, nil, nil, nil, nil, nil 2168 | }, { 2169 | "Vanish", 658, 2170 | Common, Basic, Rogue, Spell, 2171 | 0, 6, 0, 0, 2172 | nil, nil, nil, nil, nil, nil, nil, nil 2173 | }, { 2174 | "War Golem", 323, 2175 | Common, Basic, 0, Minion, 2176 | 0, 7, 7, 7, 2177 | nil, nil, nil, nil, nil, nil, nil, nil 2178 | }, { 2179 | "Warglaive of Azzinoth", 494, 2180 | Common, Missions, 0, Weapon, 2181 | 0, 2, 2, 2, 2182 | nil, nil, nil, nil, nil, nil, nil, nil 2183 | }, { 2184 | "Water Elemental", 274, 2185 | Common, Basic, Mage, Minion, 2186 | 0, 4, 3, 6, 2187 | nil, nil, nil, nil, nil, nil, nil, nil 2188 | }, { 2189 | "Whirlwind", 161, 2190 | Common, Basic, Warrior, Spell, 2191 | 0, 1, 0, 0, 2192 | nil, nil, nil, nil, nil, nil, nil, nil 2193 | }, { 2194 | "Will of Mukla", 586, 2195 | Common, Missions, 0, Spell, 2196 | 0, 3, 0, 0, 2197 | nil, nil, nil, nil, nil, nil, nil, nil 2198 | }, { 2199 | "Windspeaker", 151, 2200 | Common, Basic, Shaman, Minion, 2201 | 0, 4, 3, 3, 2202 | nil, nil, nil, nil, nil, nil, nil, nil 2203 | }, { 2204 | "Ancestral Healing", 216, 2205 | Free, Basic, Shaman, Spell, 2206 | 0, 0, 0, 0, 2207 | nil, nil, nil, nil, nil, nil, nil, nil 2208 | }, { 2209 | "Anduin Wrynn", 110, 2210 | Free, Basic, Priest, Hero, 2211 | 0, 0, 0, 30, 2212 | nil, nil, nil, nil, nil, nil, nil, nil 2213 | }, { 2214 | "Arcane Explosion", 56, 2215 | Free, Basic, Mage, Spell, 2216 | 0, 2, 0, 0, 2217 | nil, nil, nil, nil, nil, nil, nil, nil 2218 | }, { 2219 | "Arcane Intellect", 489, 2220 | Free, Basic, Mage, Spell, 2221 | 0, 3, 0, 0, 2222 | nil, nil, nil, nil, nil, nil, nil, nil 2223 | }, { 2224 | "Arcane Missiles", 589, 2225 | Free, Basic, Mage, Spell, 2226 | 0, 1, 0, 0, 2227 | nil, nil, nil, nil, nil, nil, nil, nil 2228 | }, { 2229 | "Arcane Shot", 167, 2230 | Free, Basic, Hunter, Spell, 2231 | 0, 1, 0, 0, 2232 | nil, nil, nil, nil, nil, nil, nil, nil 2233 | }, { 2234 | "Armor Up!", 253, 2235 | Free, Basic, Warrior, Hero_power, 2236 | 0, 2, 0, 0, 2237 | nil, nil, nil, nil, nil, nil, nil, nil 2238 | }, { 2239 | "Assassinate", 568, 2240 | Free, Basic, Rogue, Spell, 2241 | 0, 5, 0, 0, 2242 | nil, nil, nil, nil, nil, nil, nil, nil 2243 | }, { 2244 | "Avatar of the Coin", 666, 2245 | Free, Basic, 0, Minion, 2246 | 0, 0, 1, 1, 2247 | nil, nil, nil, nil, nil, nil, nil, nil 2248 | }, { 2249 | "Backstab", 471, 2250 | Free, Basic, Rogue, Spell, 2251 | 0, 0, 0, 0, 2252 | nil, nil, nil, nil, nil, nil, nil, nil 2253 | }, { 2254 | "Blessing of Might", 394, 2255 | Free, Basic, Paladin, Spell, 2256 | 0, 1, 0, 0, 2257 | nil, nil, nil, nil, nil, nil, nil, nil 2258 | }, { 2259 | "Bloodfen Raptor", 576, 2260 | Free, Basic, 0, Minion, 2261 | Beast, 2, 3, 2, 2262 | nil, nil, nil, nil, nil, nil, nil, nil 2263 | }, { 2264 | "Boulderfist Ogre", 60, 2265 | Free, Basic, 0, Minion, 2266 | 0, 6, 6, 7, 2267 | nil, nil, nil, nil, nil, nil, nil, nil 2268 | }, { 2269 | "Charge", 646, 2270 | Free, Basic, Warrior, Spell, 2271 | 0, 0, 0, 0, 2272 | nil, nil, nil, nil, nil, nil, nil, nil 2273 | }, { 2274 | "Claw", 532, 2275 | Free, Basic, Druid, Spell, 2276 | 0, 1, 0, 0, 2277 | nil, nil, nil, nil, nil, nil, nil, nil 2278 | }, { 2279 | "Dagger Mastery", 201, 2280 | Free, Basic, Rogue, Hero_power, 2281 | 0, 2, 0, 0, 2282 | nil, nil, nil, nil, nil, nil, nil, nil 2283 | }, { 2284 | "Deadly Poison", 87, 2285 | Free, Basic, Rogue, Spell, 2286 | 0, 1, 0, 0, 2287 | nil, nil, nil, nil, nil, nil, nil, nil 2288 | }, { 2289 | "Drain Life", 332, 2290 | Free, Basic, Warlock, Spell, 2291 | 0, 3, 0, 0, 2292 | nil, nil, nil, nil, nil, nil, nil, nil 2293 | }, { 2294 | "Execute", 227, 2295 | Free, Basic, Warrior, Spell, 2296 | 0, 1, 0, 0, 2297 | nil, nil, nil, nil, nil, nil, nil, nil 2298 | }, { 2299 | "Fiery War Axe", 632, 2300 | Free, Basic, Warrior, Weapon, 2301 | 0, 2, 3, 2, 2302 | nil, nil, nil, nil, nil, nil, nil, nil 2303 | }, { 2304 | "Fireball", 522, 2305 | Free, Basic, Mage, Spell, 2306 | 0, 4, 0, 0, 2307 | nil, nil, nil, nil, nil, nil, nil, nil 2308 | }, { 2309 | "Fireblast", 677, 2310 | Free, Basic, Mage, Hero_power, 2311 | 0, 2, 0, 0, 2312 | nil, nil, nil, nil, nil, nil, nil, nil 2313 | }, { 2314 | "Frost Shock", 233, 2315 | Free, Basic, Shaman, Spell, 2316 | 0, 1, 0, 0, 2317 | nil, nil, nil, nil, nil, nil, nil, nil 2318 | }, { 2319 | "Garrosh Hellscream", 635, 2320 | Free, Basic, Warrior, Hero, 2321 | 0, 0, 0, 30, 2322 | nil, nil, nil, nil, nil, nil, nil, nil 2323 | }, { 2324 | "Gul'dan", 618, 2325 | Free, Basic, Warlock, Hero, 2326 | 0, 0, 0, 30, 2327 | nil, nil, nil, nil, nil, nil, nil, nil 2328 | }, { 2329 | "Hammer of Wrath", 350, 2330 | Free, Basic, Paladin, Spell, 2331 | 0, 4, 0, 0, 2332 | nil, nil, nil, nil, nil, nil, nil, nil 2333 | }, { 2334 | "Hand of Protection", 499, 2335 | Free, Basic, Paladin, Spell, 2336 | 0, 1, 0, 0, 2337 | nil, nil, nil, nil, nil, nil, nil, nil 2338 | }, { 2339 | "Healing Totem", 275, 2340 | Free, Basic, Shaman, Minion, 2341 | Totem, 1, 0, 2, 2342 | nil, nil, nil, nil, nil, nil, nil, nil 2343 | }, { 2344 | "Healing Touch", 258, 2345 | Free, Basic, Druid, Spell, 2346 | 0, 3, 0, 0, 2347 | nil, nil, nil, nil, nil, nil, nil, nil 2348 | }, { 2349 | "Hellfire", 122, 2350 | Free, Basic, Warlock, Spell, 2351 | 0, 4, 0, 0, 2352 | nil, nil, nil, nil, nil, nil, nil, nil 2353 | }, { 2354 | "Heroic Strike", 1, 2355 | Free, Basic, Warrior, Spell, 2356 | 0, 2, 0, 0, 2357 | nil, nil, nil, nil, nil, nil, nil, nil 2358 | }, { 2359 | "Hex", 270, 2360 | Free, Basic, Shaman, Spell, 2361 | 0, 3, 0, 0, 2362 | nil, nil, nil, nil, nil, nil, nil, nil 2363 | }, { 2364 | "Holy Light", 108, 2365 | Free, Basic, Paladin, Spell, 2366 | 0, 2, 0, 0, 2367 | nil, nil, nil, nil, nil, nil, nil, nil 2368 | }, { 2369 | "Holy Smite", 409, 2370 | Free, Basic, Priest, Spell, 2371 | 0, 1, 0, 0, 2372 | nil, nil, nil, nil, nil, nil, nil, nil 2373 | }, { 2374 | "Houndmaster", 225, 2375 | Free, Basic, Hunter, Minion, 2376 | 0, 4, 4, 3, 2377 | nil, nil, nil, nil, nil, nil, nil, nil 2378 | }, { 2379 | "Innervate", 548, 2380 | Free, Basic, Druid, Spell, 2381 | 0, 0, 0, 0, 2382 | nil, nil, nil, nil, nil, nil, nil, nil 2383 | }, { 2384 | "Jaina Proudmoore", 320, 2385 | Free, Basic, Mage, Hero, 2386 | 0, 0, 0, 30, 2387 | nil, nil, nil, nil, nil, nil, nil, nil 2388 | }, { 2389 | "Lesser Heal", 126, 2390 | Free, Basic, Priest, Hero_power, 2391 | 0, 2, 0, 0, 2392 | nil, nil, nil, nil, nil, nil, nil, nil 2393 | }, { 2394 | "Life Tap", 20, 2395 | Free, Basic, Warlock, Hero_power, 2396 | 0, 2, 0, 0, 2397 | nil, nil, nil, nil, nil, nil, nil, nil 2398 | }, { 2399 | "Light's Justice", 250, 2400 | Free, Basic, Paladin, Weapon, 2401 | 0, 1, 1, 4, 2402 | nil, nil, nil, nil, nil, nil, nil, nil 2403 | }, { 2404 | "Magma Rager", 362, 2405 | Free, Basic, 0, Minion, 2406 | 0, 3, 5, 1, 2407 | nil, nil, nil, nil, nil, nil, nil, nil 2408 | }, { 2409 | "Malfurion Stormrage", 621, 2410 | Free, Basic, Druid, Hero, 2411 | 0, 0, 0, 30, 2412 | nil, nil, nil, nil, nil, nil, nil, nil 2413 | }, { 2414 | "Mark of the Wild", 480, 2415 | Free, Basic, Druid, Spell, 2416 | 0, 2, 0, 0, 2417 | nil, nil, nil, nil, nil, nil, nil, nil 2418 | }, { 2419 | "Mind Blast", 415, 2420 | Free, Basic, Priest, Spell, 2421 | 0, 2, 0, 0, 2422 | nil, nil, nil, nil, nil, nil, nil, nil 2423 | }, { 2424 | "Multi-Shot", 407, 2425 | Free, Basic, Hunter, Spell, 2426 | 0, 4, 0, 0, 2427 | nil, nil, nil, nil, nil, nil, nil, nil 2428 | }, { 2429 | "Murloc Raider", 55, 2430 | Free, Basic, 0, Minion, 2431 | Murloc, 1, 2, 1, 2432 | nil, nil, nil, nil, nil, nil, nil, nil 2433 | }, { 2434 | "Nightblade", 184, 2435 | Free, Basic, 0, Minion, 2436 | 0, 5, 4, 4, 2437 | nil, nil, nil, nil, nil, nil, nil, nil 2438 | }, { 2439 | "Northshire Cleric", 600, 2440 | Free, Basic, Priest, Minion, 2441 | 0, 1, 1, 3, 2442 | nil, nil, nil, nil, nil, nil, nil, nil 2443 | }, { 2444 | "Novice Engineer", 435, 2445 | Free, Basic, 0, Minion, 2446 | 0, 2, 1, 2, 2447 | nil, nil, nil, nil, nil, nil, nil, nil 2448 | }, { 2449 | "Oasis Snapjaw", 15, 2450 | Free, Basic, 0, Minion, 2451 | Beast, 4, 2, 7, 2452 | nil, nil, nil, nil, nil, nil, nil, nil 2453 | }, { 2454 | "Polymorph", 595, 2455 | Free, Basic, Mage, Spell, 2456 | 0, 4, 0, 0, 2457 | nil, nil, nil, nil, nil, nil, nil, nil 2458 | }, { 2459 | "Power Word: Shield", 431, 2460 | Free, Basic, Priest, Spell, 2461 | 0, 1, 0, 0, 2462 | nil, nil, nil, nil, nil, nil, nil, nil 2463 | }, { 2464 | "Raid Leader", 502, 2465 | Free, Basic, 0, Minion, 2466 | 0, 3, 2, 2, 2467 | nil, nil, nil, nil, nil, nil, nil, nil 2468 | }, { 2469 | "Reckless Rocketeer", 560, 2470 | Free, Basic, 0, Minion, 2471 | 0, 6, 5, 2, 2472 | nil, nil, nil, nil, nil, nil, nil, nil 2473 | }, { 2474 | "Reinforce", 248, 2475 | Free, Basic, Paladin, Hero_power, 2476 | 0, 2, 0, 0, 2477 | nil, nil, nil, nil, nil, nil, nil, nil 2478 | }, { 2479 | "Rexxar", 484, 2480 | Free, Basic, Hunter, Hero, 2481 | 0, 0, 0, 30, 2482 | nil, nil, nil, nil, nil, nil, nil, nil 2483 | }, { 2484 | "River Crocolisk", 535, 2485 | Free, Basic, 0, Minion, 2486 | Beast, 2, 2, 3, 2487 | nil, nil, nil, nil, nil, nil, nil, nil 2488 | }, { 2489 | "Rockbiter Weapon", 491, 2490 | Free, Basic, Shaman, Spell, 2491 | 0, 1, 0, 0, 2492 | nil, nil, nil, nil, nil, nil, nil, nil 2493 | }, { 2494 | "Sap", 385, 2495 | Free, Basic, Rogue, Spell, 2496 | 0, 2, 0, 0, 2497 | nil, nil, nil, nil, nil, nil, nil, nil 2498 | }, { 2499 | "Searing Totem", 98, 2500 | Free, Basic, Shaman, Minion, 2501 | Totem, 1, 1, 1, 2502 | nil, nil, nil, nil, nil, nil, nil, nil 2503 | }, { 2504 | "Sen'jin Shieldmasta", 326, 2505 | Free, Basic, 0, Minion, 2506 | 0, 4, 3, 5, 2507 | nil, nil, nil, nil, nil, nil, nil, nil 2508 | }, { 2509 | "Shadow Bolt", 647, 2510 | Free, Basic, Warlock, Spell, 2511 | 0, 3, 0, 0, 2512 | nil, nil, nil, nil, nil, nil, nil, nil 2513 | }, { 2514 | "Shadow Word: Pain", 315, 2515 | Free, Basic, Priest, Spell, 2516 | 0, 2, 0, 0, 2517 | nil, nil, nil, nil, nil, nil, nil, nil 2518 | }, { 2519 | "Shapeshift", 185, 2520 | Free, Basic, Druid, Hero_power, 2521 | 0, 2, 0, 0, 2522 | nil, nil, nil, nil, nil, nil, nil, nil 2523 | }, { 2524 | "Silver Hand Recruit", 268, 2525 | Free, Basic, Paladin, Minion, 2526 | 0, 1, 1, 1, 2527 | nil, nil, nil, nil, nil, nil, nil, nil 2528 | }, { 2529 | "Sinister Strike", 205, 2530 | Free, Basic, Rogue, Spell, 2531 | 0, 1, 0, 0, 2532 | nil, nil, nil, nil, nil, nil, nil, nil 2533 | }, { 2534 | "Steady Shot", 481, 2535 | Free, Basic, Hunter, Hero_power, 2536 | 0, 2, 0, 0, 2537 | nil, nil, nil, nil, nil, nil, nil, nil 2538 | }, { 2539 | "Stoneclaw Totem", 298, 2540 | Free, Basic, Shaman, Minion, 2541 | Totem, 1, 0, 2, 2542 | nil, nil, nil, nil, nil, nil, nil, nil 2543 | }, { 2544 | "Stonetusk Boar", 76, 2545 | Free, Basic, 0, Minion, 2546 | Beast, 1, 1, 1, 2547 | nil, nil, nil, nil, nil, nil, nil, nil 2548 | }, { 2549 | "Succubus", 208, 2550 | Free, Basic, Warlock, Minion, 2551 | Demon, 2, 4, 3, 2552 | nil, nil, nil, nil, nil, nil, nil, nil 2553 | }, { 2554 | "Thrall", 319, 2555 | Free, Basic, Shaman, Hero, 2556 | 0, 0, 0, 30, 2557 | nil, nil, nil, nil, nil, nil, nil, nil 2558 | }, { 2559 | "Timber Wolf", 86, 2560 | Free, Basic, Hunter, Minion, 2561 | Beast, 1, 1, 1, 2562 | nil, nil, nil, nil, nil, nil, nil, nil 2563 | }, { 2564 | "Totemic Call", 316, 2565 | Free, Basic, Shaman, Hero_power, 2566 | 0, 2, 0, 0, 2567 | nil, nil, nil, nil, nil, nil, nil, nil 2568 | }, { 2569 | "Tracking", 163, 2570 | Free, Basic, Hunter, Spell, 2571 | 0, 1, 0, 0, 2572 | nil, nil, nil, nil, nil, nil, nil, nil 2573 | }, { 2574 | "Uther Lightbringer", 257, 2575 | Free, Basic, Paladin, Hero, 2576 | 0, 0, 0, 30, 2577 | nil, nil, nil, nil, nil, nil, nil, nil 2578 | }, { 2579 | "Valeera Sanguinar", 2, 2580 | Free, Basic, Rogue, Hero, 2581 | 0, 0, 0, 30, 2582 | nil, nil, nil, nil, nil, nil, nil, nil 2583 | }, { 2584 | "Voidwalker", 340, 2585 | Free, Basic, Warlock, Minion, 2586 | Demon, 1, 1, 3, 2587 | nil, nil, nil, nil, nil, nil, nil, nil 2588 | }, { 2589 | "Voodoo Doctor", 410, 2590 | Free, Basic, 0, Minion, 2591 | 0, 1, 2, 1, 2592 | nil, nil, nil, nil, nil, nil, nil, nil 2593 | }, { 2594 | "Warsong Commander", 193, 2595 | Free, Basic, Warrior, Minion, 2596 | 0, 3, 2, 3, 2597 | nil, nil, nil, nil, nil, nil, nil, nil 2598 | }, { 2599 | "Wicked Knife", 183, 2600 | Free, Basic, Rogue, Weapon, 2601 | 0, 1, 1, 2, 2602 | nil, nil, nil, nil, nil, nil, nil, nil 2603 | }, { 2604 | "Wild Growth", 282, 2605 | Free, Basic, Druid, Spell, 2606 | 0, 2, 0, 0, 2607 | nil, nil, nil, nil, nil, nil, nil, nil 2608 | }, { 2609 | "Windfury", 146, 2610 | Free, Basic, Shaman, Spell, 2611 | 0, 2, 0, 0, 2612 | nil, nil, nil, nil, nil, nil, nil, nil 2613 | }, { 2614 | "Wolfrider", 174, 2615 | Free, Basic, 0, Minion, 2616 | 0, 3, 3, 1, 2617 | nil, nil, nil, nil, nil, nil, nil, nil 2618 | }, { 2619 | "Wrath of Air Totem", 365, 2620 | Free, Basic, Shaman, Minion, 2621 | Totem, 1, 0, 2, 2622 | nil, nil, nil, nil, nil, nil, nil, nil 2623 | }}; -------------------------------------------------------------------------------- /card.h: -------------------------------------------------------------------------------- 1 | #ifndef _card_h 2 | #define _card_h 3 | 4 | #include 5 | #include "partial.h" 6 | 7 | #define nil (void *)0 8 | 9 | typedef enum { 10 | Legendary, 11 | Epic, 12 | Rare, 13 | Common, 14 | Free 15 | } Card_quality; 16 | 17 | typedef enum { 18 | None, 19 | Debug, 20 | Missions, 21 | Reward, 22 | Basic, 23 | Expert 24 | } Card_set; 25 | 26 | typedef enum { 27 | Neutral, 28 | Druid, 29 | Hunter, 30 | Mage, 31 | Paladin, 32 | Priest, 33 | Rogue, 34 | Shaman, 35 | Warlock, 36 | Warrior 37 | } Card_class; 38 | 39 | typedef enum { 40 | Hero, 41 | Minion, 42 | Weapon, 43 | Spell, 44 | Secret, 45 | Hero_power 46 | } Card_type; 47 | 48 | typedef enum { 49 | General, 50 | Beast, 51 | Demon, 52 | Dragon, 53 | Murloc, 54 | Pirate, 55 | Totem 56 | } Card_minion_type; 57 | 58 | typedef struct Card { 59 | const char *name; 60 | uint16_t id; 61 | uint8_t quality; 62 | uint8_t set; 63 | uint8_t class; 64 | uint8_t type; 65 | uint8_t minion_type; 66 | uint8_t cost; 67 | uint8_t attack; 68 | uint8_t health; 69 | void *on_attacked; 70 | void *on_damaged; 71 | void *on_healed; 72 | void *on_played; 73 | void *on_summoned; 74 | void *on_destroyed; 75 | void *on_turn_start; 76 | void *on_turn_end; 77 | } Card; 78 | 79 | Card cards[524]; 80 | 81 | #endif // _card_h 82 | -------------------------------------------------------------------------------- /inc/asmlib.h: -------------------------------------------------------------------------------- 1 | /*************************** asmlib.h *************************************** 2 | * Author: Agner Fog 3 | * Date created: 2003-12-12 4 | * Last modified: 2013-10-04 5 | * Project: asmlib.zip 6 | * Source URL: www.agner.org/optimize 7 | * 8 | * Description: 9 | * Header file for the asmlib function library. 10 | * This library is available in many versions for different platforms. 11 | * See asmlib-instructions.pdf for details. 12 | * 13 | * (c) Copyright 2003 - 2013 by Agner Fog. 14 | * GNU General Public License http://www.gnu.org/licenses/gpl.html 15 | *****************************************************************************/ 16 | 17 | 18 | #ifndef ASMLIB_H 19 | #define ASMLIB_H 20 | 21 | 22 | /*********************************************************************** 23 | Define compiler-specific types and directives 24 | ***********************************************************************/ 25 | 26 | // Define type size_t 27 | #ifndef _SIZE_T_DEFINED 28 | #include "stddef.h" 29 | #endif 30 | 31 | // Define integer types with known size: int32_t, uint32_t, int64_t, uint64_t. 32 | // If this doesn't work then insert compiler-specific definitions here: 33 | #if defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1600) 34 | // Compilers supporting C99 or C++0x have stdint.h defining these integer types 35 | #include 36 | #define INT64_SUPPORTED // Remove this if the compiler doesn't support 64-bit integers 37 | #elif defined(_MSC_VER) 38 | // Older Microsoft compilers have their own definition 39 | typedef signed __int16 int16_t; 40 | typedef unsigned __int16 uint16_t; 41 | typedef signed __int32 int32_t; 42 | typedef unsigned __int32 uint32_t; 43 | typedef signed __int64 int64_t; 44 | typedef unsigned __int64 uint64_t; 45 | #define INT64_SUPPORTED // Remove this if the compiler doesn't support 64-bit integers 46 | #else 47 | // This works with most compilers 48 | typedef signed short int int16_t; 49 | typedef unsigned short int uint16_t; 50 | typedef signed int int32_t; 51 | typedef unsigned int uint32_t; 52 | typedef long long int64_t; 53 | typedef unsigned long long uint64_t; 54 | #define INT64_SUPPORTED // Remove this if the compiler doesn't support 64-bit integers 55 | #endif 56 | 57 | 58 | // Turn off name mangling 59 | #ifdef __cplusplus 60 | extern "C" { 61 | #endif 62 | 63 | /*********************************************************************** 64 | Function prototypes, memory and string functions 65 | ***********************************************************************/ 66 | void * A_memcpy (void * dest, const void * src, size_t count); // Copy count bytes from src to dest 67 | void * A_memmove(void * dest, const void * src, size_t count); // Same as memcpy, allows overlap between src and dest 68 | void * A_memset (void * dest, int c, size_t count); // Set count bytes in dest to (char)c 69 | int A_memcmp (const void * buf1, const void * buf2, size_t num); // Compares two blocks of memory 70 | size_t GetMemcpyCacheLimit(void); // Data blocks bigger than this will be copied uncached by memcpy and memmove 71 | void SetMemcpyCacheLimit(size_t); // Change limit in GetMemcpyCacheLimit 72 | size_t GetMemsetCacheLimit(void); // Data blocks bigger than this will be stored uncached by memset 73 | void SetMemsetCacheLimit(size_t); // Change limit in GetMemsetCacheLimit 74 | char * A_strcat (char * dest, const char * src); // Concatenate strings dest and src. Store result in dest 75 | char * A_strcpy (char * dest, const char * src); // Copy string src to dest 76 | size_t A_strlen (const char * str); // Get length of zero-terminated string 77 | int A_strcmp (const char * a, const char * b); // Compare strings. Case sensitive 78 | int A_stricmp (const char *string1, const char *string2); // Compare strings. Case insensitive for A-Z only 79 | char * A_strstr (char * haystack, const char * needle); // Search for substring in string 80 | void A_strtolower(char * string); // Convert string to lower case for A-Z only 81 | void A_strtoupper(char * string); // Convert string to upper case for a-z only 82 | size_t A_substring(char * dest, const char * source, size_t pos, size_t len); // Copy a substring for source into dest 83 | size_t A_strspn (const char * str, const char * set); // Find span of characters that belong to set 84 | size_t A_strcspn(const char * str, const char * set); // Find span of characters that don't belong to set 85 | size_t strCountInSet(const char * str, const char * set); // Count characters that belong to set 86 | size_t strcount_UTF8(const char * str); // Counts the number of characters in a UTF-8 encoded string 87 | 88 | 89 | /*********************************************************************** 90 | Function prototypes, miscellaneous functions 91 | ***********************************************************************/ 92 | uint32_t A_popcount(uint32_t x); // Count 1-bits in 32-bit integer 93 | int RoundD (double x); // Round to nearest or even 94 | int RoundF (float x); // Round to nearest or even 95 | int InstructionSet(void); // Tell which instruction set is supported 96 | char * ProcessorName(void); // ASCIIZ text describing microprocessor 97 | void CpuType(int * vendor, int * family, int * model); // Get CPU vendor, family and model 98 | size_t DataCacheSize(int level); // Get size of data cache 99 | void A_DebugBreak(void); // Makes a debug breakpoint 100 | #ifdef INT64_SUPPORTED 101 | uint64_t ReadTSC(void); // Read microprocessor internal clock (64 bits) 102 | #else 103 | uint32_t ReadTSC(void); // Read microprocessor internal clock (only 32 bits supported by compiler) 104 | #endif 105 | void cpuid_ex (int abcd[4], int eax, int ecx); // call CPUID instruction 106 | static inline void cpuid_abcd (int abcd[4], int eax) { 107 | cpuid_ex(abcd, eax, 0);} 108 | 109 | #ifdef __cplusplus 110 | } // end of extern "C" 111 | 112 | // Define overloaded versions if compiling as C++ 113 | 114 | static inline int Round (double x) { // Overload name Round 115 | return RoundD(x);} 116 | static inline int Round (float x) { // Overload name Round 117 | return RoundF(x);} 118 | static inline const char * A_strstr(const char * haystack, const char * needle) { 119 | return A_strstr((char*)haystack, needle);} // Overload A_strstr with const char * version 120 | 121 | #endif // __cplusplus 122 | 123 | 124 | /*********************************************************************** 125 | Function prototypes, integer division functions 126 | ***********************************************************************/ 127 | 128 | // Turn off name mangling 129 | #ifdef __cplusplus 130 | extern "C" { 131 | #endif 132 | 133 | void setdivisori32(int buffer[2], int d); // Set divisor for repeated division 134 | int dividefixedi32(const int buffer[2], int x); // Fast division with previously set divisor 135 | void setdivisoru32(uint32_t buffer[2], uint32_t d); // Set divisor for repeated division 136 | uint32_t dividefixedu32(const uint32_t buffer[2], uint32_t x); // Fast division with previously set divisor 137 | 138 | // Test if emmintrin.h is included and __m128i defined 139 | #if defined(__GNUC__) && defined(_EMMINTRIN_H_INCLUDED) && !defined(__SSE2__) 140 | #error Please compile with -sse2 or higher 141 | #endif 142 | 143 | #if defined(_INCLUDED_EMM) || (defined(_EMMINTRIN_H_INCLUDED) && defined(__SSE2__)) 144 | #define VECTORDIVISIONDEFINED 145 | 146 | // Integer vector division functions. These functions divide an integer vector by a scalar: 147 | 148 | // Set divisor for repeated integer vector division 149 | void setdivisorV8i16(__m128i buf[2], int16_t d); // Set divisor for repeated division 150 | void setdivisorV8u16(__m128i buf[2], uint16_t d); // Set divisor for repeated division 151 | void setdivisorV4i32(__m128i buf[2], int32_t d); // Set divisor for repeated division 152 | void setdivisorV4u32(__m128i buf[2], uint32_t d); // Set divisor for repeated division 153 | 154 | // Fast division of vector by previously set divisor 155 | __m128i dividefixedV8i16(const __m128i buf[2], __m128i x); // Fast division with previously set divisor 156 | __m128i dividefixedV8u16(const __m128i buf[2], __m128i x); // Fast division with previously set divisor 157 | __m128i dividefixedV4i32(const __m128i buf[2], __m128i x); // Fast division with previously set divisor 158 | __m128i dividefixedV4u32(const __m128i buf[2], __m128i x); // Fast division with previously set divisor 159 | 160 | #endif // defined(_INCLUDED_EMM) || (defined(_EMMINTRIN_H_INCLUDED) && defined(__SSE2__)) 161 | 162 | #ifdef __cplusplus 163 | } // end of extern "C" 164 | #endif // __cplusplus 165 | 166 | #ifdef __cplusplus 167 | 168 | // Define classes and operator '/' for fast division with fixed divisor 169 | class div_i32; 170 | class div_u32; 171 | static inline int32_t operator / (int32_t x, div_i32 const &D); 172 | static inline uint32_t operator / (uint32_t x, div_u32 const & D); 173 | 174 | class div_i32 { // Signed 32 bit integer division 175 | public: 176 | div_i32() { // Default constructor 177 | buffer[0] = buffer[1] = 0; 178 | } 179 | div_i32(int d) { // Constructor with divisor 180 | setdivisor(d); 181 | } 182 | void setdivisor(int d) { // Set divisor 183 | setdivisori32(buffer, d); 184 | } 185 | protected: 186 | int buffer[2]; // Internal memory 187 | friend int32_t operator / (int32_t x, div_i32 const & D); 188 | }; 189 | 190 | static inline int32_t operator / (int32_t x, div_i32 const &D){// Overloaded operator '/' 191 | return dividefixedi32(D.buffer, x); 192 | } 193 | 194 | static inline int32_t operator /= (int32_t &x, div_i32 const &D){// Overloaded operator '/=' 195 | return x = x / D; 196 | } 197 | 198 | class div_u32 { // Unsigned 32 bit integer division 199 | public: 200 | div_u32() { // Default constructor 201 | buffer[0] = buffer[1] = 0; 202 | } 203 | div_u32(uint32_t d) { // Constructor with divisor 204 | setdivisor(d); 205 | } 206 | void setdivisor(uint32_t d) { // Set divisor 207 | setdivisoru32(buffer, d); 208 | } 209 | protected: 210 | uint32_t buffer[2]; // Internal memory 211 | friend uint32_t operator / (uint32_t x, div_u32 const & D); 212 | }; 213 | 214 | static inline uint32_t operator / (uint32_t x, div_u32 const & D){ // Overloaded operator '/' 215 | return dividefixedu32(D.buffer, x); 216 | } 217 | 218 | static inline uint32_t operator /= (uint32_t &x, div_u32 const &D){// Overloaded operator '/=' 219 | return x = x / D; 220 | } 221 | 222 | #endif // __cplusplus 223 | 224 | #endif // ASMLIB_H 225 | -------------------------------------------------------------------------------- /inc/asmlibran.h: -------------------------------------------------------------------------------- 1 | /***************************** randoma.h ********************************** 2 | * Author: Agner Fog 3 | * Date created: 1997 4 | * Last modified: 2013-09-20 5 | * Project: randoma 6 | * Source URL: www.agner.org/random 7 | * 8 | * Description: 9 | * This header file contains function prototypes and class declarations for 10 | * the randoma library of uniform random number generators optimized in 11 | * assembly language. 12 | * 13 | * The following random number generators are available: 14 | * Mersenne Twister, Mother-Of-All generator and SFMT generator. 15 | * 16 | * This library is available in many versions for different platforms, 17 | * see ran-instructions.pdf for details. 18 | * 19 | * Copyright 1997-2013 by Agner Fog. 20 | * GNU General Public License http://www.gnu.org/licenses/gpl.html 21 | ******************************************************************************* 22 | 23 | 24 | Description of random number generator functions: 25 | ================================================= 26 | 27 | Single-threaded versions: 28 | ------------------------- 29 | void MersenneRandomInit(int seed); 30 | void MotherRandomInit(int seed); 31 | void SFMTgenRandomInit(int seed, int IncludeMother); 32 | This function must be called before any random number is generated. 33 | Different values for seed will generate different random number sequences. 34 | SFMTgenRandomInit will make a combination of the SFMT generator and the 35 | Mother-Of-All generator if IncludeMother = 1 or an SFMT generator alone if 36 | IncludeMother = 0. 37 | 38 | void MersenneRandomInitByArray(int const seeds[], int NumSeeds); 39 | void SFMTgenRandomInitByArray (int const seeds[], int NumSeeds, int IncludeMother); 40 | Alternative to MersenneRandomInit when the seed consists of more than one integer. 41 | 42 | int MersenneIRandom (int min, int max); 43 | int MotherIRandom (int min, int max); 44 | int SFMTgenIRandom (int min, int max); 45 | Generates a random integer in the interval from min to max, inclusive. 46 | 47 | int MersenneIRandomX(int min, int max); 48 | int SFMTgenIRandomX (int min, int max); 49 | Same as above. All possible output values have exactly the same probability 50 | in the IRandomX versions, whereas the IRandom versions may have a slight 51 | bias when the interval length is very high and not a power of 2. 52 | 53 | double MersenneRandom(); 54 | double MotherRandom(); 55 | double SFMTgenRandom(); 56 | long double SFMTgenRandomL(); 57 | Generates a random number x in the interval 0 <= x < 1 with uniform distribution. 58 | The resolution is 2^(-32) for MersenneRandom() and MotherRandom(), 59 | 2^(-52) for SFMTgenRandom() and 2^(-63) for SFMTgenRandomL(). 60 | (SFMTgenRandomL() requires that the compiler supports long double precision). 61 | 62 | uint32_t MersenneBRandom(); 63 | uint32_t MotherBRandom(); 64 | uint32_t SFMTgenBRandom(); 65 | Generates a random 32-bit number. All 32 bits are random. 66 | 67 | 68 | DLL versions: 69 | ------------- 70 | These functions use the __stdcall calling convention rather than __cdecl. 71 | They are intended for use with randomad32.dll or randomad64.dll for 72 | programming languages that do not support static linking. The function 73 | names are the same as above with a D appended to the name. 74 | 75 | 76 | Thread-safe versions: 77 | --------------------- 78 | These functions are wrapped in the classes CRandomMersenneA, CRandomMotherA 79 | and CRandomSFMTA. Use these for multi-threaded applications or when an 80 | object-oriented design is desired. There is no performance penalty for 81 | using these classes. Each thread should have its own instance of the 82 | random number generator class to prevent interaction between the threads. 83 | Make sure each instance has a different seed. 84 | 85 | *******************************************************************************/ 86 | 87 | #ifndef ASMLIBRAN_H 88 | #define ASMLIBRAN_H 89 | 90 | #include "asmlib.h" 91 | 92 | /*********************************************************************** 93 | System-specific definitions 94 | ***********************************************************************/ 95 | 96 | // Define macro for extern "C" __stdcall call for dynamic linking: 97 | #if defined(_WIN32) && !defined(_WIN64) 98 | // __stdcall used only in 32-bit Windows 99 | #define DLL_STDCALL __stdcall 100 | #else 101 | // 64-bit Windows has only one calling convention. 102 | // 32 and 64 bit Unix does not use __stdcall for dynamic linking 103 | #define DLL_STDCALL 104 | #endif 105 | 106 | 107 | /*********************************************************************** 108 | Define size of state vector 109 | ***********************************************************************/ 110 | 111 | // Must match the value used in the library source (randomah.asi) 112 | #define SFMT_N_A 88 113 | 114 | #define MERS_N_A 624 115 | 116 | // Turn off name mangling 117 | #ifdef __cplusplus 118 | extern "C" { 119 | #endif 120 | 121 | /*********************************************************************** 122 | Function prototypes for random number generators 123 | ***********************************************************************/ 124 | 125 | /*********************************************************************** 126 | Define function for Physical random number generator 127 | ***********************************************************************/ 128 | 129 | int PhysicalSeed(int seeds[], int NumSeeds); // Physical random seed generator. Not deterministic 130 | int DLL_STDCALL PhysicalSeedD(int seeds[], int NumSeeds); // Windows DLL version 131 | 132 | 133 | /*********************************************************************** 134 | Define functions for Mersenne Twister 135 | Thread-safe, single-threaded and Windows DLL versions 136 | ***********************************************************************/ 137 | 138 | // Single-threaded static link versions for Mersenne Twister 139 | void MersenneRandomInit(int seed); // Re-seed 140 | void MersenneRandomInitByArray(int const seeds[], int NumSeeds);// Seed by more than 32 bits 141 | int MersenneIRandom (int min, int max); // Output random integer 142 | int MersenneIRandomX(int min, int max); // Output random integer, exact 143 | double MersenneRandom(void); // Output random float 144 | uint32_t MersenneBRandom(void); // Output random bits 145 | 146 | // Single-threaded dynamic link versions for Mersenne Twister 147 | void DLL_STDCALL MersenneRandomInitD(int seed); // Re-seed 148 | void DLL_STDCALL MersenneRandomInitByArrayD(int const seeds[], int NumSeeds); // Seed by more than 32 bits 149 | int DLL_STDCALL MersenneIRandomD (int min, int max); // Output random integer 150 | int DLL_STDCALL MersenneIRandomXD(int min, int max); // Output random integer, exact 151 | double DLL_STDCALL MersenneRandomD(void); // Output random float 152 | uint32_t DLL_STDCALL MersenneBRandomD(void); // Output random bits 153 | 154 | // Thread-safe library functions for Mersenne Twister. 155 | // The thread-safe versions have as the first parameter a pointer to a 156 | // private memory buffer. These functions are intended to be called from 157 | // the class CRandomMersenneA defined below. 158 | // If calling from C rather than C++ then supply a private memory buffer 159 | // as Pthis. The necessary size of the buffer is given in the class 160 | // definition below. 161 | #define MERS_BUFFERSIZE (208+MERS_N_A*4) // Size of internal buffer 162 | 163 | void MersRandomInit(void * Pthis, int seed); // Re-seed 164 | void MersRandomInitByArray(void * Pthis, int const seeds[], int NumSeeds); // Seed by more than 32 bits 165 | int MersIRandom (void * Pthis, int min, int max); // Output random integer 166 | int MersIRandomX(void * Pthis, int min, int max); // Output random integer, exact 167 | double MersRandom (void * Pthis); // Output random float 168 | uint32_t MersBRandom (void * Pthis); // Output random bits 169 | 170 | 171 | /*********************************************************************** 172 | Define functions for Mother-of-all generator 173 | Thread-safe, single-threaded and Windows DLL versions 174 | ***********************************************************************/ 175 | // Single-threaded static link versions for Mother-of-all 176 | void MotherRandomInit(int seed); // Re-seed 177 | int MotherIRandom (int min, int max); // Output random integer 178 | double MotherRandom(void); // Output random float 179 | uint32_t MotherBRandom(void); // Output random bits 180 | 181 | // Single-threaded dynamic link versions for Mother-of-all 182 | void DLL_STDCALL MotherRandomInitD(int seed); // Re-seed 183 | int DLL_STDCALL MotherIRandomD (int min, int max); // Output random integer 184 | double DLL_STDCALL MotherRandomD(void); // Output random float 185 | uint32_t DLL_STDCALL MotherBRandomD(void); // Output random bits 186 | 187 | // Thread-safe library functions for Mother-of-all 188 | // The thread-safe versions have as the first parameter a pointer to a 189 | // private memory buffer. These functions are intended to be called from 190 | // the class CRandomMotherA defined below. 191 | // If calling from C rather than C++ then supply a private memory buffer 192 | // as Pthis. The necessary size of the buffer is given in the class 193 | // definition below. 194 | #define MOTHER_BUFFERSIZE 80 // Size of internal buffer 195 | 196 | void MotRandomInit(void * Pthis, int seed); // Initialization 197 | int MotIRandom(void * Pthis, int min, int max); // Get integer random number in desired interval 198 | double MotRandom (void * Pthis); // Get floating point random number 199 | uint32_t MotBRandom(void * Pthis); // Output random bits 200 | 201 | 202 | /*********************************************************************** 203 | Define functions for SFMT generator. 204 | Thread-safe, single-threaded and Windows DLL versions 205 | ***********************************************************************/ 206 | 207 | // Single-threaded static link versions for SFMT 208 | void SFMTgenRandomInit(int seed, int IncludeMother); // Re-seed 209 | void SFMTgenRandomInitByArray(int const seeds[], int NumSeeds, int IncludeMother); // Seed by more than 32 bits 210 | int SFMTgenIRandom (int min, int max); // Output random integer 211 | int SFMTgenIRandomX(int min, int max); // Output random integer, exact 212 | double SFMTgenRandom(void); // Output random floating point number, double presision 213 | long double SFMTgenRandomL(void); // Output random floating point number, long double presision 214 | uint32_t SFMTgenBRandom(void); // Output random bits 215 | 216 | // Single-threaded dynamic link versions for SFMT 217 | void DLL_STDCALL SFMTgenRandomInitD(int seed, int IncludeMother);// Re-seed 218 | void DLL_STDCALL SFMTgenRandomInitByArrayD(int const seeds[], int NumSeeds, int IncludeMother); // Seed by more than 32 bits 219 | int DLL_STDCALL SFMTgenIRandomD (int min, int max); // Output random integer 220 | int DLL_STDCALL SFMTgenIRandomXD(int min, int max); // Output random integer, exact 221 | double DLL_STDCALL SFMTgenRandomD(void); // Output random float 222 | uint32_t DLL_STDCALL SFMTgenBRandomD(void); // Output random bits 223 | 224 | // Thread-safe library functions for SFMT 225 | // The thread-safe versions have as the first parameter a pointer to a 226 | // private memory buffer. These functions are intended to be called from 227 | // the class CRandomSFMTA defined below. 228 | // If calling from C rather than C++ then supply a private memory buffer 229 | // as Pthis. The necessary size of the buffer is given in the class 230 | // definition below. 231 | #define SFMT_BUFFERSIZE (128+SFMT_N_A*16) // Size of internal buffer 232 | 233 | void SFMTRandomInit(void * Pthis, int ThisSize, int seed, int IncludeMother); // Re-seed 234 | void SFMTRandomInitByArray(void * Pthis, int ThisSize, int const seeds[], int NumSeeds, int IncludeMother); // Seed by more than 32 bits 235 | int SFMTIRandom (void * Pthis, int min, int max); // Output random integer 236 | int SFMTIRandomX(void * Pthis, int min, int max); // Output random integer, exact 237 | double SFMTRandom (void * Pthis); // Output random floating point number, double presision 238 | long double SFMTRandomL (void * Pthis); // Output random floating point number, long double precision 239 | uint32_t SFMTBRandom (void * Pthis); // Output random bits 240 | 241 | 242 | /*********************************************************************** 243 | Miscellaneous utility functions 244 | ***********************************************************************/ 245 | int PhysicalSeed(int seeds[], int NumSeeds); // Seed from physical random number generator on VIA processor 246 | 247 | uint64_t ReadTSC (void); // Read internal CPU clock counter (useful as seed) 248 | 249 | int InstructionSet (void); // Find supported instruction set (used internally) 250 | 251 | 252 | #ifdef __cplusplus 253 | } // end of extern "C" 254 | #endif 255 | 256 | /*********************************************************************** 257 | Define classes for thread-safe versions of random number generators 258 | ***********************************************************************/ 259 | #ifdef __cplusplus 260 | 261 | 262 | // Class for Mersenne Twister 263 | class CRandomMersenneA { // Encapsulate random number generator 264 | public: 265 | CRandomMersenneA(int seed) { // Constructor 266 | RandomInit(seed);} 267 | void RandomInit(int seed) { // Re-seed 268 | MersRandomInit(this, seed);} 269 | void RandomInitByArray(int const seeds[], int NumSeeds) {// Seed by more than 32 bits 270 | MersRandomInitByArray(this, seeds, NumSeeds);} 271 | int IRandom (int min, int max) { // Output random integer 272 | return MersIRandom(this, min, max);} 273 | int IRandomX(int min, int max) { // Output random integer, exact 274 | return MersIRandomX(this, min, max);} 275 | double Random() { // Output random float 276 | return MersRandom(this);} 277 | uint32_t BRandom() { // Output random bits 278 | return MersBRandom(this);} 279 | private: 280 | char internals[MERS_BUFFERSIZE]; // Internal variables 281 | }; 282 | 283 | 284 | // Class for Mother-of-all 285 | class CRandomMotherA { // Encapsulate random number generator 286 | public: 287 | CRandomMotherA(int seed) { // Constructor 288 | RandomInit(seed);} 289 | void RandomInit(int seed) { // Initialization 290 | MotRandomInit(this, seed);} 291 | int IRandom(int min, int max) { // Get integer random number in desired interval 292 | return MotIRandom(this, min, max);} 293 | double Random() { // Get floating point random number 294 | return MotRandom(this);} 295 | uint32_t BRandom() { // Output random bits 296 | return MotBRandom(this);} 297 | private: 298 | char internals[MOTHER_BUFFERSIZE]; // Internal variables 299 | }; 300 | 301 | 302 | // Class for SFMT generator with or without Mother-Of-All generator 303 | class CRandomSFMTA { // Encapsulate random number generator 304 | public: 305 | CRandomSFMTA(int seed, int IncludeMother = 0) { // Constructor 306 | RandomInit(seed, IncludeMother);} 307 | void RandomInit(int seed, int IncludeMother = 0) { // Re-seed 308 | SFMTRandomInit(this, sizeof(*this), seed, IncludeMother);} 309 | void RandomInitByArray(int const seeds[], int NumSeeds, int IncludeMother = 0) {// Seed by more than 32 bits 310 | SFMTRandomInitByArray(this, sizeof(*this), seeds, NumSeeds, IncludeMother);} 311 | int IRandom (int min, int max) { // Output random integer 312 | return SFMTIRandom(this, min, max);} 313 | int IRandomX(int min, int max) { // Output random integer, exact 314 | return SFMTIRandomX(this, min, max);} 315 | double Random() { // Output random float 316 | return SFMTRandom(this);} 317 | long double RandomL() { // Output random float 318 | return SFMTRandomL(this);} 319 | uint32_t BRandom() { // Output random bits 320 | return SFMTBRandom(this);} 321 | private: 322 | char internals[SFMT_BUFFERSIZE]; // Internal variables 323 | }; 324 | 325 | 326 | // Class for SFMT generator without Mother-Of-All generator 327 | // Derived from CRandomSFMTA 328 | class CRandomSFMTA0 : public CRandomSFMTA { 329 | public: 330 | CRandomSFMTA0(int seed) : CRandomSFMTA(seed,0) {} 331 | }; 332 | 333 | 334 | // Class for SFMT generator combined with Mother-Of-All generator 335 | // Derived from CRandomSFMTA 336 | class CRandomSFMTA1 : public CRandomSFMTA { 337 | public: 338 | CRandomSFMTA1(int seed) : CRandomSFMTA(seed,1) {} 339 | }; 340 | 341 | 342 | #endif // __cplusplus 343 | 344 | #endif // ASMLIBRAN_H 345 | -------------------------------------------------------------------------------- /lib/asmlib.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robert-nix/soot/5d91bdd20b8c98b952df28d2032a55987cd5bd70/lib/asmlib.zip -------------------------------------------------------------------------------- /lib/libacof64o.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robert-nix/soot/5d91bdd20b8c98b952df28d2032a55987cd5bd70/lib/libacof64o.lib -------------------------------------------------------------------------------- /partial.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "support.h" 3 | #include "partial.h" 4 | 5 | Partial_pool *partial_pool_new(void) { 6 | Partial_pool *p = (Partial_pool *)get_page(0); 7 | p->pool_end_address = (uintptr_t)p + get_page_size(); 8 | return p; 9 | } 10 | 11 | Partial *partial_new(Partial_pool *pool, Applicee *f) { 12 | Partial *p = (Partial *)((uintptr_t)pool + 16); 13 | while (p->ref_count != 0) { 14 | p += sizeof(Partial); 15 | if ((uintptr_t)p >= pool->pool_end_address) { 16 | pool->pool_end_address = 17 | get_page_size() + get_page(pool->pool_end_address); 18 | } 19 | } 20 | p->ref_count = 1; 21 | p->f = f; 22 | return (Partial *)((intptr_t)p | Partial_function); 23 | } 24 | 25 | void partial_bind_value(Partial *p, int arg, intptr_t value) { 26 | p = (Partial *)((uintptr_t)p & -8); 27 | p->args[arg - 1] = (void *)((value << 3) | Value); 28 | } 29 | 30 | void partial_bind_partial(Partial *p, int arg, Partial *partial) { 31 | p = (Partial *)((uintptr_t)p & -8); 32 | p->args[arg - 1] = partial; 33 | } 34 | 35 | void *partial_apply(Partial *p, void *state) { 36 | // If the pointer is a function, there are no arguments: 37 | if (((uintptr_t)p & 7) == Function) { 38 | return ((Applicee *)p)(state, 0, 0, 0); 39 | } 40 | 41 | p = (Partial *)((uintptr_t)p & -8); 42 | 43 | // state may only be a Partial * or null: 44 | if (p->state) { 45 | state = partial_apply(p->state, state); 46 | } 47 | 48 | intptr_t arg0p = (intptr_t)p->args[0]; 49 | void *arg0r = 0; 50 | if (arg0p != 0) { 51 | if ((arg0p & 7) == Value) { 52 | arg0r = (void *)(arg0p >> 3); 53 | } else { 54 | arg0r = partial_apply((Partial *)arg0p, state); 55 | } 56 | } 57 | 58 | intptr_t arg1p = (intptr_t)p->args[1]; 59 | void *arg1r = 0; 60 | if (arg1p != 0) { 61 | if ((arg1p & 7) == Value) { 62 | arg1r = (void *)(arg1p >> 3); 63 | } else { 64 | arg1r = partial_apply((Partial *)arg1p, state); 65 | } 66 | } 67 | 68 | intptr_t arg2p = (intptr_t)p->args[2]; 69 | void *arg2r = 0; 70 | if (arg2p != 0) { 71 | if ((arg2p & 7) == Value) { 72 | arg2r = (void *)(arg2p >> 3); 73 | } else { 74 | arg2r = partial_apply((Partial *)arg2p, state); 75 | } 76 | } 77 | 78 | return p->f(state, arg0r, arg1r, arg2r); 79 | } 80 | 81 | void partial_combine(Partial *p, Partial *c) { 82 | if (((uintptr_t)p & 7) == 0) { 83 | print_s("Tried to call partial_combine with a plain function.\n"); 84 | A_DebugBreak(); 85 | return; 86 | } 87 | p = (Partial *)((uintptr_t)p & -8); 88 | 89 | if (p->state) { 90 | partial_combine(c, p->state); 91 | } 92 | p->state = c; 93 | } 94 | 95 | void partial_inc_ref(Partial *p) { 96 | p = (Partial *)((uintptr_t)p & -8); 97 | p->ref_count++; 98 | } 99 | 100 | void partial_dec_ref(Partial *p) { 101 | p = (Partial *)((uintptr_t)p & -8); 102 | p->ref_count--; 103 | } 104 | 105 | uint64_t partial_test(uint64_t s, uint64_t arg0, uint64_t arg1, uint64_t arg2) { 106 | uint64_t result = 0; 107 | result += s; 108 | result *= arg0; 109 | result += arg1; 110 | result *= arg2; 111 | return result; 112 | } 113 | -------------------------------------------------------------------------------- /partial.h: -------------------------------------------------------------------------------- 1 | #ifndef _partial_h 2 | #define _partial_h 3 | 4 | // idea: give_card(s, count(filter_all(s,...))) partially applied without the s 5 | // args. we refer to this function with a pointer to the data structure and 3 6 | // bits saying that the pointer is a partial, not an actual function 7 | 8 | typedef void *(Applicee)(void *, void *, void *, void *); 9 | 10 | typedef enum { 11 | Function, 12 | Partial_function, 13 | Value 14 | } Pointer_type; // 3 bits 15 | 16 | typedef struct { 17 | uint64_t ref_count; 18 | Applicee *f; 19 | void *state; 20 | void *args[3]; 21 | } Partial; // 48 bytes 22 | 23 | typedef struct { 24 | uintptr_t pool_end_address; 25 | } Partial_pool; 26 | 27 | Partial_pool *partial_pool_new(void); 28 | 29 | // Although Partials are ideologically immutable, their creation is described 30 | // using multiple mutating functions to better describe the Partial itself. 31 | // --- 32 | // Creates a new partial within the provided pool. The returned pointer has 33 | // lower bits set to denote it as a partial. f should be a plain function 34 | // pointer to a function of exactly 4 arguments. 35 | Partial *partial_new(Partial_pool *pool, Applicee *f); 36 | 37 | // Binds a value in the provided partial at the provided argument index. When 38 | // called, the partial will supply the underlying function with this argument. 39 | void partial_bind_value(Partial *p, int arg, intptr_t value); 40 | 41 | // Binds a partial in the provided partial at the provided argument index. When 42 | // called, the partial will supply the underlying function's argument at this 43 | // index with the result of applying this partial. 44 | void partial_bind_partial(Partial *p, int arg, Partial *partial); 45 | 46 | // Applies the partial with the given state pointer. It's worth noting, in the 47 | // simulation, state is totally mutable (state is copied at branching points) 48 | // and the return value doesn't matter, but it wouldn't feel right without it. 49 | void *partial_apply(Partial *p, void *state); 50 | 51 | // Given the current partial p and another partial c, combine_partial makes it 52 | // so that when p is applied, c will first be applied to find the resulting 53 | // state which will then be provided to p. 54 | // e.g.: 55 | // combine_partial(p, c) := p(s, ...) => p(c(s, ...), ...) 56 | // also := p(c1(s, ...), ...) => p(c(c1(s, ...), ...), ...) 57 | void partial_combine(Partial *p, Partial *c); 58 | 59 | // Reference counting 60 | void partial_inc_ref(Partial *p); 61 | void partial_dec_ref(Partial *p); 62 | 63 | uint64_t partial_test(uint64_t, uint64_t, uint64_t, uint64_t); 64 | 65 | #endif // _partial_h 66 | -------------------------------------------------------------------------------- /project.clj: -------------------------------------------------------------------------------- 1 | (defproject soot "unversioned" 2 | :description "hearthstone clojure hearthstone" 3 | :url "https://github.com/Mischanix/soot" 4 | :dependencies [[org.clojure/clojure "1.5.1"] 5 | [org.clojure/math.combinatorics "0.0.7"] 6 | [criterium "0.4.2"]]) 7 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # c 2 | 3 | only build on windows x64 c99 gcc (i use tdm-gcc); could be rewritten for not 4 | windows / not 64-bit, but meh 5 | 6 | oh yeah, -nostdlib #yolo 7 | 8 | # clojure 9 | 10 | - tray contains mana crystals (current/max "spent+unspent") 11 | - hero character has health, armor, hero power, weapon? 12 | - hand contains cards, limit of 10 (new cards destroyed) 13 | - board contains minions, limit of 7 per side (new minions destroyed) 14 | - deck contains undrawn cards, starts at 30; at 0, fatigue kicks in, damaging 15 | the player (1 2 3 4 5 ... damage) on any attempted draw 16 | 17 | minions contain: 18 | - Name, Cost, Attack, Current Health, Maximum Health 19 | - Type (Beast, Demon, Dragon, Murloc, Pirate, Totem, General) 20 | - Properties (Taunt, Windfury, Charge, Stealth, Divine Shield) 21 | - Effects (event-based e.g. Battlecry, Deathrattle, Enrage, EoT/BoT) 22 | - External buffs (e.g. Spell Damage) 23 | 24 | words in fn names: 25 | 26 | - my: refers to the current controller in the game state or to the controller of 27 | the minion for which an action is being performed 28 | - opponent: the opposite of 'my' 29 | 30 | functions: 31 | 32 | - game state is always first arg 33 | - functions that don't return a game state are normally called directly, whereas 34 | functions that do return a game state are generally partially applied 35 | - filters are common 36 | - values/functions interchangeable (call the function against the current game 37 | state to get the current value) 38 | 39 | card states: 40 | - :undrawn 41 | - :drawn 42 | - :played 43 | - :dead 44 | 45 | card types: 46 | - :weapon 47 | - :character (includes :hero, :minion) 48 | - :hero 49 | - :minion 50 | - :spell 51 | - :hero-power 52 | 53 | tempted to remove `-target` from loads of function names, need to double check 54 | "normativity" of that though 55 | 56 | might replace 'opponent' with 'enemy' 57 | 58 | lots of todos in cards: saving them for when I have a complete picture of the 59 | structure of the game state 60 | 61 | in give- and in :aura, :health is assumed to buff :max-health as well (as 62 | otherwise it'd be a restore) 63 | 64 | a target is damaged if it is below its original health? test with warrior... 65 | 66 | really need to distinguish spell damage buffed abilities. arcane missiles needs 67 | a way to send more missiles by spell damage, too, (same with avenging wrath 68 | etc.) 69 | 70 | redo it in C once we find out that the JVM won't do it for us. 71 | 72 | ## function notes 73 | 74 | ### targeting 75 | 76 | - `(target filter expr)`; filter may be a single or a coll of keywords and/or 77 | functions. functions are applied with the contextual target as the sole 78 | argument and should return a boolean (true include/false exclude). colls are 79 | combined using logical and. when filtering cards, cards are filtered for :state 80 | :played and :character unless an overriding keyword is provided. an empty 81 | vector allows the default filtering. this behavior belongs to filter-all. expr 82 | functions are applied with the state as the sole argument, and this state 83 | contains the target as a part of its context. often for target, colls are used 84 | for single keywords just cause it looks nicer. 85 | 86 | - `(target-random)`; while (target ...) will require input from the user if more 87 | than one viable target is found, (target-random ...) will choose randomly from 88 | viable targets. if a number is supplied to the filter coll for target-random, 89 | that number of ''unique'' targets will be chosen. a second expr may be supplied 90 | 91 | `(target-random filter expr fallback)` that is called for the times where a 92 | viable target does not exist. 93 | 94 | - `(target-all)`; (target-all ...) applies expr to every viable target, not just 95 | one. 96 | 97 | ### choose one 98 | 99 | - `(choose one two)`; requires input to choose between two possible spells. 100 | spells can be numbers or strings referring to ids or names of the spell to cast 101 | 102 | ### combo 103 | 104 | - `(combo normal-expr combo-expr)`; wrapper for rogue combo spells. combo on 105 | minions is an optional battlecry, but on spells the spell effect branches based 106 | on combo state, so it's sometimes helpful to describe it as a branch instead of 107 | as a property of the card (although :combo can be used on spells as well) 108 | 109 | ### verbs on cards 110 | 111 | - draw-: undrawn -> drawn 112 | - summon-: (undrawn, drawn, nil) -> played; summon- is often called with a 113 | string, number, or collection of strings/numbers, in which case cards are 114 | created before being summoned. 115 | - play-: drawn -> played 116 | - return-: played -> drawn 117 | -------------------------------------------------------------------------------- /soot.c: -------------------------------------------------------------------------------- 1 | #include "support.h" 2 | #include "state.h" 3 | #include "card.h" 4 | #include "partial.h" 5 | 6 | #include 7 | #include 8 | 9 | void _main(void); 10 | void _main(void) { 11 | init_large_pages(); 12 | 13 | Partial_pool *pool = partial_pool_new(); 14 | Partial *p = partial_new(pool, (Applicee *)partial_test); 15 | partial_bind_value(p, 1, 2); // * 2 16 | partial_bind_value(p, 2, -15); // + -15 17 | partial_bind_value(p, 3, 4); // * 4 18 | print_s("pointer="); print_p((intptr_t)p); print_s("\n"); 19 | uint64_t stuff = (uint64_t)partial_apply(p, (void *)10); 20 | print_s("stuff="); print_p(stuff); print_s("\n"); 21 | 22 | print_s("sizeof(State)="); print_p(sizeof(State)); print_s(", "); 23 | print_s("sizeof(Thing)="); print_p(sizeof(Thing)); print_s(", "); 24 | print_s("sizeof(Card)="); print_p(sizeof(Card)); print_s(", "); 25 | print_s("sizeof(Partial)="); print_p(sizeof(Partial)); print_s("\n"); 26 | print_s("page_size="); print_p(get_page_size()); print_s("\n"); 27 | SFMTgenRandomInit(0x752, 0); 28 | print_p((intptr_t)SFMTgenIRandom(0, 0x100000)); print_s("\n"); 29 | print_p((intptr_t)SFMTgenIRandom(0, 0x100000)); print_s("\n"); 30 | print_p((intptr_t)SFMTgenIRandom(0, 0x100000)); print_s("\n"); 31 | print_p((intptr_t)SFMTgenIRandom(0, 0x100000)); print_s("\n"); 32 | print_p((intptr_t)SFMTgenIRandom(0, 0x100000)); print_s("\n"); 33 | print_p((intptr_t)SFMTgenIRandom(0, 0x100000)); print_s("\n"); 34 | print_p((intptr_t)SFMTgenIRandom(0, 0x100000)); print_s("\n"); 35 | ExitProcess(0); 36 | } 37 | -------------------------------------------------------------------------------- /src/soot/game.clj: -------------------------------------------------------------------------------- 1 | ; game.clj - let's get to a debuggable point; set up a valid game and play it 2 | ; randomly. 3 | (ns soot.game 4 | (:require [clojure.set :as set] 5 | [clojure.math.combinatorics :as combo] 6 | [clojure.pprint :refer [pprint]])) 7 | 8 | (defn without 9 | [coll n] 10 | (concat (take n coll) (nthrest coll (inc n)))) 11 | 12 | ; mockup of the ai primitive 13 | (defn choose 14 | "Branches between the supplied functions on state" 15 | [s fns labels] 16 | (if (first fns) 17 | (let [choice (rand-int (dec (count fns))) 18 | ; _ (pprint s) 19 | ; _ (pprint fns) 20 | ; _ (pprint labels) 21 | chose ((nth fns choice) s)] 22 | (if chose 23 | (do 24 | ; (println "\nChoosing:") 25 | ; (println labels) 26 | ; (println "Chose" choice (nth labels choice)) 27 | chose) 28 | (recur s (without fns choice) (without labels choice)))) 29 | nil)) 30 | 31 | (load "game_helpers") 32 | (load "cards") 33 | 34 | (def cards-by-id 35 | (loop [v cards by-id {}] (if (nil? v) 36 | by-id 37 | (let [head (first v)] 38 | (recur 39 | (next v) 40 | (conj by-id {(:id head) head})))))) 41 | 42 | (defn card 43 | "Gets a card definition by numerical id or attempts to get a card definition 44 | by name, throwing an exception if not exactly one card is found" 45 | [id] (if (number? id) 46 | (cards-by-id id) 47 | (let [result (filter #(= (:name %) id) cards)] 48 | (if (= 1 (count result)) 49 | (first result) 50 | (throw (Exception. (str 51 | "Could not find exactly one card with name " id))))))) 52 | 53 | ;;; 54 | 55 | ; phases: setup, mulliganing, turns, finished 56 | (defn create-game 57 | "Initializes a game up to before the mulliganing phase" 58 | [first-hero first-deck second-hero second-deck] (-> { 59 | ; whoever owns the current actor, determining :my/:opponent 60 | :actor 0 61 | ; hero, hero power, mana, and refs to weapon, minions 62 | :heroes (apply hash-map (interleave [0 1] 63 | (map create-hero [first-hero second-hero] [0 1]))) 64 | ; everything else - mix together the players to keep the structure flat 65 | :cards (vec (map (fn [card eid] (assoc-in card [:eid] eid)) (shuffle (mapcat 66 | (fn [v] (let [[pid deck] v] (map create-card deck (repeat pid)))) 67 | [[0 first-deck] [1 second-deck]])) (range))) 68 | } 69 | (#(assoc % :next-eid (count (:cards %)))) 70 | (draw-cards 3) 71 | swap-actor 72 | (draw-cards 4) 73 | swap-actor)) 74 | 75 | (defn mulligan 76 | "Do mulliganing for the current actor" 77 | [s] (let [ 78 | subsets (combo/subsets (filter-all s [:my :drawn :card])) 79 | eidsets (map #(set (map vector (repeat :eid) (map :eid %))) subsets) 80 | chosen (choose s 81 | ; transitions 82 | (for [eidset eidsets] 83 | (fn [s] (update-cards s (fn [c] 84 | (if (some eidset c) 85 | (assoc c :state :mulliganing) 86 | c))))) 87 | ; names 88 | (map #(map :name %) subsets))] 89 | ; with chosen, draw count mulliganing, make mulliganing undrawn, shuffle 90 | (-> chosen 91 | (draw-cards (count (filter-all chosen [:my :mulliganing :card]))) 92 | (update-cards #(if (some #{[:state :mulliganing]} %) 93 | (assoc-in % [:state] :undrawn) %)) 94 | (update-in [:cards] shuffle) 95 | (index-cards)))) 96 | 97 | (defn play-turn 98 | "Runs a full turn of play for the current actor" 99 | [s] (-> s 100 | (trigger-all :start-of-turn) 101 | (update-hero (fn [h] 102 | (assoc h :mana-crystal 103 | (min 10 (+ (or (:mana-crystal h) 0) 1))))) 104 | (update-hero (fn [h] 105 | (assoc h :mana 106 | (max (- (:mana-crystal h) (or (:overload h) 0)) 0)))) 107 | (draw-cards 1) 108 | (choose-loop) 109 | ((fn [s] 110 | (if (first (filter-all s [:hero :discarded])) 111 | (-> s 112 | (assoc :game-over true) 113 | (assoc :winner (:owner (first (filter-all s [:hero :played]))))) 114 | (-> s 115 | (trigger-all :end-of-turn) 116 | (reset-turn-stats))))))) 117 | -------------------------------------------------------------------------------- /src/soot/game_helpers.clj: -------------------------------------------------------------------------------- 1 | (in-ns 'soot.game) 2 | 3 | (defn all-things [s] (concat (vals (:heroes s)) (:cards s))) 4 | 5 | (defn thing-by-eid [s eid] (first (filter #(= (:eid %) eid) (all-things s)))) 6 | 7 | (defn targeter [s] (thing-by-eid s (:targeter s))) 8 | 9 | (defn observer [s] (thing-by-eid s (:observer s))) 10 | 11 | (defn last-summoned [s] (thing-by-eid (:last-summoned s))) 12 | 13 | (defn update-cards 14 | "Applies f to each card in state" 15 | [s f] (update-in s [:cards] (partial mapv f))) 16 | 17 | (defn update-last-summoned 18 | [s f] (update-cards s (fn [c] (if (= (:eid c) (:last-summoned s)) 19 | (f c) c)))) 20 | 21 | (defn update-targeter 22 | [s f] (update-cards s (fn [c] (if (= (:eid c) (:targeter s)) 23 | (f c) c)))) 24 | 25 | (defn index-cards 26 | "Adds indices to cards; use this after shuffling" 27 | [s] (update-in s [:cards] (fn 28 | [cs] (map (fn [c i] (assoc c :index i)) cs (range))))) 29 | 30 | (defn update-hero 31 | "Applies f to the current hero" 32 | [s f] (update-in s [:heroes (:actor s)] f)) 33 | 34 | (defn update-all 35 | "Applies f to cards and heroes" 36 | [s f] (-> s (update-hero f) (update-cards f))) 37 | 38 | (defn current-hero [s] (get-in s [:heroes (:actor s)])) 39 | 40 | (defn current-target 41 | "Returns the state of the current target" 42 | [s] (let [[type n] (:target s)] (cond 43 | (= type :hero) ((:heroes s) n) 44 | (= type :card) (nth (:cards s) n)))) 45 | 46 | (defn update-target 47 | "Applies f to the current target" 48 | [s f] (let [[type n] (:target s)] (cond 49 | (= type :hero) (update-in s [:heroes n] f) 50 | (= type :card) (update-in s [:cards] 51 | (partial mapv (fn [i c] (if (= i n) (f c) c)) (range)))))) 52 | 53 | (defn set-target 54 | "Sets state on the current target" 55 | ([s vs] ((apply comp 56 | (for [[k v] (seq vs)] #(update-target % (fn [c] (assoc c k v))))) s)) 57 | ([vs] (fn [s] (set-target s vs)))) 58 | 59 | ; observer stack (used to tell an event notifee who they are) 60 | 61 | (defn push-observer [s o] (-> s 62 | (update-in [:observer-stack] (fn [stack] (cons (:observer s) stack))) 63 | (assoc :observer o))) 64 | 65 | (defn pop-observer [s] (-> s 66 | (assoc :observer (first (:observer-stack s))) 67 | (update-in [:observer-stack] rest))) 68 | 69 | (def filter-map 70 | "keywords to boolean predicates for use with filter-all" 71 | { 72 | :my (fn [s] #(= (:owner %) (:actor s))) 73 | :opponent (fn [s] #(not= (:owner %) (:actor s))) 74 | :self (fn [s] #(= (:eid %) (:targeter s))) 75 | ; states 76 | :undrawn (fn [s] #(= (:state %) :undrawn)) 77 | :drawn (fn [s] #(= (:state %) :drawn)) 78 | :mulliganing (fn [s] #(= (:state %) :mulliganing)) 79 | :played (fn [s] #(= (:state %) :played)) 80 | :discarded (fn [s] #(= (:state %) :discarded)) 81 | ; types 82 | :character (fn [s] #(or (:hero %) (:minion %))) 83 | :card (fn [s] #(or (:weapon %) (:minion %) (:spell %) (:secret %))) 84 | :all (fn [s] (fn [c] true)) 85 | ; etc 86 | :damaged (fn [s] #(< (:health %) (:max-health %))) 87 | :last-summoned (fn [s] #(= (:eid %) (:last-summoned s))) 88 | ; adjacent to targeter 89 | :adjacent (fn [s] #(some #{[:left (:targeter s)] [:right (:targeter s)]} %)) 90 | :adjacent-to-target (fn [s] #(some #{ 91 | [:left (:eid (current-target s))] 92 | [:right (:eid (current-target s))]} %)) 93 | ; mapped pairs 94 | :not (fn [pred] #(not (pred %))) 95 | }) 96 | 97 | (defn filter-pred 98 | [s filt] (let [pred (filter-map filt)] 99 | (if pred 100 | (pred s) 101 | (if (map? filt) 102 | (let [[[k v]] (seq filt)] 103 | ((filter-map k) (filter-pred s (or (filter-map v) v)))) 104 | filt)))) 105 | 106 | (defn add-default-filters 107 | [filters] (cond->> filters 108 | (not-any? #{:self :undrawn :drawn :mulliganing :played :discarded} filters) 109 | (cons :played) 110 | (not-any? #{:self :card :weapon :character :hero :minion :spell :hero-power 111 | :secret :all} filters) 112 | (cons :character))) 113 | 114 | (defn add-direct-filters 115 | "Adds filters for direct targeting, implementing stealth and spell immunity; 116 | requires state to discern whether we are targeting via a spell or a minion." 117 | [s filters] (cond->> filters 118 | (not-any? #{:self :my} filters) (cons {:not :stealth}) 119 | (:spell (targeter s)) (cons {:not :spell-immunity}))) 120 | 121 | (defn filter-all 122 | [s filters] 123 | (let [fs (add-default-filters (flatten [filters])) 124 | pred (apply every-pred (map filter-pred (repeat s) fs))] 125 | (filter pred (all-things s)))) 126 | 127 | (defn trigger-target 128 | "Triggers an event on the current target. If the event returns nil, trigger 129 | acts as identity" 130 | [s event] (let [f (or (event (current-target s)) identity)] 131 | (-> s 132 | (push-observer (:eid (current-target s))) 133 | (#(or (f %) %)) 134 | pop-observer))) 135 | 136 | (defn trigger-all 137 | "Triggers an event on every entity currently in play" 138 | [s event] (reduce #(%2 %1) s (map (fn 139 | [c] (let [f (or (event c) identity)] 140 | (fn [state] (-> state 141 | (push-observer (:eid c)) 142 | (#(or (f %) %)) 143 | pop-observer)))) (filter-all s [:all])))) 144 | 145 | (defn damage-target 146 | "Gives n damage to the current target, triggering damage-based secrets" 147 | ([s n] 148 | (let [target (current-target s) 149 | _ (if (not n) (do (println "damage-target called with fucked up shit") (pprint n) (pprint s))) 150 | spell? (:spell (targeter s)) 151 | spell-damage (or (apply + (map 152 | :spell-damage 153 | (filter-all s [:my :spell-damage]))) 0) 154 | damage (if spell? (+ spell-damage n) n) 155 | damaged-armor (- (or (:armor target) 0) damage) 156 | minimum-health (or (:minimum-health target) 0) 157 | new-health (max minimum-health 158 | (+ (:health target) (min 0 damaged-armor))) 159 | new-armor (max 0 damaged-armor)] 160 | (cond 161 | (:immune target) s 162 | (:divine-shield target) (set-target s {:divine-shield false}) 163 | true (-> s 164 | (assoc :damage-taking damage) 165 | (trigger-all :before-damaged) 166 | (set-target {:health new-health :armor new-armor}) 167 | (assoc :damage-taken damage) 168 | (trigger-all :after-damaged))))) 169 | ([n] (fn [s] (damage-target s n)))) 170 | 171 | ; target stack stuff 172 | 173 | (defn target-info [t] [(if (:hero t) :hero :card) (:index t)]) 174 | 175 | (defn push-target [s t] (-> s 176 | (update-in [:target-stack] (fn [stack] (cons (:target s) stack))) 177 | (assoc :target (target-info t)))) 178 | 179 | (defn pop-target [s] (-> s 180 | ((fn [s] (if (:actor s) s (do 181 | (pprint s) 182 | (throw (Exception. "Invalid state")))))) 183 | (assoc :target (first (:target-stack s))) 184 | (update-in [:target-stack] rest))) 185 | 186 | ; targeter stack (playing, destroyer, healer, attacker, damager) 187 | 188 | (defn push-targeter [s t] (-> s 189 | (update-in [:targeter-stack] (fn [stack] (cons (:targeter s) stack))) 190 | (assoc :targeter t))) 191 | 192 | (defn pop-targeter [s] (-> s 193 | (assoc :targeter (first (:targeter-stack s))) 194 | (update-in [:targeter-stack] rest))) 195 | 196 | (defn redirect-attack-target 197 | "Modified the target stack so that the next popped target is the current 198 | target. This should cause any before-damaged events to change the target of 199 | the current attack to that target." 200 | [s] (-> s 201 | (update-in [:target-stack] #(cons (:target s) (rest %))))) 202 | 203 | (defn target-entity 204 | [s t f] (-> s 205 | (push-target t) 206 | f 207 | pop-target)) 208 | 209 | (defn target 210 | "Branches the game state, applying f to the state after the target is chosen; 211 | filters is a seq of functions or keywords. :my and :opponent are special 212 | keywords that vary based on the current actor in state." 213 | ([s filters f] (let [choices (filter-all s (add-direct-filters s filters))] 214 | (choose s 215 | (for [choice choices] (fn [s] (target-entity s choice f))) 216 | (map :name choices)))) 217 | ([filters f] (fn [s] (target s filters f)))) 218 | 219 | (defn target-all 220 | "Doesn't branch, but performs the composition of f for all targets to resolve 221 | the game state" 222 | ; kinda copy-paste but I don't care as much 223 | ([s filters f] (let [choices (filter-all s filters)] 224 | ((apply comp (for [choice choices] (fn [s] (-> s 225 | (push-target choice) 226 | f 227 | pop-target)))) s))) 228 | ([filters f] (fn [s] (target-all s filters f)))) 229 | 230 | (defn target-random 231 | "Doesn't branch, but performs f on a random or a number of random targets." 232 | ([s filters f alternate] (let [ 233 | [n rest-filters] (if (number? (first filters)) 234 | [(first filters) (rest filters)] [1 filters]) 235 | choices (filter-all s rest-filters) 236 | n-choices (count choices) 237 | chosen (shuffle (concat (repeat n true) (repeat (- n-choices n) false)))] 238 | ((apply comp (for [ 239 | [choice chose] 240 | (partition 2 (interleave (concat choices (repeat nil)) chosen))] 241 | (if choice 242 | (if chose 243 | (fn [s] (if s (-> s (push-target choice) f pop-target) nil)) 244 | identity) 245 | (fn [s] (if s (alternate s) nil))))) s))) 246 | ([s filters f] (target-random s filters f (fn [s] nil)))) 247 | 248 | (defn swap-actor 249 | [s] (update-in s [:actor] {0 1 1 0})) 250 | 251 | (defn tick-fatigue 252 | "Does a tick of fatigue on the current player" 253 | [state] (target state [:my :hero] (fn [s] (-> s 254 | (update-target (fn [hero] (update-in hero [:fatigue] #(+ 1 (or % 0))))) 255 | (#(damage-target % (get-in % [:heroes (:actor %) :fatigue]))))))) 256 | 257 | (defn cards-in-hand [s] (count (filter-all s [:my :drawn]))) 258 | 259 | (defn draw-cards 260 | "Draws n cards for the current player" 261 | ([s n] (if (> n 0) (let [ 262 | undrawn (:eid (first (filter-all s [:my :undrawn :card]))) 263 | card-state (if (>= (cards-in-hand s) 10) :discarded :drawn) 264 | drawn (if undrawn 265 | (-> s 266 | (update-cards #(if (some #{[:eid undrawn]} %) 267 | (assoc % :state card-state) %))) 268 | (tick-fatigue s))] (draw-cards drawn (dec n))) s)) 269 | ([n] (fn [s] (draw-cards s n)))) 270 | 271 | (defn draw-opponent-cards 272 | [s amount] (-> s 273 | swap-actor 274 | (draw-cards amount) 275 | swap-actor)) 276 | 277 | ; needed to resolve summons 278 | (declare card) 279 | 280 | (def property-map 281 | { 282 | :charge 1 283 | :windfury 1 284 | :immune true 285 | :divine-shield true 286 | :taunt true 287 | :freeze true 288 | :stealth true 289 | :spell-immunity true 290 | }) 291 | 292 | (def actor-map 293 | "Functions to transform card-def keys to events and stuff. 294 | (fn [value] (fn [card] ... card))" 295 | (-> { 296 | ; :attack (fn [v] (fn [c] (assoc c :attack v))) 297 | :hero-power (fn [v] (fn [c] (assoc c :power (card v)))) 298 | :when-my-spell-cast (fn [v] (fn [c] (assoc c 299 | :after-played (fn [s] (if (and 300 | (= (:owner (targeter s)) (:owner (observer s))) ; my 301 | (:spell s)) ; spell-cast 302 | (v s) s))))) 303 | :end-of-my-turn (fn [v] (fn [c] (assoc c 304 | :end-of-turn (fn [s] (if (and 305 | (= (:owner (targeter s)) (:owner (observer s)))) ; my 306 | (v s) s))))) 307 | :health (fn [v] (fn [c] (-> c (assoc :health v) (assoc :max-health v)))) 308 | :properties (fn [v] (fn [c] 309 | ((apply comp 310 | (map (fn [prop] 311 | (fn [card] (assoc card prop (property-map prop)))) v)) c))) 312 | :type (fn [v] (fn [c] (-> c (assoc v true) (assoc :type v)))) 313 | } 314 | ((apply comp (map (fn [k] 315 | (fn [m] (assoc m k (fn [v] (fn [c] (assoc c k v)))))) 316 | ; these keywords simply place their value directly on the card 317 | [:attack :spell-damage :deathrattle :battlecry]))))) 318 | 319 | (defn create-card 320 | "Creates an undrawn card given an id/name and controller id" 321 | [cid pid] (let [ 322 | card-def (card cid) 323 | actor (some #{:minion :weapon :secret :hero} (keys card-def)) 324 | ability (some #{:hero-power :spell} (keys card-def)) 325 | ] (cond-> card-def 326 | true (-> 327 | (assoc :state :undrawn) 328 | (assoc :owner pid)) 329 | actor ((apply comp 330 | ; Again, NPEs help keep shit real 331 | (map (fn 332 | [[k v]] (let [f (actor-map k)] 333 | (if f 334 | (f v) 335 | (println "Unknown actor prop (cid actor k):" cid actor k)))) 336 | (seq (actor card-def))))) 337 | ability (-> 338 | (assoc :use (ability card-def)))))) 339 | 340 | (defn summon-card 341 | [s cid] (-> s 342 | (update-in [:cards] 343 | (fn [cs] (vec (concat cs [(-> (create-card cid (:actor s)) 344 | (assoc :index (count cs)) 345 | (assoc :eid (:next-eid s)) 346 | (assoc :summoned true) 347 | (assoc :state :undrawn))])))) 348 | (assoc :last-summoned (:next-eid s)) 349 | (update-in [:next-eid] inc))) 350 | 351 | (defn give-card 352 | ([s cid] (-> s 353 | (summon-card cid) 354 | (update-last-summoned #(assoc % :state 355 | (if (>= (cards-in-hand s) 10) :discarded :drawn))))) 356 | ([cid] (fn [s] (give-card s cid)))) 357 | 358 | (defn give-opponent-card 359 | ([s cid] (-> s 360 | swap-actor 361 | (give-card cid) 362 | swap-actor)) 363 | ([cid] (fn [s] (give-opponent-card s cid)))) 364 | 365 | (defn summon-minion 366 | "Creates and summons one or more minions for the current actor. Does not 367 | trigger battlecries." 368 | ([s minions] (if (seq? minions) 369 | ((apply comp (map (fn [m] (fn [s] (summon-minion s m))) minions)) s) 370 | ; use identity for over-summoning; it's not an invalid state. 371 | (if (>= (count (filter-all s [:my :minion])) 7) s 372 | (-> s 373 | (trigger-all :before-summoned) 374 | (summon-card minions) 375 | ; summon to the right of the targeter 376 | (update-last-summoned #(-> % 377 | (assoc :summoning-sickness true) 378 | (assoc :state :played) 379 | (assoc :left (:targeter s)) 380 | (assoc :right (:right (targeter s))))) 381 | ; update the targeter's right 382 | (#(update-cards % (fn [c] (if (= (:eid c) (:targeter s)) 383 | (assoc c :right (:last-summoned %)) c)))) 384 | ; update the targeter's right's left 385 | (#(update-cards % (fn [c] (if (= (:eid c) (:right (targeter s))) 386 | (assoc c :left (:last-summoned %)) c)))) 387 | (trigger-all :after-summoned))))) 388 | ([minions] (fn [s] (summon-minion s minions)))) 389 | 390 | (defn summon-opponent-minion 391 | ([s minions] (-> s 392 | swap-actor 393 | (summon-minion minions) 394 | swap-actor)) 395 | ([minions] (fn [s] (summon-opponent-minion s minions)))) 396 | 397 | (defn remove-target-positioning 398 | "Removes the target's positioning info and updates the target's neighbors' 399 | positioning info" 400 | [s] (let [target (current-target s)] (-> s 401 | (update-target (fn [t] (-> t 402 | (assoc :left nil) 403 | (assoc :right nil)))) 404 | (update-cards (fn [c] (cond-> c 405 | (= (:eid c) (:left target)) (assoc :right (:right target)) 406 | (= (:eid c) (:right target)) (assoc :left (:left target)))))))) 407 | 408 | (defn return-target 409 | ([s] (-> s 410 | (update-target (fn [t] (-> (create-card (:id t) (:owner t)) 411 | (assoc :eid (:eid t)) 412 | (assoc :state :drawn)))) 413 | (remove-target-positioning))) 414 | ([] (fn [s] (return-target s)))) 415 | 416 | (defn swap-with-target ; Alarm-o-Bot 417 | [s] (let [target-eid (:eid (current-target s))] 418 | (-> s 419 | (trigger-all :before-summoned) 420 | (target [:self] return-target) 421 | (assoc :last-summoned target-eid) 422 | (update-target (fn [t] (-> t 423 | (assoc :summoning-sickness true) 424 | (assoc :state :played) 425 | (assoc :left (:left (targeter s))) 426 | (assoc :right (:right (targeter s)))))) 427 | (update-cards (fn [c] (cond-> c 428 | (= (:eid c) (:left (targeter s))) (assoc :right target-eid) 429 | (= (:eid c) (:right (targeter s))) (assoc :left target-eid)))) 430 | (trigger-all :after-summoned)))) 431 | 432 | ; (defn && [& bools] (every? identity bools)) 433 | (defn || [& bools] (some identity (cons false bools))) 434 | 435 | (def give-target-map 436 | "Determines how to add stats with give-target" 437 | ; also causes NPEs! (fn [& values] ...) 438 | { 439 | :immune || 440 | :divine-shield || 441 | :taunt || 442 | :freeze || 443 | ; gets to be a number because it's the easiest way to deal with +charge auras 444 | :charge + 445 | :windfury + ; for raging worgen's enrage 446 | :stealth || 447 | :stealth-this-turn || 448 | :stealth-next-turn || 449 | :spell-damage + 450 | :attack + 451 | :attack-this-turn + 452 | :use-cost + 453 | :mana + 454 | :mana-crystal + 455 | :health + 456 | :max-health + 457 | :armor + 458 | :deathrattle comp 459 | :before-minion-attacks comp 460 | :start-of-my-turn comp 461 | :end-of-turn comp 462 | }) 463 | 464 | (defn give-target 465 | "Adds to the current target's stats" 466 | ; todo: do correct :max-health updating with :health modifiers 467 | ([s stats] (if (map? stats) 468 | (reduce #(%2 %1) s (map (fn 469 | [[stat value]] (fn [s] 470 | (update-target s (fn [t] 471 | ; support functions such as doubling attack/health 472 | (update-in t [stat] (if (fn? value) value (fn [v] 473 | ; prevent NPEing when the target doesn't have a value yet 474 | (#(% value (or v (%))) (give-target-map stat))))))))) 475 | stats)) 476 | (give-target s {stats true}))) 477 | ([stats] (fn [s] (give-target s stats)))) 478 | 479 | (defn buff-target 480 | ([s attack health] (give-target s {:attack attack :health health})) 481 | ([attack health] (fn [s] (buff-target s attack health)))) 482 | 483 | (defn buff-weapon 484 | ([s attack health] (target s [:my :weapon] (buff-target attack health))) 485 | ([attack health] (fn [s] (buff-weapon s attack health)))) 486 | 487 | (defn buff-self 488 | ([s attack health] (target s [:self] (buff-target attack health))) 489 | ([attack health] (fn [s] (buff-self s attack health)))) 490 | 491 | (defn choose-one 492 | "Chooses between given spell ids/names. Does NOT create the spells, simply 493 | applies their card-def's :spell function." 494 | ([s choices] (choose s 495 | (map :spell (map card choices)) 496 | (map #(:name (card %)) choices))) 497 | ([choices] (fn [s] (choose-one s choices)))) 498 | 499 | (defn destroy-target 500 | "Destroys (discards) the target. Triggers deathrattles." 501 | ; note: for minions damaged to below 0 health, destruction is triggered after 502 | ; exiting the current card's context; i.e., after a card is used, all cards 503 | ; are checked for destruction. this prevents weirdness when aoe cards and 504 | ; aura minions combine. 505 | ([s] (-> s 506 | (trigger-all :before-destroyed) 507 | (set-target {:state :discarded}) 508 | (trigger-target :deathrattle) 509 | (remove-target-positioning) 510 | (trigger-all :after-destroyed))) 511 | ([] (fn [s] (destroy-target s)))) 512 | 513 | (defn destroy-self 514 | [s] (target [:self] destroy-target)) 515 | 516 | (defn equip-weapon 517 | "Creates and summons a weapon for the current hero. Destroys any existing 518 | weapon first" 519 | ; todo: this feels wrong 520 | ([s cid] (-> s 521 | (target [:my :weapon] destroy-target) 522 | (summon-card cid) 523 | (update-last-summoned #(assoc % :state :played)))) 524 | ([cid] (fn [s] (equip-weapon s cid)))) 525 | 526 | (defn destroy-opponent-weapon 527 | [s] (target s [:opponent :weapon] destroy-target)) 528 | 529 | (defn opponent-weapon-durability 530 | [s] (:health (first (filter-all s [:opponent :weapon])))) 531 | 532 | (defn create-hero 533 | [cid pid] (-> 534 | (create-card cid pid) 535 | (assoc :state :played) 536 | (assoc :index pid) 537 | (assoc :eid (- pid 2)))) 538 | 539 | (defn set-hero 540 | [s cid] (let [pid (:actor s)] 541 | (update-hero #(create-hero cid pid)))) 542 | 543 | (defn count-minions 544 | [s filters] (count (filter-all s (conj filters :minion)))) 545 | 546 | (defn mind-control-target 547 | ([s] (-> s (update-target (fn [c] (assoc c :owner (- 1 (:actor s))))))) 548 | ([] (fn [s] (mind-control-target s)))) 549 | 550 | (defn polymorph-target 551 | ([s cid] (-> s 552 | (summon-card cid) 553 | ; summon to the right of the targeter 554 | (update-last-summoned #(-> % 555 | (assoc :state :played) 556 | (assoc :summoning-sickness true) 557 | (assoc :left (:left (current-target s))) 558 | (assoc :right (:right (current-target s))))) 559 | ; update the target's left's right 560 | (#(update-cards % (fn [c] (if (= (:eid c) (:left (current-target s))) 561 | (assoc c :right (:last-summoned %)) c)))) 562 | ; update the target's right's left 563 | (#(update-cards % (fn [c] (if (= (:eid c) (:right (current-target s))) 564 | (assoc c :left (:last-summoned %)) c)))) 565 | (destroy-target))) 566 | ([cid] (fn [s] (polymorph-target s cid)))) 567 | 568 | (defn combo 569 | ([s normal-f combo-f] (if (> (:cards-played-this-turn s) 0) 570 | (combo-f s) (normal-f s))) 571 | ([normal-f combo-f] (fn [s] (combo s normal-f combo-f)))) 572 | 573 | (defn is-dead 574 | ; used in cases where the card hasn't been checked for death yet, so we check 575 | ; current health as well 576 | [c] (or (= (:state c) :discarded) (<= (:health c) 0))) 577 | 578 | (defn destroy-minions 579 | ([s] (target-all [:minion] destroy-target)) 580 | ([] (fn [s] (destroy-minions s)))) 581 | 582 | (defn draw-target 583 | [s] (update-target s #(update-in % [:state] :drawn))) 584 | 585 | (defn copy-target 586 | [s] (let [target (current-target s)] 587 | (update-targeter s (fn [t] (-> target 588 | (assoc :owner (:owner t)) 589 | (assoc :eid (:eid t)) 590 | (assoc :left (:left t)) 591 | (assoc :right (:right t))))))) 592 | 593 | (defn hero-armor [s] (:armor (current-hero s))) 594 | 595 | (defn hero-health [s] (:health (current-hero s))) 596 | 597 | (defn hero-max-health [s] (:max-health (current-hero s))) 598 | 599 | (defn hero-power [s] (:power (current-hero s))) 600 | 601 | (defn hero-attack [s] (:attack-this-turn (current-hero s))) 602 | 603 | ; probably need to move this up before actor-map 604 | (defn set-hero-power [s cid] 605 | (target s [:my :hero] #(update-target % 606 | (fn [hero] (assoc hero :power (card cid)))))) 607 | 608 | (defn is-friendly [s character] (= (:owner character) (:actor s))) 609 | 610 | (defn restore-health 611 | "Restores amount health to the current target. Has a special case for 612 | Auchenai Soulpriest." 613 | ([s amount] 614 | (let [t (current-target s) 615 | new-health (max (+ (:health t) amount) (:max-health t)) 616 | restored (- new-health (:health t)) 617 | soulpriest (:auchenai-soulpriest-aura (current-hero s))] 618 | (cond 619 | ; note: this damage is increased by spell damage when it's a healing spell 620 | soulpriest (-> s damage-target s) 621 | (> restored 0) (-> s 622 | (trigger-all :before-healed) 623 | (update-target #(assoc % :health new-health)) 624 | (trigger-all :after-healed))))) 625 | ([amount] (fn [s] (restore-health s amount)))) 626 | 627 | (defn gain-aura 628 | "Adds the current target's aura effects to other minions" 629 | [s] 630 | (let [target (current-target s) 631 | aura (:aura target) 632 | self? (= :self (:filter aura)) 633 | filters (cons {:not :self} (:filter aura)) 634 | stats (dissoc aura :filter)] 635 | (if self? 636 | (give-target s stats) 637 | (-> s (target-all filters (fn [t] 638 | (reduce #(%2 %1) t (map (fn 639 | [[stat value]] (fn [c] 640 | ; similar to give-target, but only use + for comp 641 | (let [update-fn (fn [v] (+ value (or v (+))))] 642 | (-> c 643 | (update-in [stat] update-fn) 644 | ; and also store these given stats in :aura-gains 645 | (update-in [:aura-gains stat] update-fn))))) stats)))))))) 646 | 647 | (defn fade-aura 648 | "Removes the current target's aura effects from other minions" 649 | [s] 650 | ; copy paste -- all we wanna do is negate update-fn 651 | (let [target (current-target s) 652 | aura (:aura target) 653 | self? (= :self (:filter aura)) 654 | filters (cons {:not :self} (:filter aura)) 655 | stats (dissoc aura :filter)] 656 | (if self? 657 | ; fades on self are only used for enrage fading... there's a lot of 658 | ; cheating going on with auras, something to think about. 659 | (give-target s (map (fn [[k v]] [k (- v)]) stats)) 660 | (-> s (target-all filters (fn [t] 661 | (reduce #(%2 %1) t (map (fn 662 | [[stat value]] (fn [c] 663 | (let [update-fn (fn [v] (- (or v (+)) value))] 664 | (-> c 665 | (update-in [stat] update-fn) 666 | (update-in [:aura-gains stat] update-fn))))) stats)))))))) 667 | 668 | (defn silence-target 669 | "Silences the target minion, removing all card text, including properties, 670 | events, and outgoing auras" 671 | [s] 672 | (let [t (current-target s) 673 | card-def (create-card (:id t) (:owner t)) 674 | card-attack (:attack card-def) 675 | card-health (:health card-def) 676 | new-health (min card-health (:health t))] 677 | (-> s 678 | ; remove our auras from others 679 | fade-aura 680 | ; give post-silence pre-aura stats 681 | (update-target (fn [c] (-> c 682 | (assoc :health new-health) 683 | (assoc :attack card-attack) 684 | (dissoc :taunt :freeze :enrage :charge :windfury :divine-shield 685 | :stealth :spell-damage :deathrattle :aura)))) 686 | ; reapply auras gained from others 687 | (give-target (:aura-gains t))))) 688 | 689 | (defn use-minion 690 | "Attacks with a minion" 691 | [eid] (fn [state] 692 | (let [minion (thing-by-eid state eid) 693 | times-attacking (or (:times-attacking minion) 0) 694 | times-can-attack (if (:windfury minion) 2 1) 695 | can-attack (and 696 | (or 697 | (> (or (:charge minion) 0) 0) 698 | (not (:summoning-sickness minion))) 699 | (not (:cant-attack minion)) 700 | (not (:freeze minion)) 701 | (> (:attack minion) 0) 702 | (< times-attacking times-can-attack))] 703 | (if can-attack 704 | (-> state 705 | (push-targeter eid) 706 | (target [:opponent] (fn [s] (-> s 707 | (trigger-all :before-attacked) 708 | (damage-target (:attack minion)) 709 | (update-targeter #(assoc % :times-attacking (inc times-attacking))) 710 | (push-targeter (:eid (current-target s))) 711 | (target-entity minion 712 | (fn [st] (let [rec-damage (or (:attack (targeter st)) 0)] 713 | (if (> rec-damage 0) 714 | (damage-target st rec-damage) 715 | st)))) 716 | (pop-targeter) 717 | (trigger-all :after-attacked)))) 718 | pop-targeter) 719 | nil)))) 720 | 721 | (defn play-minion 722 | "Plays a minion (targeter) to the right of the current target" 723 | [s] (let [targeter-eid (:targeter s) 724 | tar (current-target s) 725 | target-eid (:eid tar)] 726 | (-> s 727 | (trigger-all :before-summoned) 728 | (assoc :last-summoned targeter-eid) 729 | ; summon to the right of the target 730 | (update-last-summoned #(-> % 731 | (assoc :state :played) 732 | (assoc :summoning-sickness true) 733 | (assoc :left target-eid) 734 | (assoc :right (:right tar)))) 735 | (update-cards (fn [c] (cond-> c 736 | ; update the target's right 737 | (= (:eid c) target-eid) (assoc :right targeter-eid) 738 | ; update the target's right's left 739 | (= (:eid c) (:right tar)) (assoc :left targeter-eid)))) 740 | (target-entity (targeter s) #(trigger-target % :battlecry)) 741 | (trigger-all :after-summoned)))) 742 | 743 | (defn use-card 744 | "Uses a card (spell, minion, weapon, or secret)" 745 | [eid] (fn [state] 746 | (let [thing (thing-by-eid state eid) 747 | cost (if (fn? (:cost thing)) ((:cost thing) state) (:cost thing)) 748 | unusable (> cost (:mana (current-hero state))) 749 | cant-play-minions (>= (count (filter-all state [:my :minion])) 7) 750 | invalid (fn [_] nil) 751 | used (or unusable (cond-> state 752 | true (-> 753 | (push-targeter eid) 754 | (trigger-all :before-played)) 755 | (:minion thing) (-> 756 | (target [:my] play-minion)) 757 | (:weapon thing) (-> 758 | (target [:my :weapon] destroy-target) 759 | (assoc :last-summoned eid) 760 | (update-last-summoned #(-> % 761 | (assoc :state :played))) 762 | (target [:self] #(trigger-target % :battlecry))) 763 | (:secret thing) (-> 764 | (assoc :last-summoned eid) 765 | (update-last-summoned #(-> % 766 | (assoc :state :played)))) 767 | (:spell thing) (-> 768 | (update-targeter #(assoc % :state :discarded)) 769 | ((:use thing)))))] 770 | (if used 771 | (if unusable nil 772 | (if (and (:minion thing) cant-play-minions) nil 773 | (-> used 774 | (update-hero (fn [h] (update-in h [:mana] #(- % cost)))) 775 | (trigger-all :after-played) 776 | (update-in [:cards-played-this-turn] #(+ (or % 0) 1)) 777 | pop-targeter))))))) 778 | 779 | (defn use-hero-power 780 | [s] 781 | (let [hero (current-hero s) 782 | times-power-used (or (:times-power-used hero) 0) 783 | cost (:cost (:power hero)) 784 | unusable (or (> cost (:mana hero)) (>= times-power-used 1))] 785 | (if unusable 786 | nil 787 | (-> s 788 | (push-targeter (:eid hero)) 789 | ((:hero-power (:power hero))) 790 | (update-hero (fn [h] 791 | (update-in h [:mana] #(- % cost)))) 792 | (update-hero (fn [h] 793 | (assoc h :times-power-used (inc times-power-used)))) 794 | pop-targeter)))) 795 | 796 | (defn attack-with-hero 797 | [state] 798 | (let [hero (current-hero state) 799 | times-attacking (or (:times-attacking hero) 0) 800 | times-can-attack (if 801 | (:windfury (first (filter-all state [:my :weapon]))) 2 1) 802 | can-attack (and 803 | (not (:freeze hero)) 804 | (> (or (:attack hero) 0) 0) 805 | (< times-attacking times-can-attack))] 806 | (if can-attack 807 | (-> state 808 | (push-targeter (:eid hero)) 809 | (target [:opponent] (fn [s] (-> s 810 | (trigger-all :before-attacked) 811 | (damage-target (:attack hero)) 812 | (update-hero (fn [h] (assoc h :times-attacking (inc times-attacking)))) 813 | (push-targeter (:eid (current-target s))) 814 | (target-entity hero 815 | (fn [st] (let [rec-damage (or (:attack (targeter st)) 0)] 816 | (if (> rec-damage 0) 817 | (damage-target st rec-damage) 818 | st)))) 819 | (pop-targeter) 820 | (trigger-all :after-attacked)))) 821 | pop-targeter) 822 | nil))) 823 | 824 | (defn end-turn 825 | [s] (assoc s :turn-ended true)) 826 | 827 | (defn choose-loop 828 | "Enumerates the choices in a turn of play, chooses one, and updates any state 829 | that needs to be updated after each action is taken. This repeats until the 830 | choice is made to end the turn." 831 | [s] 832 | (let [my-cards (filter-all s [:my :drawn :card]) 833 | my-minions (filter-all s [:my :minion]) 834 | used-cards (map use-card (map :eid my-cards)) 835 | card-names (map :name my-cards) 836 | used-minions (map use-minion (map :eid my-minions)) 837 | minion-names (map :name my-minions) 838 | choices (concat used-cards used-minions 839 | [use-hero-power attack-with-hero end-turn]) 840 | labels (concat card-names minion-names 841 | ["Hero Power" "Attack with Hero" "End Turn"]) 842 | action-taken (-> s 843 | ; if this returns nil something has gone wrong 844 | (choose choices labels) 845 | ((fn [st] (if (:actor st) 846 | st 847 | (do 848 | (println "CHOOSE RETURNED NIL") 849 | (pprint choices) 850 | (pprint labels) 851 | (pprint s) 852 | (pprint st) nil)))) 853 | ((fn [st] (if (vector? (:cards st)) 854 | st 855 | (do 856 | (println ":cards not a vector") 857 | (pprint choices) 858 | (pprint labels) 859 | (pprint s) 860 | (pprint st) nil)))) 861 | ; destroy dead weapons 862 | (target-all [:my :weapon] (fn [s] 863 | (if (<= (:health (current-target s)) 0) 864 | (destroy-target s) 865 | s))) 866 | ; recalculate hero attack 867 | (#(update-hero % (fn [h] 868 | (assoc h :attack (+ 869 | (or (:attack-this-turn h) 0) 870 | (or (:attack (first (filter-all % [:my :weapon]))) 0)))))) 871 | ; destroy dead minions and heroes 872 | (target-all [] (fn [s] 873 | (if (<= (or (:health (current-target s)) 1) 0) 874 | (destroy-target s) 875 | s))) 876 | ; apply end-of-turn if a hero is dead 877 | (#(update-in % [:turn-ended] (fn [v] (or v 878 | (first (filter-all % [:hero :discarded])))))))] 879 | (if (:turn-ended action-taken) action-taken (recur action-taken)))) 880 | 881 | (defn reset-turn-stats 882 | "Resets or turns over state values specific to this turn, e.g. 883 | attack-this-turn, overload." 884 | [s] (-> s 885 | (update-all 886 | (fn [c] 887 | (cond-> c 888 | (:attack-this-turn c) 889 | (update-in [:attack] #(- % (or (:attack-this-turn c) 0))) 890 | true 891 | (dissoc 892 | :immune 893 | :times-attacking 894 | :summoning-sickness 895 | :times-power-used 896 | :attack-this-turn 897 | :minimum-health-this-turn 898 | :stealth-this-turn 899 | :overload) 900 | (:overload-next-turn c) 901 | (assoc :overload (:overload-next-turn c)) 902 | (:stealth-next-turn c) 903 | (assoc :stealth-this-turn (:stealth-next-turn c)) 904 | ))) 905 | (dissoc 906 | :turn-ended 907 | :cards-played-this-turn 908 | :spells-cost-this-turn 909 | :spells-cost-next-turn) 910 | (cond-> 911 | (:spells-cost-next-turn s) 912 | (assoc :spells-cost-this-turn (:spells-cost-next-turn s))))) 913 | -------------------------------------------------------------------------------- /state.h: -------------------------------------------------------------------------------- 1 | #ifndef _state_h 2 | #define _state_h 3 | 4 | #include 5 | #include "thing.h" 6 | 7 | typedef struct State { 8 | uint8_t actor; 9 | uint8_t flags[7]; 10 | uint16_t things_len; 11 | uint16_t last_summoned; 12 | uint16_t target; 13 | uint16_t targeter; 14 | uint16_t *target_stack; 15 | uint16_t *targeter_stack; 16 | uint16_t *observer_stack; 17 | uint16_t observer; 18 | uint8_t cards_played_this_turn; 19 | uint8_t spells_cost_this_turn; 20 | uint8_t spells_cost_next_turn; 21 | } State; 22 | 23 | #endif // _state_h 24 | -------------------------------------------------------------------------------- /support.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "support.h" 3 | 4 | HANDLE stdout; 5 | int stdout_initted; 6 | 7 | void print(char *buf, size_t length) { 8 | if (!stdout_initted) { 9 | stdout = GetStdHandle(STD_OUTPUT_HANDLE); 10 | stdout_initted = 1; 11 | } 12 | 13 | WriteFile(stdout, buf, length, 0, 0); 14 | } 15 | 16 | void print_s(char *str) { 17 | print(str, strlen(str)); 18 | } 19 | 20 | void print_p(intptr_t p) { 21 | char hex[16]; 22 | size_t n = __builtin_clzll(p) / 4; 23 | size_t i = 15; 24 | while (i >= n) { 25 | hex[i--] = "0123456789abcdef"[p & 15]; 26 | p /= 16; 27 | } 28 | print(hex + n, 16 - n); 29 | } 30 | 31 | void print_n(uint64_t n) { 32 | print("unused", n); 33 | } 34 | 35 | void init_large_pages(void) { 36 | HANDLE hToken; 37 | OpenProcessToken( 38 | GetCurrentProcess(), 39 | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, 40 | &hToken); 41 | TOKEN_PRIVILEGES tp; 42 | LookupPrivilegeValue( 43 | NULL, 44 | TEXT("SeLockMemoryPrivilege"), 45 | &tp.Privileges[0].Luid); 46 | tp.PrivilegeCount = 1; 47 | tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 48 | AdjustTokenPrivileges( 49 | hToken, FALSE, &tp, 50 | 0, 0, 0); 51 | CloseHandle(hToken); 52 | 53 | if (GetLastError() != 0) { 54 | print_s("Couldn't get SeLockMemoryPrivilege. We're hosed.\n"); 55 | ExitProcess(1); 56 | } 57 | } 58 | 59 | size_t page_size; 60 | 61 | uintptr_t get_page(uintptr_t p) { 62 | if (page_size == 0) { 63 | page_size = GetLargePageMinimum(); 64 | } 65 | uintptr_t n = (uintptr_t)VirtualAlloc((void *)p, 66 | page_size, MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); 67 | if (n == 0) { 68 | print_s("Couldn't alloc a page. We're hosed.\n"); 69 | ExitProcess(1); 70 | } 71 | return n; 72 | } 73 | 74 | size_t get_page_size(void) { 75 | return page_size; 76 | } 77 | 78 | void free_page(void *addr) { 79 | VirtualFree(addr, 0, MEM_RELEASE); 80 | } 81 | -------------------------------------------------------------------------------- /support.h: -------------------------------------------------------------------------------- 1 | #ifndef _support_h 2 | #define _support_h 3 | 4 | #include 5 | #include 6 | 7 | // console output 8 | void print(char *, size_t); 9 | void print_s(char *); 10 | void print_p(intptr_t); 11 | void print_n(uint64_t); 12 | 13 | // memory allocation 14 | void init_large_pages(void); 15 | uintptr_t get_page(uintptr_t ); 16 | size_t get_page_size(void); 17 | void free_page(void *); 18 | 19 | #endif // _support_h 20 | -------------------------------------------------------------------------------- /test/soot/game_test.clj: -------------------------------------------------------------------------------- 1 | (ns soot.game-test 2 | (:require [clojure.test :refer :all] 3 | [soot.game :refer :all] 4 | [clojure.pprint :refer [pprint]] 5 | [criterium.core :as crit])) 6 | 7 | (def druid-deck [ 8 | "Innervate" "Innervate" 9 | "Claw" "Claw" 10 | 633 633 ; Wrath 11 | "Bloodmage Thalnos" 12 | "Novice Engineer" "Novice Engineer" 13 | "Wild Pyromancer" "Wild Pyromancer" 14 | "Earthen Ring Farseer" "Earthen Ring Farseer" 15 | "Harvest Golem" "Harvest Golem" 16 | "Tinkmaster Overspark" 17 | "Swipe" "Swipe" 18 | "Defender of Argus" 19 | "Keeper of the Grove" "Keeper of the Grove" 20 | 464 ; Starfall 21 | 587 587 ; Druid of the Claw 22 | "Sylvanas Windrunner" 23 | "Cairne Bloodhoof" 24 | "Ancient of Lore" "Ancient of Lore" 25 | "Baron Geddon" 26 | "Cenarius" 27 | ]) 28 | 29 | (defn druid-game 30 | [] 31 | (-> (create-game 32 | "Malfurion Stormrage" 33 | druid-deck 34 | "Malfurion Stormrage" 35 | druid-deck) 36 | mulligan 37 | swap-actor 38 | mulligan 39 | (give-card "The Coin") 40 | swap-actor)) 41 | 42 | (defn turn-until-win 43 | [s] (let [next-turn 44 | (-> s 45 | play-turn 46 | swap-actor)] 47 | (if (:game-over next-turn) 48 | next-turn 49 | (recur next-turn)))) 50 | 51 | (deftest random-game-test 52 | (testing "FIXME, I fail." 53 | (crit/bench (turn-until-win (druid-game))) 54 | (is (= 0 1)))) 55 | -------------------------------------------------------------------------------- /thing.h: -------------------------------------------------------------------------------- 1 | #ifndef _thing_h 2 | #define _thing_h 3 | 4 | #include 5 | 6 | typedef struct Thing { 7 | uint16_t id; 8 | uint8_t attack; 9 | uint8_t health; 10 | uint16_t left; 11 | uint16_t right; 12 | uint32_t flags1; /* 13 | owner : 1 14 | state : 3 (undrawn, drawn, mulliganed, played, discarded) 15 | card_type : 3 (hero, minion, weapon, spell, secret) 16 | minion_type : 3 (general, beast, demon, dragon, murloc, pirate, totem) 17 | times_attacked : 2 18 | mana : 4 19 | mana_crystals : 4 20 | times_power_used : 1 21 | use_cost : 5 22 | armor : 6 */ 23 | uint32_t flags2; /* 24 | taunt : 1 25 | stealth : 1 26 | conceal : 1 27 | summoned : 1 28 | exhaustion : 1 29 | silenced : 1 30 | immune : 1 31 | spell_immunity : 1 32 | spell_damage : 4 33 | divine_shield : 1 34 | freeze : 1 35 | charge : 1 36 | windfury : 1 37 | preparation : 1 38 | ancestral_spirit : 1 39 | summoning_portals : 3 40 | headcracks : 3 41 | auchenai_soulpriest : 1 42 | counterspell : 1 43 | kirin_tor_mage : 1 44 | (unused) : 5 */ 45 | int8_t spells_cost; 46 | int8_t minions_cost; 47 | uint8_t attack_this_turn; 48 | uint8_t max_health; 49 | uint32_t has_partials; // helps with reference counting when we copy states 50 | // 8*8 = 64 bytes 51 | void *on_attacked; 52 | void *on_damaged; 53 | void *on_healed; 54 | void *on_played; 55 | void *on_summoned; 56 | void *on_destroyed; 57 | void *on_turn_start; 58 | void *on_turn_end; 59 | } Thing; 60 | 61 | /* unsafe bitfields macro - name, type, field, size, offset */ 62 | #define _bitfield(n,t,f,s,o) \ 63 | static inline uint8_t get_##n(t *); \ 64 | static inline uint8_t get_##n(t *thing) { \ 65 | return (uint8_t)((thing->f & (((1 << s) - 1) << o)) >> o); \ 66 | } \ 67 | static inline void set_##n(t *, uint8_t); \ 68 | static inline void set_##n(t *thing, uint8_t value) { \ 69 | thing->f = (thing->f & ~(((1 << s) - 1) << o)) | (((uint32_t)value) << o); \ 70 | } 71 | 72 | /* flags1 bitfields */ 73 | _bitfield(owner, Thing, flags1, 1, 0); 74 | _bitfield(state, Thing, flags1, 3, 1); 75 | _bitfield(card_type, Thing, flags1, 3, 4); 76 | _bitfield(minion_type, Thing, flags1, 3, 7); 77 | _bitfield(times_attacked, Thing, flags1, 2, 10); 78 | _bitfield(mana, Thing, flags1, 4, 12); 79 | _bitfield(mana_crystals, Thing, flags1, 4, 16); 80 | _bitfield(times_power_used, Thing, flags1, 1, 20); 81 | _bitfield(use_cost, Thing, flags1, 5, 21); 82 | _bitfield(armor, Thing, flags1, 6, 26); 83 | 84 | /* flags2 bitfields */ 85 | _bitfield(taunt, Thing, flags2, 1, 0); 86 | _bitfield(stealth, Thing, flags2, 1, 1); 87 | _bitfield(conceal, Thing, flags2, 1, 2); 88 | _bitfield(summoned, Thing, flags2, 1, 3); 89 | _bitfield(exhaustion, Thing, flags2, 1, 4); 90 | _bitfield(silenced, Thing, flags2, 1, 5); 91 | _bitfield(immune, Thing, flags2, 1, 6); 92 | _bitfield(spell_immunity, Thing, flags2, 1, 7); 93 | _bitfield(spell_damage, Thing, flags2, 4, 8); 94 | _bitfield(divine_shield, Thing, flags2, 1, 12); 95 | _bitfield(freeze, Thing, flags2, 1, 13); 96 | _bitfield(charge, Thing, flags2, 1, 14); 97 | _bitfield(windfury, Thing, flags2, 1, 15); 98 | _bitfield(preparation, Thing, flags2, 1, 16); 99 | _bitfield(ancestral_spirit, Thing, flags2, 1, 17); 100 | _bitfield(summoning_portals, Thing, flags2, 3, 18); 101 | _bitfield(headcracks, Thing, flags2, 3, 21); 102 | _bitfield(auchenai_soulpriest, Thing, flags2, 1, 24); 103 | _bitfield(counterspell, Thing, flags2, 1, 25); 104 | _bitfield(kirin_tor_mage, Thing, flags2, 1, 26); 105 | 106 | /* has_partials bitfields */ 107 | _bitfield(has_on_attacked, Thing, has_partials, 1, 0); 108 | _bitfield(has_on_damaged, Thing, has_partials, 1, 1); 109 | _bitfield(has_on_healed, Thing, has_partials, 1, 2); 110 | _bitfield(has_on_played, Thing, has_partials, 1, 3); 111 | _bitfield(has_on_summoned, Thing, has_partials, 1, 4); 112 | _bitfield(has_on_destroyed, Thing, has_partials, 1, 5); 113 | _bitfield(has_on_turn_start, Thing, has_partials, 1, 6); 114 | _bitfield(has_on_turn_end, Thing, has_partials, 1, 7); 115 | 116 | #endif // _thing_h 117 | --------------------------------------------------------------------------------