PageRenderTime 58ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 2ms

/ai/action.cs

https://github.com/revolutioncom/HRCustomClasses
C# | 7414 lines | 6158 code | 930 blank | 326 comment | 2351 complexity | 32ee997c99d71ff7390718b10a55e5f8 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. // the ai :D
  2. //please ask/write me if you use this in your project
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Text;
  6. //TODO:
  7. //cardids of duplicate + avenge
  8. //tueftlermeisteroberfunks
  9. //verrückter bomber ( 3 damage to random chars)
  10. //nozdormu (for computing time :D)
  11. //faehrtenlesen
  12. // lehrensucher cho
  13. //scharmuetzel kills all :D
  14. //hoggersmash
  15. namespace HREngine.Bots
  16. {
  17. public class Action
  18. {
  19. public bool cardplay = false;
  20. public bool heroattack = false;
  21. public bool useability = false;
  22. public bool minionplay = false;
  23. public Handmanager.Handcard handcard;
  24. public int cardEntitiy = -1;
  25. public int owntarget = -1; //= target where card/minion is placed
  26. public int ownEntitiy = -1;
  27. public int enemytarget = -1; // target where red arrow is placed
  28. public int enemyEntitiy = -1;
  29. public int druidchoice = 0; // 1 left card, 2 right card
  30. public int numEnemysBeforePlayed = 0;
  31. public bool comboBeforePlayed = false;
  32. public void print()
  33. {
  34. Helpfunctions help = Helpfunctions.Instance;
  35. help.logg("current Action: ");
  36. if (this.cardplay)
  37. {
  38. help.logg("play " + this.handcard.card.name);
  39. if (this.druidchoice >= 1) help.logg("choose choise " + this.druidchoice);
  40. help.logg("with entityid " + this.cardEntitiy);
  41. if (this.owntarget >= 0)
  42. {
  43. help.logg("on position " + this.owntarget);
  44. }
  45. if (this.enemytarget >= 0)
  46. {
  47. help.logg("and target to " + this.enemytarget + " " + this.enemyEntitiy);
  48. }
  49. }
  50. if (this.minionplay)
  51. {
  52. help.logg("attacker: " + this.owntarget + " enemy: " + this.enemytarget);
  53. help.logg("targetplace " + this.enemyEntitiy);
  54. }
  55. if (this.heroattack)
  56. {
  57. help.logg("attack with hero, enemy: " + this.enemytarget);
  58. help.logg("targetplace " + this.enemyEntitiy);
  59. }
  60. if (this.useability)
  61. {
  62. help.logg("useability ");
  63. if (this.enemytarget >= 0)
  64. {
  65. help.logg("on enemy: " + this.enemytarget + "targetplace " + this.enemyEntitiy);
  66. }
  67. }
  68. help.logg("");
  69. }
  70. }
  71. public class Playfield
  72. {
  73. public bool logging = false;
  74. public bool sEnemTurn = false;
  75. public int attackFaceHP = 15;
  76. public int evaluatePenality = 0;
  77. public int ownController = 0;
  78. public int ownHeroEntity = -1;
  79. public int enemyHeroEntity = -1;
  80. public int value = Int32.MinValue;
  81. public int guessingHeroHP = 30;
  82. public int mana = 0;
  83. public int enemyHeroHp = 30;
  84. public HeroEnum ownHeroName = HeroEnum.druid;
  85. public HeroEnum enemyHeroName = HeroEnum.druid;
  86. public bool ownHeroReady = false;
  87. public bool enemyHeroReady = false;
  88. public int ownHeroNumAttackThisTurn = 0;
  89. public int enemyHeroNumAttackThisTurn = 0;
  90. public bool ownHeroWindfury = false;
  91. public bool enemyHeroWindfury = false;
  92. public List<string> ownSecretsIDList = new List<string>();
  93. public int enemySecretCount = 0;
  94. public int ownHeroHp = 30;
  95. public int ownheroAngr = 0;
  96. public int enemyheroAngr = 0;
  97. public bool ownHeroFrozen = false;
  98. public bool enemyHeroFrozen = false;
  99. public bool heroImmuneWhileAttacking = false;
  100. public bool enemyheroImmuneWhileAttacking = false;
  101. public bool heroImmune = false;
  102. public bool enemyHeroImmune = false;
  103. public int ownWeaponDurability = 0;
  104. public int ownWeaponAttack = 0;
  105. public string ownWeaponName = "";
  106. public string enemyWeaponName = "";
  107. public int enemyWeaponAttack = 0;
  108. public int enemyWeaponDurability = 0;
  109. public List<Minion> ownMinions = new List<Minion>();
  110. public List<Minion> enemyMinions = new List<Minion>();
  111. public List<Handmanager.Handcard> owncards = new List<Handmanager.Handcard>();
  112. public List<Action> playactions = new List<Action>();
  113. public bool complete = false;
  114. public int owncarddraw = 0;
  115. public int ownHeroDefence = 0;
  116. public int enemycarddraw = 0;
  117. public int enemyAnzCards = 0;
  118. public int enemyHeroDefence = 0;
  119. public int doublepriest = 0;
  120. public int spellpower = 0;
  121. public bool auchenaiseelenpriesterin = false;
  122. public bool ownBaronRivendare = false;
  123. public bool enemyBaronRivendare = false;
  124. public bool playedmagierinderkirintor = false;
  125. public bool playedPreparation = false;
  126. public int winzigebeschwoererin = 0;
  127. public int startedWithWinzigebeschwoererin = 0;
  128. public int zauberlehrling = 0;
  129. public int startedWithZauberlehrling = 0;
  130. public int managespenst = 0;
  131. public int startedWithManagespenst = 0;
  132. public int soeldnerDerVenture = 0;
  133. public int startedWithsoeldnerDerVenture = 0;
  134. public int beschwoerungsportal = 0;
  135. public int startedWithbeschwoerungsportal = 0;
  136. public int ownWeaponAttackStarted = 0;
  137. public int ownMobsCountStarted = 0;
  138. public int ownCardsCountStarted = 0;
  139. public int ownHeroHpStarted = 30;
  140. public int enemyHeroHpStarted = 30;
  141. public int mobsplayedThisTurn = 0;
  142. public int startedWithMobsPlayedThisTurn = 0;
  143. public int cardsPlayedThisTurn = 0;
  144. public int ueberladung = 0; //=recall
  145. public int ownMaxMana = 0;
  146. public int enemyMaxMana = 0;
  147. public int lostDamage = 0;
  148. public int lostHeal = 0;
  149. public int lostWeaponDamage = 0;
  150. public int ownDeckSize = 30;
  151. public int enemyDeckSize = 30;
  152. public int ownHeroFatigue = 0;
  153. public int enemyHeroFatigue = 0;
  154. public bool ownAbilityReady = false;
  155. public CardDB.Card ownHeroAblility;
  156. public bool enemyAbilityReady = false;
  157. public CardDB.Card enemyHeroAblility;
  158. //Helpfunctions help = Helpfunctions.Instance;
  159. private void addMinionsReal(List<Minion> source, List<Minion> trgt)
  160. {
  161. foreach (Minion m in source)
  162. {
  163. trgt.Add(new Minion(m));
  164. }
  165. }
  166. private void addCardsReal(List<Handmanager.Handcard> source)
  167. {
  168. foreach (Handmanager.Handcard m in source)
  169. {
  170. this.owncards.Add(new Handmanager.Handcard(m));
  171. }
  172. }
  173. public Playfield()
  174. {
  175. //this.simulateEnemyTurn = Ai.Instance.simulateEnemyTurn;
  176. this.ownController = Hrtprozis.Instance.getOwnController();
  177. this.ownHeroEntity = Hrtprozis.Instance.ownHeroEntity;
  178. this.enemyHeroEntity = Hrtprozis.Instance.enemyHeroEntitiy;
  179. this.mana = Hrtprozis.Instance.currentMana;
  180. this.ownMaxMana = Hrtprozis.Instance.ownMaxMana;
  181. this.enemyMaxMana = Hrtprozis.Instance.enemyMaxMana;
  182. this.evaluatePenality = 0;
  183. this.ownSecretsIDList = Hrtprozis.Instance.ownSecretList;
  184. this.enemySecretCount = Hrtprozis.Instance.enemySecretCount;
  185. this.heroImmune = Hrtprozis.Instance.heroImmune;
  186. this.enemyHeroImmune = Hrtprozis.Instance.enemyHeroImmune;
  187. this.attackFaceHP = Hrtprozis.Instance.attackFaceHp;
  188. addMinionsReal(Hrtprozis.Instance.ownMinions, ownMinions);
  189. addMinionsReal(Hrtprozis.Instance.enemyMinions, enemyMinions);
  190. addCardsReal(Handmanager.Instance.handCards);
  191. this.enemyHeroHp = Hrtprozis.Instance.enemyHp;
  192. this.ownHeroName = Hrtprozis.Instance.heroname;
  193. this.enemyHeroName = Hrtprozis.Instance.enemyHeroname;
  194. this.ownHeroHp = Hrtprozis.Instance.heroHp;
  195. this.complete = false;
  196. this.ownHeroReady = Hrtprozis.Instance.ownheroisread;
  197. this.ownHeroWindfury = Hrtprozis.Instance.ownHeroWindfury;
  198. this.ownHeroNumAttackThisTurn = Hrtprozis.Instance.ownHeroNumAttacksThisTurn;
  199. this.ownHeroFrozen = Hrtprozis.Instance.herofrozen;
  200. this.enemyHeroFrozen = Hrtprozis.Instance.enemyfrozen;
  201. this.ownheroAngr = Hrtprozis.Instance.heroAtk;
  202. this.heroImmuneWhileAttacking = Hrtprozis.Instance.heroImmuneToDamageWhileAttacking;
  203. this.ownWeaponDurability = Hrtprozis.Instance.heroWeaponDurability;
  204. this.ownWeaponAttack = Hrtprozis.Instance.heroWeaponAttack;
  205. this.ownWeaponName = Hrtprozis.Instance.ownHeroWeapon;
  206. this.owncarddraw = 0;
  207. this.ownHeroDefence = Hrtprozis.Instance.heroDefence;
  208. this.enemyHeroDefence = Hrtprozis.Instance.enemyDefence;
  209. this.enemyWeaponAttack = Hrtprozis.Instance.enemyWeaponAttack;//dont know jet
  210. this.enemyWeaponName = Hrtprozis.Instance.enemyHeroWeapon;
  211. this.enemyWeaponDurability = Hrtprozis.Instance.enemyWeaponDurability;
  212. this.enemycarddraw = 0;
  213. this.enemyAnzCards = Handmanager.Instance.enemyAnzCards;
  214. this.ownAbilityReady = Hrtprozis.Instance.ownAbilityisReady;
  215. this.ownHeroAblility = Hrtprozis.Instance.heroAbility;
  216. this.enemyHeroAblility = Hrtprozis.Instance.enemyAbility;
  217. this.doublepriest = 0;
  218. this.spellpower = 0;
  219. this.mobsplayedThisTurn = Hrtprozis.Instance.numMinionsPlayedThisTurn;
  220. this.startedWithMobsPlayedThisTurn = Hrtprozis.Instance.numMinionsPlayedThisTurn;// only change mobsplayedthisturm
  221. this.cardsPlayedThisTurn = Hrtprozis.Instance.cardsPlayedThisTurn;
  222. this.ueberladung = Hrtprozis.Instance.ueberladung;
  223. this.ownHeroFatigue = Hrtprozis.Instance.ownHeroFatigue;
  224. this.enemyHeroFatigue = Hrtprozis.Instance.enemyHeroFatigue;
  225. this.ownDeckSize = Hrtprozis.Instance.ownDeckSize;
  226. this.enemyDeckSize = Hrtprozis.Instance.enemyDeckSize;
  227. //need the following for manacost-calculation
  228. this.ownHeroHpStarted = this.ownHeroHp;
  229. this.enemyHeroHpStarted = this.enemyHeroHp;
  230. this.ownWeaponAttackStarted = this.ownWeaponAttack;
  231. this.ownCardsCountStarted = this.owncards.Count;
  232. this.ownMobsCountStarted = this.ownMinions.Count + this.enemyMinions.Count;
  233. this.playedmagierinderkirintor = false;
  234. this.playedPreparation = false;
  235. this.zauberlehrling = 0;
  236. this.winzigebeschwoererin = 0;
  237. this.managespenst = 0;
  238. this.soeldnerDerVenture = 0;
  239. this.beschwoerungsportal = 0;
  240. this.startedWithbeschwoerungsportal = 0;
  241. this.startedWithManagespenst = 0;
  242. this.startedWithWinzigebeschwoererin = 0;
  243. this.startedWithZauberlehrling = 0;
  244. this.startedWithsoeldnerDerVenture = 0;
  245. this.ownBaronRivendare = false;
  246. this.enemyBaronRivendare = false;
  247. foreach (Minion m in this.ownMinions)
  248. {
  249. if (m.silenced) continue;
  250. if (m.name == "prophetvelen") this.doublepriest++;
  251. spellpower = spellpower + m.handcard.card.spellpowervalue;
  252. if (m.name == "auchenaisoulpriest") this.auchenaiseelenpriesterin = true;
  253. if (m.name == "pint-sizedsummoner")
  254. {
  255. this.winzigebeschwoererin++;
  256. this.startedWithWinzigebeschwoererin++;
  257. }
  258. if (m.name == "sorcerersapprentice")
  259. {
  260. this.zauberlehrling++;
  261. this.startedWithZauberlehrling++;
  262. }
  263. if (m.name == "manawraith")
  264. {
  265. this.managespenst++;
  266. this.startedWithManagespenst++;
  267. }
  268. if (m.name == "venturecomercenary")
  269. {
  270. this.soeldnerDerVenture++;
  271. this.startedWithsoeldnerDerVenture++;
  272. }
  273. if (m.name == "summoningportal")
  274. {
  275. this.beschwoerungsportal++;
  276. this.startedWithbeschwoerungsportal++;
  277. }
  278. if (m.handcard.card.specialMin == CardDB.specialMinions.baronrivendare)
  279. {
  280. this.ownBaronRivendare = true;
  281. }
  282. foreach (Enchantment e in m.enchantments)// only at first init needed, after that its copied
  283. {
  284. if (e.CARDID == "NEW1_036e" || e.CARDID == "NEW1_036e2") m.cantLowerHPbelowONE = true;
  285. }
  286. }
  287. foreach (Minion m in this.enemyMinions)
  288. {
  289. if (m.silenced) continue;
  290. if (m.name == "manawraith")
  291. {
  292. this.managespenst++;
  293. this.startedWithManagespenst++;
  294. }
  295. if (m.handcard.card.specialMin == CardDB.specialMinions.baronrivendare)
  296. {
  297. this.enemyBaronRivendare = true;
  298. }
  299. }
  300. }
  301. public Playfield(Playfield p)
  302. {
  303. this.sEnemTurn = p.sEnemTurn;
  304. this.ownController = p.ownController;
  305. this.ownHeroEntity = p.ownHeroEntity;
  306. this.enemyHeroEntity = p.enemyHeroEntity;
  307. this.evaluatePenality = p.evaluatePenality;
  308. foreach(string s in p.ownSecretsIDList)
  309. { this.ownSecretsIDList.Add(s); }
  310. this.enemySecretCount = p.enemySecretCount;
  311. this.mana = p.mana;
  312. this.ownMaxMana = p.ownMaxMana;
  313. this.enemyMaxMana = p.enemyMaxMana;
  314. addMinionsReal(p.ownMinions, ownMinions);
  315. addMinionsReal(p.enemyMinions, enemyMinions);
  316. addCardsReal(p.owncards);
  317. this.enemyHeroHp = p.enemyHeroHp;
  318. this.ownHeroName = p.ownHeroName;
  319. this.enemyHeroName = p.enemyHeroName;
  320. this.ownHeroHp = p.ownHeroHp;
  321. this.playactions.AddRange(p.playactions);
  322. this.complete = false;
  323. this.ownHeroReady = p.ownHeroReady;
  324. this.enemyHeroReady = p.enemyHeroReady;
  325. this.ownHeroNumAttackThisTurn = p.ownHeroNumAttackThisTurn;
  326. this.enemyHeroNumAttackThisTurn = p.enemyHeroNumAttackThisTurn;
  327. this.ownHeroWindfury = p.ownHeroWindfury;
  328. this.attackFaceHP = p.attackFaceHP;
  329. this.heroImmune = p.heroImmune;
  330. this.enemyHeroImmune = p.enemyHeroImmune;
  331. this.ownheroAngr = p.ownheroAngr;
  332. this.enemyheroAngr = p.enemyheroAngr;
  333. this.ownHeroFrozen = p.ownHeroFrozen;
  334. this.enemyHeroFrozen = p.enemyHeroFrozen;
  335. this.heroImmuneWhileAttacking = p.heroImmuneWhileAttacking;
  336. this.enemyheroImmuneWhileAttacking = p.enemyheroImmuneWhileAttacking;
  337. this.owncarddraw = p.owncarddraw;
  338. this.ownHeroDefence = p.ownHeroDefence;
  339. this.enemyWeaponAttack = p.enemyWeaponAttack;
  340. this.enemyWeaponDurability = p.enemyWeaponDurability;
  341. this.enemyWeaponName = p.enemyWeaponName;
  342. this.enemycarddraw = p.enemycarddraw;
  343. this.enemyAnzCards = p.enemyAnzCards;
  344. this.enemyHeroDefence = p.enemyHeroDefence;
  345. this.ownWeaponDurability = p.ownWeaponDurability;
  346. this.ownWeaponAttack = p.ownWeaponAttack;
  347. this.ownWeaponName = p.ownWeaponName;
  348. this.lostDamage = p.lostDamage;
  349. this.lostWeaponDamage = p.lostWeaponDamage;
  350. this.lostHeal = p.lostHeal;
  351. this.ownAbilityReady = p.ownAbilityReady;
  352. this.enemyAbilityReady = p.enemyAbilityReady;
  353. this.ownHeroAblility = p.ownHeroAblility;
  354. this.enemyHeroAblility = p.enemyHeroAblility;
  355. this.doublepriest = 0;
  356. this.spellpower = 0;
  357. this.mobsplayedThisTurn = p.mobsplayedThisTurn;
  358. this.startedWithMobsPlayedThisTurn = p.startedWithMobsPlayedThisTurn;
  359. this.cardsPlayedThisTurn = p.cardsPlayedThisTurn;
  360. this.ueberladung = p.ueberladung;
  361. this.ownDeckSize = p.ownDeckSize;
  362. this.enemyDeckSize = p.enemyDeckSize;
  363. this.ownHeroFatigue = p.ownHeroFatigue;
  364. this.enemyHeroFatigue = p.enemyHeroFatigue;
  365. //need the following for manacost-calculation
  366. this.ownHeroHpStarted = p.ownHeroHpStarted;
  367. this.enemyHeroHp = p.enemyHeroHp;
  368. this.ownWeaponAttackStarted = p.ownWeaponAttackStarted;
  369. this.ownCardsCountStarted = p.ownCardsCountStarted;
  370. this.ownMobsCountStarted = p.ownMobsCountStarted;
  371. this.startedWithWinzigebeschwoererin = p.startedWithWinzigebeschwoererin;
  372. this.playedmagierinderkirintor = p.playedmagierinderkirintor;
  373. this.startedWithZauberlehrling = p.startedWithZauberlehrling;
  374. this.startedWithWinzigebeschwoererin = p.startedWithWinzigebeschwoererin;
  375. this.startedWithManagespenst = p.startedWithManagespenst;
  376. this.startedWithsoeldnerDerVenture = p.startedWithsoeldnerDerVenture;
  377. this.startedWithbeschwoerungsportal = p.startedWithbeschwoerungsportal;
  378. this.ownBaronRivendare = false;
  379. this.enemyBaronRivendare = false;
  380. this.zauberlehrling = 0;
  381. this.winzigebeschwoererin = 0;
  382. this.managespenst = 0;
  383. this.soeldnerDerVenture = 0;
  384. foreach (Minion m in this.ownMinions)
  385. {
  386. if (m.silenced) continue;
  387. if (m.handcard.card.specialMin == CardDB.specialMinions.prophetvelen) this.doublepriest++;
  388. spellpower = spellpower + m.handcard.card.spellpowervalue;
  389. if (m.handcard.card.specialMin == CardDB.specialMinions.auchenaisoulpriest) this.auchenaiseelenpriesterin = true;
  390. if (m.handcard.card.specialMin == CardDB.specialMinions.pintsizedsummoner) this.winzigebeschwoererin++;
  391. if (m.handcard.card.specialMin == CardDB.specialMinions.sorcerersapprentice) this.zauberlehrling++;
  392. if (m.handcard.card.specialMin == CardDB.specialMinions.manawraith) this.managespenst++;
  393. if (m.handcard.card.specialMin == CardDB.specialMinions.venturecomercenary) this.soeldnerDerVenture++;
  394. if (m.handcard.card.specialMin == CardDB.specialMinions.summoningportal) this.beschwoerungsportal++;
  395. if (m.handcard.card.specialMin == CardDB.specialMinions.baronrivendare)
  396. {
  397. this.ownBaronRivendare = true;
  398. }
  399. }
  400. foreach (Minion m in this.enemyMinions)
  401. {
  402. if (m.silenced) continue;
  403. if (m.handcard.card.specialMin == CardDB.specialMinions.manawraith) this.managespenst++;
  404. if (m.handcard.card.specialMin == CardDB.specialMinions.baronrivendare)
  405. {
  406. this.enemyBaronRivendare = true;
  407. }
  408. }
  409. }
  410. public bool isEqual(Playfield p, bool logg)
  411. {
  412. if (logg)
  413. {
  414. if (this.value != p.value) return false;
  415. }
  416. if (this.enemySecretCount != p.enemySecretCount)
  417. {
  418. if(logg) Helpfunctions.Instance.logg("enemy secrets changed ");
  419. return false;
  420. }
  421. if (this.mana != p.mana || this.enemyMaxMana != p.enemyMaxMana || this.ownMaxMana != p.ownMaxMana)
  422. {
  423. if (logg) Helpfunctions.Instance.logg("mana changed " + this.mana + " " + p.mana + " " + this.enemyMaxMana + " " + p.enemyMaxMana + " " + this.ownMaxMana + " " + p.ownMaxMana);
  424. return false;
  425. }
  426. if (this.ownDeckSize != p.ownDeckSize || this.enemyDeckSize != p.enemyDeckSize || this.ownHeroFatigue != p.ownHeroFatigue || this.enemyHeroFatigue != p.enemyHeroFatigue)
  427. {
  428. if (logg) Helpfunctions.Instance.logg("deck/fatigue changed " + this.ownDeckSize + " " + p.ownDeckSize + " " + this.enemyDeckSize + " " + p.enemyDeckSize + " " + this.ownHeroFatigue + " " + p.ownHeroFatigue + " " + this.enemyHeroFatigue + " " + p.enemyHeroFatigue);
  429. }
  430. if (this.cardsPlayedThisTurn != p.cardsPlayedThisTurn || this.mobsplayedThisTurn != p.mobsplayedThisTurn || this.ueberladung != p.ueberladung)
  431. {
  432. if (logg) Helpfunctions.Instance.logg("stuff changed " + this.cardsPlayedThisTurn + " " + p.cardsPlayedThisTurn + " " + this.mobsplayedThisTurn + " " + p.mobsplayedThisTurn + " " + this.ueberladung + " " + p.ueberladung);
  433. return false;
  434. }
  435. if (this.ownHeroName != p.ownHeroName || this.enemyHeroName != p.enemyHeroName)
  436. {
  437. if (logg) Helpfunctions.Instance.logg("hero name changed ");
  438. return false;
  439. }
  440. if (this.ownHeroHp != p.ownHeroHp || this.ownheroAngr != p.ownheroAngr || this.ownHeroDefence != p.ownHeroDefence || this.ownHeroFrozen != p.ownHeroFrozen || this.heroImmuneWhileAttacking != p.heroImmuneWhileAttacking || this.heroImmune!=p.heroImmune)
  441. {
  442. if (logg) Helpfunctions.Instance.logg("ownhero changed " + this.ownHeroHp + " " + p.ownHeroHp + " " + this.ownheroAngr + " " + p.ownheroAngr + " " + this.ownHeroDefence + " " + p.ownHeroDefence + " " + this.ownHeroFrozen + " " + p.ownHeroFrozen + " " + this.heroImmuneWhileAttacking + " " + p.heroImmuneWhileAttacking + " " + this.heroImmune + " " + p.heroImmune);
  443. return false;
  444. }
  445. if (this.ownHeroReady != p.ownHeroReady || this.ownWeaponAttack != p.ownWeaponAttack || this.ownWeaponDurability != p.ownWeaponDurability || this.ownHeroNumAttackThisTurn != p.ownHeroNumAttackThisTurn || this.ownHeroWindfury != p.ownHeroWindfury)
  446. {
  447. if (logg) Helpfunctions.Instance.logg("weapon changed " + this.ownHeroReady + " " + p.ownHeroReady + " " + this.ownWeaponAttack + " " + p.ownWeaponAttack + " " + this.ownWeaponDurability + " " + p.ownWeaponDurability + " " + this.ownHeroNumAttackThisTurn + " " + p.ownHeroNumAttackThisTurn + " " + this.ownHeroWindfury + " " + p.ownHeroWindfury);
  448. return false;
  449. }
  450. if (this.enemyHeroHp != p.enemyHeroHp || this.enemyWeaponAttack != p.enemyWeaponAttack || this.enemyHeroDefence != p.enemyHeroDefence || this.enemyWeaponDurability != p.enemyWeaponDurability || this.enemyHeroFrozen != p.enemyHeroFrozen || this.enemyHeroImmune != p.enemyHeroImmune)
  451. {
  452. if (logg) Helpfunctions.Instance.logg("enemyhero changed " + this.enemyHeroHp + " " + p.enemyHeroHp + " " + this.enemyWeaponAttack + " " + p.enemyWeaponAttack + " " + this.enemyHeroDefence + " " + p.enemyHeroDefence + " " + this.enemyWeaponDurability + " " + p.enemyWeaponDurability + " " + this.enemyHeroFrozen + " " + p.enemyHeroFrozen + " " + this.enemyHeroImmune + " " + p.enemyHeroImmune);
  453. return false;
  454. }
  455. /*if (this.auchenaiseelenpriesterin != p.auchenaiseelenpriesterin || this.winzigebeschwoererin != p.winzigebeschwoererin || this.zauberlehrling != p.zauberlehrling || this.managespenst != p.managespenst || this.soeldnerDerVenture != p.soeldnerDerVenture || this.beschwoerungsportal != p.beschwoerungsportal || this.doublepriest != p.doublepriest)
  456. {
  457. Helpfunctions.Instance.logg("special minions changed " + this.auchenaiseelenpriesterin + " " + p.auchenaiseelenpriesterin + " " + this.winzigebeschwoererin + " " + p.winzigebeschwoererin + " " + this.zauberlehrling + " " + p.zauberlehrling + " " + this.managespenst + " " + p.managespenst + " " + this.soeldnerDerVenture + " " + p.soeldnerDerVenture + " " + this.beschwoerungsportal + " " + p.beschwoerungsportal + " " + this.doublepriest + " " + p.doublepriest);
  458. return false;
  459. }*/
  460. if (this.ownHeroAblility.name != p.ownHeroAblility.name)
  461. {
  462. if (logg) Helpfunctions.Instance.logg("hero ability changed ");
  463. return false;
  464. }
  465. if (this.spellpower != p.spellpower)
  466. {
  467. if (logg) Helpfunctions.Instance.logg("spellpower changed");
  468. return false;
  469. }
  470. if (this.ownMinions.Count != p.ownMinions.Count || this.enemyMinions.Count != p.enemyMinions.Count || this.owncards.Count != p.owncards.Count)
  471. {
  472. if (logg) Helpfunctions.Instance.logg("minions count or hand changed");
  473. return false;
  474. }
  475. bool minionbool = true;
  476. for (int i = 0; i < this.ownMinions.Count; i++)
  477. {
  478. Minion dis = this.ownMinions[i]; Minion pis = p.ownMinions[i];
  479. //if (dis.entitiyID == 0) dis.entitiyID = pis.entitiyID;
  480. //if (pis.entitiyID == 0) pis.entitiyID = dis.entitiyID;
  481. if (dis.entitiyID != pis.entitiyID) minionbool= false;
  482. if (dis.Angr != pis.Angr || dis.Hp != pis.Hp || dis.maxHp != pis.maxHp || dis.numAttacksThisTurn != pis.numAttacksThisTurn) minionbool = false;
  483. if (dis.Ready != pis.Ready) minionbool = false; // includes frozen, exhaunted
  484. if (dis.playedThisTurn != pis.playedThisTurn || dis.numAttacksThisTurn != pis.numAttacksThisTurn) minionbool = false;
  485. if (dis.silenced != pis.silenced || dis.stealth != pis.stealth || dis.taunt != pis.taunt || dis.windfury != pis.windfury || dis.wounded != pis.wounded || dis.zonepos != pis.zonepos) minionbool = false;
  486. if (dis.divineshild != pis.divineshild || dis.cantLowerHPbelowONE != pis.cantLowerHPbelowONE || dis.immune != pis.immune) minionbool = false;
  487. }
  488. if (minionbool == false)
  489. {
  490. if (logg) Helpfunctions.Instance.logg("ownminions changed");
  491. return false;
  492. }
  493. for (int i = 0; i < this.enemyMinions.Count; i++)
  494. {
  495. Minion dis = this.enemyMinions[i]; Minion pis = p.enemyMinions[i];
  496. //if (dis.entitiyID == 0) dis.entitiyID = pis.entitiyID;
  497. //if (pis.entitiyID == 0) pis.entitiyID = dis.entitiyID;
  498. if (dis.entitiyID != pis.entitiyID) minionbool = false;
  499. if (dis.Angr != pis.Angr || dis.Hp != pis.Hp || dis.maxHp != pis.maxHp || dis.numAttacksThisTurn != pis.numAttacksThisTurn) minionbool = false;
  500. if (dis.Ready != pis.Ready) minionbool = false; // includes frozen, exhaunted
  501. if (dis.playedThisTurn != pis.playedThisTurn || dis.numAttacksThisTurn != pis.numAttacksThisTurn) minionbool = false;
  502. if (dis.silenced != pis.silenced || dis.stealth != pis.stealth || dis.taunt != pis.taunt || dis.windfury != pis.windfury || dis.wounded != pis.wounded || dis.zonepos != pis.zonepos) minionbool = false;
  503. if (dis.divineshild != pis.divineshild || dis.cantLowerHPbelowONE != pis.cantLowerHPbelowONE || dis.immune != pis.immune) minionbool = false;
  504. }
  505. if (minionbool == false)
  506. {
  507. if (logg) Helpfunctions.Instance.logg("enemyminions changed");
  508. return false;
  509. }
  510. for (int i = 0; i < this.owncards.Count; i++)
  511. {
  512. Handmanager.Handcard dishc = this.owncards[i]; Handmanager.Handcard pishc = p.owncards[i];
  513. if ( dishc.position != pishc.position || dishc.entity != pishc.entity || dishc.getManaCost(this) != pishc.getManaCost(p))
  514. {
  515. if (logg) Helpfunctions.Instance.logg("handcard changed: " + dishc.card.name);
  516. return false;
  517. }
  518. }
  519. return true;
  520. }
  521. public void simulateEnemysTurn()
  522. {
  523. int maxwide = 20;
  524. this.enemyAbilityReady = true;
  525. this.enemyHeroNumAttackThisTurn = 0;
  526. this.enemyHeroWindfury = false;
  527. if (this.enemyWeaponName == "doomhammer") this.enemyHeroWindfury = true;
  528. this.enemyheroImmuneWhileAttacking = false;
  529. if (this.enemyWeaponName == "gladiatorslongbow") this.enemyheroImmuneWhileAttacking = true;
  530. if (!this.enemyHeroFrozen && this.enemyWeaponDurability > 0) this.enemyHeroReady = true;
  531. this.enemyheroAngr = this.enemyWeaponAttack;
  532. bool havedonesomething = true;
  533. List<Playfield> posmoves = new List<Playfield>();
  534. posmoves.Add(new Playfield(this));
  535. List<Playfield> temp = new List<Playfield>();
  536. int deep = 0;
  537. while (havedonesomething)
  538. {
  539. temp.Clear();
  540. temp.AddRange(posmoves);
  541. havedonesomething = false;
  542. Playfield bestold = null;
  543. int bestoldval = 20000000;
  544. foreach (Playfield p in temp)
  545. {
  546. if (p.complete)
  547. {
  548. continue;
  549. }
  550. List<Minion> playedMinions = new List<Minion>(8);
  551. foreach (Minion m in p.enemyMinions)
  552. {
  553. if (m.Ready && m.Angr >= 1 && !m.frozen)
  554. {
  555. //BEGIN:cut (double/similar) attacking minions out#####################################
  556. // DONT LET SIMMILAR MINIONS ATTACK IN ONE TURN (example 3 unlesh the hounds-hounds doesnt need to simulated hole)
  557. List<Minion> tempoo = new List<Minion>(playedMinions);
  558. bool dontattacked = true;
  559. bool isSpecial = PenalityManager.Instance.specialMinions.ContainsKey(m.name);
  560. foreach (Minion mnn in tempoo)
  561. {
  562. // special minions are allowed to attack in silended and unsilenced state!
  563. //help.logg(mnn.silenced + " " + m.silenced + " " + mnn.name + " " + m.name + " " + penman.specialMinions.ContainsKey(m.name));
  564. bool otherisSpecial = PenalityManager.Instance.specialMinions.ContainsKey(mnn.name);
  565. if ((!isSpecial || (isSpecial && m.silenced)) && (!otherisSpecial || (otherisSpecial && mnn.silenced))) // both are not special, if they are the same, dont add
  566. {
  567. if (mnn.Angr == m.Angr && mnn.Hp == m.Hp && mnn.divineshild == m.divineshild && mnn.taunt == m.taunt && mnn.poisonous == m.poisonous) dontattacked = false;
  568. continue;
  569. }
  570. if (isSpecial == otherisSpecial && !m.silenced && !mnn.silenced) // same are special
  571. {
  572. if (m.name != mnn.name) // different name -> take it
  573. {
  574. continue;
  575. }
  576. // same name -> test whether they are equal
  577. if (mnn.Angr == m.Angr && mnn.Hp == m.Hp && mnn.divineshild == m.divineshild && mnn.taunt == m.taunt && mnn.poisonous == m.poisonous) dontattacked = false;
  578. continue;
  579. }
  580. }
  581. if (dontattacked)
  582. {
  583. playedMinions.Add(m);
  584. }
  585. else
  586. {
  587. //help.logg(m.name + " doesnt need to attack!");
  588. continue;
  589. }
  590. //END: cut (double/similar) attacking minions out#####################################
  591. //help.logg(m.name + " is going to attack!");
  592. List<targett> trgts = p.getAttackTargets(false);
  593. if (true)//(this.useCutingTargets)
  594. {
  595. trgts = Ai.Instance.cutAttackTargets(trgts, p, false);
  596. }
  597. foreach (targett trgt in trgts)
  598. {
  599. Playfield pf = new Playfield(p);
  600. havedonesomething = true;
  601. pf.ENEMYattackWithMinion(m, trgt.target, trgt.targetEntity);
  602. posmoves.Add(pf);
  603. }
  604. if (trgts.Count == 1 && trgts[0].target == 100)//only enemy hero is available als attack
  605. {
  606. break;
  607. }
  608. }
  609. }
  610. // attacked with minions done
  611. // attack with hero
  612. if (p.enemyHeroReady)
  613. {
  614. List<targett> trgts = p.getAttackTargets(false);
  615. havedonesomething = true;
  616. if (true)//(this.useCutingTargets)
  617. {
  618. trgts = Ai.Instance.cutAttackTargets(trgts, p, false);
  619. }
  620. foreach (targett trgt in trgts)
  621. {
  622. Playfield pf = new Playfield(p);
  623. pf.ENEMYattackWithWeapon(trgt.target, trgt.targetEntity, 0);
  624. posmoves.Add(pf);
  625. }
  626. }
  627. // use ability
  628. /// TODO check if ready after manaup
  629. if (p.enemyAbilityReady && p.enemyHeroAblility.canplayCard(p, 0))
  630. {
  631. int abilityPenality = 0;
  632. havedonesomething = true;
  633. // if we have mage or priest, we have to target something####################################################
  634. if (p.enemyHeroName == HeroEnum.mage || p.enemyHeroName == HeroEnum.priest)
  635. {
  636. List<targett> trgts = p.enemyHeroAblility.getTargetsForCard(p);
  637. foreach (targett trgt in trgts)
  638. {
  639. Playfield pf = new Playfield(p);
  640. havedonesomething = true;
  641. pf.ENEMYactivateAbility(p.enemyHeroAblility, trgt.target, trgt.targetEntity);
  642. posmoves.Add(pf);
  643. }
  644. }
  645. else
  646. {
  647. // the other classes dont have to target####################################################
  648. Playfield pf = new Playfield(p);
  649. havedonesomething = true;
  650. pf.ENEMYactivateAbility(p.enemyHeroAblility, -1, -1);
  651. posmoves.Add(pf);
  652. }
  653. }
  654. p.endEnemyTurn();
  655. if (Ai.Instance.botBase.getPlayfieldValue(p) < bestoldval) // want the best enemy-play-> worst for us
  656. {
  657. bestoldval = Ai.Instance.botBase.getPlayfieldValue(p);
  658. bestold = p;
  659. }
  660. posmoves.Remove(p);
  661. if (posmoves.Count >= maxwide) break;
  662. }
  663. if ( bestoldval <= 10000 && bestold != null)
  664. {
  665. posmoves.Add(bestold);
  666. }
  667. deep++;
  668. if (posmoves.Count >= maxwide) break;
  669. }
  670. foreach (Playfield p in posmoves)
  671. {
  672. if (!p.complete) p.endEnemyTurn();
  673. }
  674. int bestval = int.MaxValue;
  675. Playfield bestplay = posmoves[0];
  676. foreach (Playfield p in posmoves)
  677. {
  678. int val = Ai.Instance.botBase.getPlayfieldValue(p);
  679. if (bestval > val)// we search the worst value
  680. {
  681. bestplay = p;
  682. bestval = val;
  683. }
  684. }
  685. this.value = bestplay.value;
  686. }
  687. public void prepareNextTurn()
  688. {
  689. this.ownMaxMana = Math.Min(10, this.ownMaxMana + 1);
  690. this.mana = this.ownMaxMana - this.ueberladung;
  691. foreach (Minion m in ownMinions)
  692. {
  693. m.Ready = true;
  694. m.numAttacksThisTurn = 0;
  695. m.playedThisTurn = false;
  696. }
  697. if (this.ownWeaponName != "") this.ownHeroReady = true;
  698. this.ownheroAngr = this.ownWeaponAttack;
  699. this.ownHeroFrozen = false;
  700. this.ownAbilityReady = true;
  701. this.complete = false;
  702. this.sEnemTurn = false;
  703. this.value = int.MinValue;
  704. }
  705. public List<targett> getAttackTargets(bool own)
  706. {
  707. List<targett> trgts = new List<targett>();
  708. List<targett> trgts2 = new List<targett>();
  709. bool hastanks = false;
  710. if (own)
  711. {
  712. trgts2.Add(new targett(200, this.enemyHeroEntity));
  713. foreach (Minion m in this.enemyMinions)
  714. {
  715. if (m.stealth) continue; // cant target stealth
  716. if (m.taunt)
  717. {
  718. hastanks = true;
  719. trgts.Add(new targett(m.id + 10, m.entitiyID));
  720. }
  721. else
  722. {
  723. trgts2.Add(new targett(m.id + 10, m.entitiyID));
  724. }
  725. }
  726. }
  727. else
  728. {
  729. foreach (Minion m in this.ownMinions)
  730. {
  731. if (m.stealth) continue; // cant target stealth
  732. if (m.taunt)
  733. {
  734. hastanks = true;
  735. trgts.Add(new targett(m.id, m.entitiyID));
  736. }
  737. else
  738. {
  739. trgts2.Add(new targett(m.id, m.entitiyID));
  740. }
  741. }
  742. if (trgts2.Count == 0) trgts2.Add(new targett(100, this.ownHeroEntity));
  743. }
  744. if (hastanks) return trgts;
  745. return trgts2;
  746. }
  747. public int getBestPlace(CardDB.Card card, bool lethal)
  748. {
  749. if (card.type != CardDB.cardtype.MOB) return 0;
  750. if (this.ownMinions.Count == 0) return 0;
  751. if (this.ownMinions.Count == 1) return 1;
  752. int[] places = new int[this.ownMinions.Count];
  753. int i = 0;
  754. int tempval = 0;
  755. if (lethal && card.specialMin == CardDB.specialMinions.defenderofargus)
  756. {
  757. i = 0;
  758. foreach (Minion m in this.ownMinions)
  759. {
  760. places[i] = 0;
  761. tempval = 0;
  762. if (m.Ready)
  763. {
  764. tempval -= m.Angr -1;
  765. if(m.windfury) tempval-=m.Angr -1;
  766. }
  767. places[i] = tempval;
  768. i++;
  769. }
  770. i = 0;
  771. int bestpl = 7;
  772. int bestval = 10000;
  773. foreach (Minion m in this.ownMinions)
  774. {
  775. int prev = 0;
  776. int next = 0;
  777. if (i >= 1) prev = places[i - 1];
  778. next = places[i];
  779. if (bestval > prev + next)
  780. {
  781. bestval = prev + next;
  782. bestpl = i;
  783. }
  784. i++;
  785. }
  786. return bestpl;
  787. }
  788. if (card.specialMin == CardDB.specialMinions.sunfuryprotector || card.specialMin == CardDB.specialMinions.defenderofargus) // bestplace, if right and left minions have no taunt + lots of hp, dont make priority-minions to taunt
  789. {
  790. i = 0;
  791. foreach (Minion m in this.ownMinions)
  792. {
  793. places[i] = 0;
  794. tempval = 0;
  795. if (!m.taunt)
  796. {
  797. tempval -= m.Hp;
  798. }
  799. else
  800. {
  801. tempval -= m.Hp+2;
  802. }
  803. if (m.handcard.card.specialMin == CardDB.specialMinions.flametonguetotem) tempval += 50;
  804. if (m.handcard.card.specialMin == CardDB.specialMinions.raidleader) tempval += 10;
  805. if (m.handcard.card.specialMin == CardDB.specialMinions.grimscaleoracle) tempval += 10;
  806. if (m.handcard.card.specialMin == CardDB.specialMinions.direwolfalpha) tempval += 50;
  807. if (m.handcard.card.specialMin == CardDB.specialMinions.murlocwarleader) tempval += 10;
  808. if (m.handcard.card.specialMin == CardDB.specialMinions.southseacaptain) tempval += 10;
  809. if (m.handcard.card.specialMin == CardDB.specialMinions.stormwindchampion) tempval += 10;
  810. if (m.handcard.card.specialMin == CardDB.specialMinions.timberwolf) tempval += 10;
  811. if (m.handcard.card.specialMin == CardDB.specialMinions.leokk) tempval += 10;
  812. if (m.handcard.card.specialMin == CardDB.specialMinions.northshirecleric) tempval += 10;
  813. if (m.handcard.card.specialMin == CardDB.specialMinions.sorcerersapprentice) tempval += 10;
  814. if (m.handcard.card.specialMin == CardDB.specialMinions.pintsizedsummoner) tempval += 10;
  815. if (m.handcard.card.specialMin == CardDB.specialMinions.summoningportal) tempval += 10;
  816. if (m.handcard.card.specialMin == CardDB.specialMinions.scavenginghyena) tempval += 10;
  817. places[i] = tempval;
  818. i++;
  819. }
  820. i = 0;
  821. int bestpl = 7;
  822. int bestval = 10000;
  823. foreach (Minion m in this.ownMinions)
  824. {
  825. int prev = 0;
  826. int next = 0;
  827. if (i >= 1) prev = places[i - 1];
  828. next = places[i];
  829. if(bestval > prev + next)
  830. {
  831. bestval = prev + next;
  832. bestpl = i;
  833. }
  834. i++;
  835. }
  836. return bestpl;
  837. }
  838. int cardIsBuffer = 0;
  839. bool placebuff = false;
  840. if (card.specialMin == CardDB.specialMinions.flametonguetotem || card.specialMin == CardDB.specialMinions.direwolfalpha)
  841. {
  842. placebuff = true;
  843. if (card.specialMin == CardDB.specialMinions.flametonguetotem) cardIsBuffer = 2;
  844. if (card.specialMin == CardDB.specialMinions.direwolfalpha) cardIsBuffer = 1;
  845. }
  846. bool commander = false;
  847. foreach (Minion m in this.ownMinions)
  848. {
  849. if (m.handcard.card.specialMin == CardDB.specialMinions.warsongcommander) commander = true;
  850. }
  851. foreach (Minion m in this.ownMinions)
  852. {
  853. if (m.handcard.card.specialMin == CardDB.specialMinions.flametonguetotem || m.handcard.card.specialMin == CardDB.specialMinions.direwolfalpha) placebuff = true;
  854. }
  855. //attackmaxing :D
  856. if (placebuff)
  857. {
  858. int cval = 0;
  859. if (card.Charge || (card.Attack <= 3 && commander))
  860. {
  861. cval = card.Attack;
  862. if (card.windfury) cval = card.Attack;
  863. }
  864. i = 0;
  865. int[] buffplaces = new int[this.ownMinions.Count];
  866. int gesval = 0;
  867. foreach (Minion m in this.ownMinions)
  868. {
  869. buffplaces[i] = 0;
  870. places[i] = 0;
  871. if (m.Ready)
  872. {
  873. tempval = m.Angr;
  874. if (m.windfury && m.numAttacksThisTurn == 0) tempval += m.Angr;
  875. }
  876. if (m.handcard.card.specialMin == CardDB.specialMinions.flametonguetotem )
  877. {
  878. buffplaces[i] = 2;
  879. }
  880. if (m.handcard.card.specialMin == CardDB.specialMinions.direwolfalpha)
  881. {
  882. buffplaces[i] = 1;
  883. }
  884. places[i] = tempval;
  885. gesval += tempval;
  886. i++;
  887. }
  888. int bplace = 0;
  889. int bvale = 0;
  890. tempval = 0;
  891. i = 0;
  892. for (int j = 0; j <= this.ownMinions.Count; j++)
  893. {
  894. tempval = gesval;
  895. int current = cval;
  896. int prev = 0;
  897. int next = 0;
  898. if (i >= 1)
  899. {
  900. tempval -= places[i - 1];
  901. prev = places[i - 1];
  902. prev+=cardIsBuffer;
  903. current+=buffplaces[i-1];
  904. if (i < this.ownMinions.Count)
  905. {
  906. prev -= buffplaces[i];
  907. }
  908. }
  909. if (i < this.ownMinions.Count)
  910. {
  911. tempval -= places[i];
  912. next = places[i];
  913. next += cardIsBuffer;
  914. current += buffplaces[i];
  915. if (i >= 1)
  916. {
  917. next -= buffplaces[i-1];
  918. }
  919. }
  920. tempval += current + prev + next;
  921. if (tempval > bvale)
  922. {
  923. bplace = i;
  924. bvale = tempval;
  925. }
  926. i++;
  927. }
  928. return bplace;
  929. }
  930. // normal placement
  931. int cardvalue = card.Attack * 2 + card.Health;
  932. if (card.tank)
  933. {
  934. cardvalue += 5;
  935. cardvalue += card.Health;
  936. }
  937. if (card.specialMin == CardDB.specialMinions.flametonguetotem) cardvalue += 90;
  938. if (card.specialMin == CardDB.specialMinions.raidleader) cardvalue += 10;
  939. if (card.specialMin == CardDB.specialMinions.grimscaleoracle) cardvalue += 10;
  940. if (card.specialMin == CardDB.specialMinions.direwolfalpha) cardvalue += 90;
  941. if (card.specialMin == CardDB.specialMinions.murlocwarleader) cardvalue += 10;
  942. if (card.specialMin == CardDB.specialMinions.southseacaptain) cardvalue += 10;
  943. if (card.specialMin == CardDB.specialMinions.stormwindchampion) cardvalue += 10;
  944. if (card.specialMin == CardDB.specialMinions.timberwolf) cardvalue += 10;
  945. if (card.specialMin == CardDB.specialMinions.leokk) cardvalue += 10;
  946. if (card.specialMin == CardDB.specialMinions.northshirecleric) cardvalue += 10;
  947. if (card.specialMin == CardDB.specialMinions.sorcerersapprentice) cardvalue += 10;
  948. if (card.specialMin == CardDB.specialMinions.pintsizedsummoner) cardvalue += 10;
  949. if (card.specialMin == CardDB.specialMinions.summoningportal) cardvalue += 10;
  950. if (card.specialMin == CardDB.specialMinions.scavenginghyena) cardvalue += 10;
  951. if (card.specialMin == CardDB.specialMinions.faeriedragon) cardvalue += 40;
  952. cardvalue += 1;
  953. i = 0;
  954. foreach(Minion m in this.ownMinions)
  955. {
  956. places[i] = 0;
  957. tempval = m.Angr * 2 + m.maxHp;
  958. if (m.taunt)
  959. {
  960. tempval += 6;
  961. tempval += m.maxHp;
  962. }
  963. if (!m.silenced)
  964. {
  965. if (m.handcard.card.specialMin == Car

Large files files are truncated, but you can click here to view the full file