93d98e04 by Barry

Finally have AI working. Started to add feral skills.

1 parent 840d3f95
No preview for this file type
...@@ -4,6 +4,7 @@ import pickle ...@@ -4,6 +4,7 @@ import pickle
4 import math 4 import math
5 import collections 5 import collections
6 import logging 6 import logging
7 import operator
7 8
8 def log(message): 9 def log(message):
9 try: 10 try:
...@@ -134,15 +135,20 @@ PhysicalDamageTypes = { ...@@ -134,15 +135,20 @@ PhysicalDamageTypes = {
134 } 135 }
135 136
136 FeralSkills = { 137 FeralSkills = {
137 'Airy Shield': {'fp_cost': 0, 'type': 'Enhancing', 'sub_type': 'arrow shield', 'shadows': 'ignore', 'range': None, 'aoe': False, 'spell': 'arrow shield'}, 138 # 'Airy Shield': {'fp_cost': 0, 'type': 'Enhancing', 'sub_type': 'arrow shield', 'shadows': 'ignore', 'range': None, 'aoe': False, 'spell': 'arrow shield'},
138 'Binding Wave': {'type': 'Enfeebling', 'shadows': 'ignore', 'range': 15, 'aoe': True, 'spell': 'bind'}, 139 # 'Binding Wave': {'type': 'Enfeebling', 'shadows': 'ignore', 'range': 15, 'aoe': True, 'spell': 'bind'},
139 'Dire Straight': {'type': 'Physical', 'shadows': 'wipe', 'range': None, 'aoe': False}, 140 # 'Dire Straight': {'type': 'Physical', 'shadows': 'wipe', 'range': None, 'aoe': False},
140 'Dismemberment': {'type': 'Piercing', 'shadows': 'absorb', 'range': None, 'aoe': False}, # causes the monster to lose a body part 141 # 'Dismemberment': {'type': 'Piercing', 'shadows': 'absorb', 'range': None, 'aoe': False}, # causes the monster to lose a body part
141 'Earthshatter': {'type': 'Piercing', 'shadows': 'wipe', 'range': None, 'aoe': True}, 142 # 'Earthshatter': {'type': 'Piercing', 'shadows': 'wipe', 'range': None, 'aoe': True},
142 'Eyes On Me': {'type': 'Magical', 'sub_type': 'Dark', 'mp_cost': 112, 'shadows': 'absorb', 'range': 13, 'aoe': False}, 143 # 'Eyes On Me': {'type': 'Magical', 'sub_type': 'Dark', 'mp_cost': 112, 'shadows': 'absorb', 'range': 13, 'aoe': False},
143 'Hypnosis': {'type': 'Enfeebling', 'sub_type': 'sleep', 'shadows': 'ignore', 'range': 'gaze', 'aoe': True}, 144 # 'Hypnosis': {'type': 'Enfeebling', 'sub_type': 'sleep', 'shadows': 'ignore', 'range': 'gaze', 'aoe': True},
144 'Magic Barrier': {'type': 'Magical', 'sub_type': 'Dark', 'mp_cost': 29, 'shadows': 'absorb', 'range': None, 'aoe': True}, 145 # 'Magic Barrier': {'type': 'Magical', 'sub_type': 'Dark', 'mp_cost': 29, 'shadows': 'absorb', 'range': None, 'aoe': True},
145 'Sinker Drill': {'type': 'Physical', 'sub_type': 'Piercing', 'shadows': 'absorb', 'range': None, 'aoe': False}, 146 # 'Sinker Drill': {'type': 'Physical', 'sub_type': 'Piercing', 'shadows': 'absorb', 'range': None, 'aoe': False},
147 'Accuracy +15%': {'fp_cost': 23, 'effect': 'acc', 'amount': 15, 'is_percent': True, 'expires_seconds': 0, 'levels': False},
148 'Accuracy +30%': {'fp_cost': 30, 'effect': 'acc', 'amount': 30, 'is_percent': True, 'expires_seconds': 0, 'levels': False},
149 'Accuracy Bonus': {'fp_cost': 30, 'effect': 'acc', 'amount': 15, 'is_percent': True, 'expires_seconds': 0, 'levels': True},
150 'AGI +25': {'fp_cost': 17, 'effect': 'agi', 'amount': 25, 'is_percent': False, 'expires_seconds': 0, 'levels': False},
151
146 } 152 }
147 153
148 class Spells: 154 class Spells:
...@@ -193,15 +199,17 @@ class Spells: ...@@ -193,15 +199,17 @@ class Spells:
193 'Banish III': {'mp_cost': 96, 'casting_time': 3, 'recast_time': 45, 'magic_acc_stat': 'mnd', 'spell_type': 't3', 'damage_type': 'light', 'jobs': {Jobs.WHM: 65} }, 199 'Banish III': {'mp_cost': 96, 'casting_time': 3, 'recast_time': 45, 'magic_acc_stat': 'mnd', 'spell_type': 't3', 'damage_type': 'light', 'jobs': {Jobs.WHM: 65} },
194 } 200 }
195 201
196 def get_spell_list(self, level, job = None, sub_job = None): 202 def get_spell_list(self, mp, level, job = None, support_job = None):
197 available_spells = [] 203 available_spells = []
198 for spell_name, spell in self.SpellList.iteritems(): 204 for spell_name, spell in self.SpellList.iteritems():
199 if job and job in spell['jobs'] and spell['jobs'][job] <= level: 205 if job and job in spell['jobs'] and spell['jobs'][job] <= level:
200 if spell_name not in available_spells: 206 if spell_name not in available_spells:
201 available_spells.append(spell_name) 207 if spell['mp_cost'] < mp:
202 if sub_job and sub_job in spell['jobs'] and spell['jobs'][sub_job] <= level / 2: 208 available_spells.append(spell_name)
209 if support_job and support_job in spell['jobs'] and spell['jobs'][support_job] <= level / 2:
203 if spell_name not in available_spells: 210 if spell_name not in available_spells:
204 available_spells.append(spell_name) 211 if spell['mp_cost'] < mp:
212 available_spells.append(spell_name)
205 return sorted(available_spells) 213 return sorted(available_spells)
206 214
207 def get_spell_data(self, spell): 215 def get_spell_data(self, spell):
...@@ -224,8 +232,9 @@ Families = { ...@@ -224,8 +232,9 @@ Families = {
224 'max_fp': 55, 232 'max_fp': 55,
225 'available_main_job': [Jobs.WAR, Jobs.DRG, Jobs.DRK, Jobs.PLD], 233 'available_main_job': [Jobs.WAR, Jobs.DRG, Jobs.DRK, Jobs.PLD],
226 'available_support_job': [Jobs.WAR, Jobs.DRG, Jobs.DRK, Jobs.PLD], 234 'available_support_job': [Jobs.WAR, Jobs.DRG, Jobs.DRK, Jobs.PLD],
227 'innate_feral_skills': ['Sinker Drill', 'Dire Straight', 'Dismemberment', 'Earthshatter'], 235 'innate_feral_skills': [],#'Sinker Drill', 'Dire Straight', 'Dismemberment', 'Earthshatter'],
228 'target_magic_damage_adjustment': 1.00, 236 'target_magic_damage_adjustment': 1.00,
237 'feral_skills_conversion': ['Accuracy +15%'],
229 'type': 'Arcana', 238 'type': 'Arcana',
230 'strong_vs': ['Dark'], 239 'strong_vs': ['Dark'],
231 'charmable': False, 240 'charmable': False,
...@@ -272,6 +281,7 @@ Families = { ...@@ -272,6 +281,7 @@ Families = {
272 'available_support_job': [Jobs.BLM, Jobs.RDM, Jobs.WAR], 281 'available_support_job': [Jobs.BLM, Jobs.RDM, Jobs.WAR],
273 'innate_feral_skills': ['Binding Wave', 'Magic Barrier', 'Hypnosis', 'Eyes On Me', 'Airy Shield'], 282 'innate_feral_skills': ['Binding Wave', 'Magic Barrier', 'Hypnosis', 'Eyes On Me', 'Airy Shield'],
274 'type': 'Demon', 283 'type': 'Demon',
284 'feral_skills_conversion': ['Accuracy +15%'],
275 'traits': ['magic defence bonus +25%'], 285 'traits': ['magic defence bonus +25%'],
276 'target_magic_damage_adjustment': 0.75, 286 'target_magic_damage_adjustment': 0.75,
277 'charmable': False, 287 'charmable': False,
...@@ -316,6 +326,7 @@ Monsters = { ...@@ -316,6 +326,7 @@ Monsters = {
316 'Mechanical Menace': { 326 'Mechanical Menace': {
317 'family': 'acrolith', 327 'family': 'acrolith',
318 'zone': ['abyssea - uleguerand'], 328 'zone': ['abyssea - uleguerand'],
329 'feral_skills_conversion': [],
319 'hp': 20, 330 'hp': 20,
320 'mp': 20, 331 'mp': 20,
321 'weapon_base_damage': 18 332 'weapon_base_damage': 18
...@@ -323,95 +334,108 @@ Monsters = { ...@@ -323,95 +334,108 @@ Monsters = {
323 'Floating Eye': { 334 'Floating Eye': {
324 'family': 'ahriman', 335 'family': 'ahriman',
325 'zone': ['ranguemont pass'], 336 'zone': ['ranguemont pass'],
337 'feral_skills_conversion': [],
326 'hp': 15, 338 'hp': 15,
327 'mp': 24, 339 'mp': 24,
328 'weapon_base_damage': 15, 340 'weapon_base_damage': 5,
329 'image_url': 'http://vignette1.wikia.nocookie.net/ffxi/images/9/94/Floating_Eye.JPG/revision/latest?cb=20070704142439' 341 'image_url': 'http://vignette1.wikia.nocookie.net/ffxi/images/9/94/Floating_Eye.JPG/revision/latest?cb=20070704142439'
330 }, 342 },
331 'Bat Eye': { 343 'Bat Eye': {
332 'family': 'ahriman', 344 'family': 'ahriman',
333 'zone': ['ranguemont pass', 'beaucedine glacier'], 345 'zone': ['ranguemont pass', 'beaucedine glacier'],
346 'feral_skills_conversion': [],
334 'hp': 15, 347 'hp': 15,
335 'mp': 24, 348 'mp': 24,
336 'weapon_base_damage': 15, 349 'weapon_base_damage': 5,
337 'image_url': 'http://vignette3.wikia.nocookie.net/ffxi/images/4/40/Bat_Eye.jpg/revision/latest?cb=20060909124134', 350 'image_url': 'http://vignette3.wikia.nocookie.net/ffxi/images/4/40/Bat_Eye.jpg/revision/latest?cb=20060909124134',
338 }, 351 },
339 'Evil Eye': { 352 'Evil Eye': {
340 'family': 'ahriman', 353 'family': 'ahriman',
341 'zone': ['castle zvahl baileys', 'castle zvahl keep', 'xarcabard'], 354 'zone': ['castle zvahl baileys', 'castle zvahl keep', 'xarcabard'],
355 'feral_skills_conversion': [],
342 'hp': 15, 356 'hp': 15,
343 'mp': 24, 357 'mp': 24,
344 'weapon_base_damage': 15, 358 'weapon_base_damage': 5,
345 }, 359 },
346 'Morbid Eye': { 360 'Morbid Eye': {
347 'family': 'ahriman', 361 'family': 'ahriman',
348 'zone': ['castle zvahl baileys', 'castle zvahl keep'], 362 'zone': ['castle zvahl baileys', 'castle zvahl keep'],
363 'feral_skills_conversion': [],
349 'hp': 15, 364 'hp': 15,
350 'mp': 24, 365 'mp': 24,
351 'weapon_base_damage': 15 366 'weapon_base_damage': 5
352 }, 367 },
353 'Deadly Iris': { 368 'Deadly Iris': {
354 'family': 'ahriman', 369 'family': 'ahriman',
355 'zone': ['castle zvahl keep'], 370 'zone': ['castle zvahl keep'],
371 'feral_skills_conversion': [],
356 'hp': 15, 372 'hp': 15,
357 'mp': 24, 373 'mp': 24,
358 'weapon_base_damage': 15 374 'weapon_base_damage': 5
359 }, 375 },
360 'Ahriman': { 376 'Ahriman': {
361 'family': 'ahriman', 377 'family': 'ahriman',
362 'zone': ['castle zvahl baileys'], 378 'zone': ['castle zvahl baileys'],
379 'feral_skills_conversion': [],
363 'hp': 15, 380 'hp': 15,
364 'mp': 24, 381 'mp': 24,
365 'weapon_base_damage': 15 382 'weapon_base_damage': 5
366 }, 383 },
367 'Fachan': { 384 'Fachan': {
368 'family': 'ahriman', 385 'family': 'ahriman',
369 'zone': ['uleguerand range'], 386 'zone': ['uleguerand range'],
387 'feral_skills_conversion': [],
370 'hp': 15, 388 'hp': 15,
371 'mp': 24, 389 'mp': 24,
372 'weapon_base_damage': 15 390 'weapon_base_damage': 5
373 }, 391 },
374 'Gawper': { 392 'Gawper': {
375 'family': 'ahriman', 393 'family': 'ahriman',
376 'zone': ['beaucedine glacier (s)'], 394 'zone': ['beaucedine glacier (s)'],
395 'feral_skills_conversion': [],
377 'hp': 15, 396 'hp': 15,
378 'mp': 24, 397 'mp': 24,
379 'weapon_base_damage': 15 398 'weapon_base_damage': 5
380 }, 399 },
381 'Menacing Eye': { 400 'Menacing Eye': {
382 'family': 'ahriman', 401 'family': 'ahriman',
383 'zone': ['xarcabard (s)'], 402 'zone': ['xarcabard (s)'],
403 'feral_skills_conversion': [],
384 'hp': 15, 404 'hp': 15,
385 'mp': 24, 405 'mp': 24,
386 'weapon_base_damage': 15 406 'weapon_base_damage': 5
387 }, 407 },
388 'Ogler': { 408 'Ogler': {
389 'family': 'ahriman', 409 'family': 'ahriman',
390 'zone': ['castle zvahl keep (s)', 'castle zvahl baileys (s)'], 410 'zone': ['castle zvahl keep (s)', 'castle zvahl baileys (s)'],
411 'feral_skills_conversion': [],
391 'hp': 15, 412 'hp': 15,
392 'mp': 24, 413 'mp': 24,
393 'weapon_base_damage': 15 414 'weapon_base_damage': 5
394 }, 415 },
395 'Smolenkos': { 416 'Smolenkos': {
396 'family': 'ahriman', 417 'family': 'ahriman',
397 'zone': ['uleguerand range'], 418 'zone': ['uleguerand range'],
419 'feral_skills_conversion': [],
398 'hp': 15, 420 'hp': 15,
399 'mp': 24, 421 'mp': 24,
400 'weapon_base_damage': 15 422 'weapon_base_damage': 5
401 }, 423 },
402 'Doom Lens': { 424 'Doom Lens': {
403 'family': 'ahriman', 425 'family': 'ahriman',
404 'zone': ['castle zvahl keep (s)', 'castle zvahl baileys (s)'], 426 'zone': ['castle zvahl keep (s)', 'castle zvahl baileys (s)'],
427 'feral_skills_conversion': [],
405 'hp': 15, 428 'hp': 15,
406 'mp': 24, 429 'mp': 24,
407 'weapon_base_damage': 15 430 'weapon_base_damage': 5
408 }, 431 },
409 'Scowlenkos': { 432 'Scowlenkos': {
410 'family': 'ahriman', 433 'family': 'ahriman',
411 'zone': ['uleguerand range'], 434 'zone': ['uleguerand range'],
435 'feral_skills_conversion': [],
412 'hp': 15, 436 'hp': 15,
413 'mp': 24, 437 'mp': 24,
414 'weapon_base_damage': 15 438 'weapon_base_damage': 5
415 } 439 }
416 440
417 } 441 }
...@@ -477,13 +501,14 @@ class Pankration: ...@@ -477,13 +501,14 @@ class Pankration:
477 while support_job == main_job: 501 while support_job == main_job:
478 support_job = random.choice(family['available_support_job']) 502 support_job = random.choice(family['available_support_job'])
479 feral_skills = [] 503 feral_skills = []
480 skills = random.sample(family['innate_feral_skills'], 3) 504 # TODO: Add support back in for innate feral skills
481 if random.randint(1, 100) < SKILL_PERCENT: 505 # skills = random.sample(family['innate_feral_skills'], 3)
482 feral_skills.append(skills[0]) 506 # if random.randint(1, 100) < SKILL_PERCENT:
483 if random.randint(1, 100) < SKILL_PERCENT: 507 # feral_skills.append(skills[0])
484 feral_skills.append(skills[1]) 508 # if random.randint(1, 100) < SKILL_PERCENT:
485 if random.randint(1, 100) < SKILL_PERCENT: 509 # feral_skills.append(skills[1])
486 feral_skills.append(skills[2]) 510 # if random.randint(1, 100) < SKILL_PERCENT:
511 # feral_skills.append(skills[2])
487 dicipline_level = 1 512 dicipline_level = 1
488 513
489 monster = Monster(monster_name, family_name, family, hp, mp, level, 514 monster = Monster(monster_name, family_name, family, hp, mp, level,
...@@ -556,7 +581,7 @@ class Monster: ...@@ -556,7 +581,7 @@ class Monster:
556 self.mp = self.get_mp() 581 self.mp = self.get_mp()
557 self.wins = 0 582 self.wins = 0
558 self.losses = 0 583 self.losses = 0
559 self.battle_memory = [] 584 self.battle_memory = {}
560 585
561 def __str__(self): 586 def __str__(self):
562 try: 587 try:
...@@ -608,15 +633,18 @@ class Monster: ...@@ -608,15 +633,18 @@ class Monster:
608 633
609 def add_xp(self, exp_to_add): 634 def add_xp(self, exp_to_add):
610 self.exp += exp_to_add 635 self.exp += exp_to_add
636 original_level = self.level
611 for i in range(self.level, 51): 637 for i in range(self.level, 51):
612 if self.exp >= 200 * i: 638 if self.exp >= 200 * i:
613 if i > self.level: 639 if i > self.level:
614 # We leveled up! 640 # We leveled up!
615 self.level = i 641 self.level = i
616 return (True, "Congratulations your monster leveled up!\n\nStart level: {} New Level: {}".format(self.level, i))
617 else: 642 else:
618 break 643 break
619 return (False,None) 644 if original_level > self.level:
645 return (True, "Congratulations your monster leveled up!\n\nStart level: {} New Level: {}".format(original_level, self.level))
646 else:
647 return (False,None)
620 648
621 def get_current_posture(self): 649 def get_current_posture(self):
622 return TemperamentPosture[self.temperament_posture] 650 return TemperamentPosture[self.temperament_posture]
...@@ -695,12 +723,16 @@ class Monster: ...@@ -695,12 +723,16 @@ class Monster:
695 # Get the stat for the spell and base magic accuracy for that spells MA 723 # Get the stat for the spell and base magic accuracy for that spells MA
696 magic_acc_stat = spell_data['magic_acc_stat'] 724 magic_acc_stat = spell_data['magic_acc_stat']
697 if magic_acc_stat == 'int': 725 if magic_acc_stat == 'int':
726 print("DSTAT - INT")
698 dSTAT = self.get_intelligence() - enemy.get_intelligence() 727 dSTAT = self.get_intelligence() - enemy.get_intelligence()
699 elif magic_acc_stat == 'mnd': 728 elif magic_acc_stat == 'mnd':
729 print("DSTAT - INT")
700 dSTAT = self.get_mind() - enemy.get_mind() 730 dSTAT = self.get_mind() - enemy.get_mind()
701 elif magic_acc_stat == 'chr': 731 elif magic_acc_stat == 'chr':
732 print("DSTAT - INT")
702 dSTAT = self.get_charisma() - enemy.get_charisma() 733 dSTAT = self.get_charisma() - enemy.get_charisma()
703 elif magic_acc_stat == 'agi': 734 elif magic_acc_stat == 'agi':
735 print("DSTAT - INT")
704 dSTAT = self.get_agility() - enemy.get_agility() 736 dSTAT = self.get_agility() - enemy.get_agility()
705 737
706 magic_hit_rate = 50 - 0.5 * (enemy.get_magic_evasion(spell_data['damage_type']) - dSTAT) 738 magic_hit_rate = 50 - 0.5 * (enemy.get_magic_evasion(spell_data['damage_type']) - dSTAT)
...@@ -709,6 +741,8 @@ class Monster: ...@@ -709,6 +741,8 @@ class Monster:
709 magic_hit_rate = 5 741 magic_hit_rate = 5
710 elif magic_hit_rate > 95: 742 elif magic_hit_rate > 95:
711 magic_hit_rate = 95 743 magic_hit_rate = 95
744 print("DSTAT {}\nMagic Evasion: {}\nMagic hit rate: {}".format(dSTAT, enemy.get_magic_evasion(spell_data['damage_type']), magic_hit_rate))
745
712 return magic_hit_rate 746 return magic_hit_rate
713 747
714 def get_pdif(self, base_damage, defense, attack_type, level_difference): 748 def get_pdif(self, base_damage, defense, attack_type, level_difference):
...@@ -905,13 +939,48 @@ class Monster: ...@@ -905,13 +939,48 @@ class Monster:
905 # Step 0: Am I already casting a spell? Is it time to calc damage from that? 939 # Step 0: Am I already casting a spell? Is it time to calc damage from that?
906 940
907 # Step 1: Is magic possible? 941 # Step 1: Is magic possible?
908 spell_list = Spells().get_spell_list(self.level, job=self.main_job, sub_job=self.sub_job)
909 942
910 # Step 2: Do i have a memory of this monster from past battles? Does it have any elemental weakness? 943 # Step 2: Do i have a memory of this monster from past battles? Does it have any elemental weakness?
911 944
945 spell_list = Spells().get_spell_list(self.mp, self.level, job=self.main_job, support_job=self.support_job)
946 best_spell_name = None
947 if spell_list:
948 if monster.family_name in self.battle_memory:
949 battles = self.battle_memory[monster.family_name]
950 # this assumes spells are: 'spells':{'Fire': 100, 'Stone II': 500}
951 if 'spells' in battles:
952 # if i have tried all spells then i know the right spell, otherwise try
953 # one of the ones that i don't know
954 if len(battles['spells']) == len(spell_list):
955 # get the sorted spell list by best average damage against this monster.
956 for i in max(battles['spells'].iteritems(), key=operator.itemgetter(1)):
957 best_spell_name = i
958 break
959 else:
960 untried_spells = []
961 for i in spell_list:
962 if i not in battles['spells']:
963 untried_spells.append(i)
964 best_spell_name = random.choice(untried_spells)
965 else:
966 best_spell_name = random.choice(spell_list)
967 else:
968 best_spell_name = random.choice(spell_list)
912 # Step 3: What status effects is the monster currently under? What are the effects(DOTS) we can apply? 969 # Step 3: What status effects is the monster currently under? What are the effects(DOTS) we can apply?
970 spell_damage = 0
971 if best_spell_name:
972 print("BEST SPELL NAME: {}".format(best_spell_name))
973 spell_damage = self.get_magic_base_damage(best_spell_name, monster)
974
975 # TODO: Make this follow the behavior in temprament and select the right behavior.
976 if self.tp >= 1000:
977 physical_damage = self.get_physical_ws_damage(monster.get_base_defense(), 'melee', [1.0, 1.5, 4.0], [], monster.level - self.level, monster.get_vitality())
978 else:
979 physical_damage = self.get_physical_base_damage(monster.get_base_defense(), 'melee', monster.level - self.level, monster.get_vitality())
913 980
914 # find out the avg damage from each type of attack and sort them 981 return (best_spell_name, spell_damage, physical_damage)
982
983 # Step 4: find out the avg damage from each type of attack and sort them
915 984
916 # find out if we need to do defensive actions given the amount of life left in the enemy vs how much damage it does. 985 # find out if we need to do defensive actions given the amount of life left in the enemy vs how much damage it does.
917 # We should also store how hard the AI has hit previously and adjust accordingly (Store previous average damage per hit). IE project how much damage we will 986 # We should also store how hard the AI has hit previously and adjust accordingly (Store previous average damage per hit). IE project how much damage we will
...@@ -934,38 +1003,45 @@ class Monster: ...@@ -934,38 +1003,45 @@ class Monster:
934 resisted = False 1003 resisted = False
935 damage = 0 1004 damage = 0
936 1005
937 self.get_best_action(monster) 1006 # intialize the monster memory for this family name if it isn't already set.
938 1007 if monster.family_name not in self.battle_memory:
939 ###### 1008 self.battle_memory[monster.family_name] = {'spells': {}}
940 # TODO: Build some type of AI / testing to find the most powerful attack and use that (magic, melee, or ranged) 1009 action_result = self.get_best_action(monster)
941 ###### 1010 print("AI RESULTS: {}".format(action_result))
942 1011 # TODO: Add a nice response object from the action choice to make this code pretty. (no tuple)
943 spell = 'Fire' 1012 if action_result[1] > action_result[2]:
944 if self.is_a_magic_hit(spell, monster): 1013 spell = action_result[0]
945 damage = self.get_magic_base_damage(spell, monster) 1014 if self.is_a_magic_hit(spell, monster):
946 if damage == 0: 1015 damage = self.get_magic_base_damage(spell, monster)
947 resisted = True 1016 if damage == 0:
948 log("MAGIC DAMAGE: {}".format(damage)) 1017 resisted = True
949 is_a_hit = True 1018 log("MAGIC DAMAGE: {}".format(damage))
950 spell_data = Spells().get_spell_data(spell) 1019 is_a_hit = True
951 self.mp -= spell_data['mp_cost'] 1020 spell_data = Spells().get_spell_data(spell)
952 if self.mp < 0: 1021 self.mp -= spell_data['mp_cost']
953 self.mp = 0 1022 if self.mp < 0:
954 return AttackResponse(is_a_hit, damage, is_a_crit, spell, resisted) 1023 self.mp = 0
955 1024 # if the spell already exists then average the two damage amounts.
956 if self.is_a_hit(monster): 1025 if spell in self.battle_memory[monster.family_name]['spells']:
957 # TODO: Make this follow the behavior in temprament and select the right behavior. 1026 self.battle_memory[monster.family_name]['spells'][spell] = damage + (self.battle_memory[monster.family_name]['spells'][spell]) / 2
958 if self.tp >= 1000:
959 damage = self.get_physical_ws_damage(monster.get_base_defense(), 'melee', [1.0, 1.5, 4.0], [], monster.level - self.level, monster.get_vitality())
960 log("WS DAMAGE: {}".format(damage))
961 self.tp = 0
962 else: 1027 else:
963 damage = self.get_physical_base_damage(monster.get_base_defense(), 'melee', monster.level - self.level, monster.get_vitality()) 1028 self.battle_memory[monster.family_name]['spells'][spell] = damage
964 print("STD DAMAGE: {}".format(damage)) 1029 return AttackResponse(is_a_hit, damage, is_a_crit, spell, resisted)
965 self.tp += 64 1030 else:
966 is_a_hit = True 1031 if self.is_a_hit(monster):
967 # Returns the amount of damage and if it is a crit 1032 # TODO: Make this follow the behavior in temprament and select the right behavior.
968 return AttackResponse(is_a_hit, damage, is_a_crit, spell, resisted) 1033 if self.tp >= 1000:
1034 damage = self.get_physical_ws_damage(monster.get_base_defense(), 'melee', [1.0, 1.5, 4.0], [], monster.level - self.level, monster.get_vitality())
1035 log("WS DAMAGE: {}".format(damage))
1036 self.tp = 0
1037 else:
1038 damage = self.get_physical_base_damage(monster.get_base_defense(), 'melee', monster.level - self.level, monster.get_vitality())
1039 print("STD DAMAGE: {}".format(damage))
1040 self.tp += 64
1041 is_a_hit = True
1042 # Returns the amount of damage and if it is a crit
1043 return AttackResponse(is_a_hit, damage, is_a_crit, spell, resisted)
1044
969 1045
970 def is_a_magic_hit(self, spell, monster): 1046 def is_a_magic_hit(self, spell, monster):
971 hit_rate = self.get_magic_hit_rate(spell, monster) 1047 hit_rate = self.get_magic_hit_rate(spell, monster)
...@@ -1135,7 +1211,7 @@ class Arena: ...@@ -1135,7 +1211,7 @@ class Arena:
1135 if __name__ == "__main__": 1211 if __name__ == "__main__":
1136 #print Families 1212 #print Families
1137 1213
1138 print("Spell List: \n{}\n".format(Spells().get_spell_list(20, job=Jobs.BLM, sub_job=Jobs.WHM))) 1214 print("Spell List: \n{}\n".format(Spells().get_spell_list(100, 10, job=Jobs.RDM, support_job=Jobs.WAR)))
1139 hunt_response = None 1215 hunt_response = None
1140 p = Pankration() 1216 p = Pankration()
1141 print("Zones: \n\n{}".format('\n'.join(p.list_zones()))) 1217 print("Zones: \n\n{}".format('\n'.join(p.list_zones())))
...@@ -1150,12 +1226,12 @@ if __name__ == "__main__": ...@@ -1150,12 +1226,12 @@ if __name__ == "__main__":
1150 print(hunt_response.message) 1226 print(hunt_response.message)
1151 monster = hunt_response.monster 1227 monster = hunt_response.monster
1152 monster.set_monster_name('Kickass 1') 1228 monster.set_monster_name('Kickass 1')
1153 monster.set_status_effect('int', 100, False, None) 1229
1154 print("The Soul Plate Shows: \n\n{}".format(monster)) 1230 print("The Soul Plate Shows: \n\n{}".format(monster))
1155 # print(monster.set_strategy(4, 3)) 1231 # print(monster.set_strategy(4, 3))
1156 # print(monster.set_strategy(1, 1)) 1232 # print(monster.set_strategy(1, 1))
1157 # print(monster.set_strategy(1, 2)) 1233 # print(monster.set_strategy(1, 2))
1158 monster.add_xp(22900) 1234 #monster.add_xp(22900)
1159 # phy_damage = monster.get_physical_base_damage(100, 'melee', -15) 1235 # phy_damage = monster.get_physical_base_damage(100, 'melee', -15)
1160 # print("Phys Attack: {}".format(phy_damage)) 1236 # print("Phys Attack: {}".format(phy_damage))
1161 # print(monster.get_base_defense()) 1237 # print(monster.get_base_defense())
...@@ -1176,7 +1252,8 @@ if __name__ == "__main__": ...@@ -1176,7 +1252,8 @@ if __name__ == "__main__":
1176 print("1 The Soul Plate Shows: \n\n{}".format(monster)) 1252 print("1 The Soul Plate Shows: \n\n{}".format(monster))
1177 print("2 The Soul Plate Shows: \n\n{}".format(monster2)) 1253 print("2 The Soul Plate Shows: \n\n{}".format(monster2))
1178 print("MP m1: {}\nMP m2: {}".format(monster.get_mp(), monster2.get_mp())) 1254 print("MP m1: {}\nMP m2: {}".format(monster.get_mp(), monster2.get_mp()))
1179 monster2.add_xp(16900) 1255 #print(monster2.add_xp(16900))
1256 #monster2.set_status_effect('int', 100, False, None)
1180 phy_damage = monster2.attack(monster) 1257 phy_damage = monster2.attack(monster)
1181 print("Phys Attack: {}".format(phy_damage)) 1258 print("Phys Attack: {}".format(phy_damage))
1182 1259
...@@ -1201,12 +1278,13 @@ if __name__ == "__main__": ...@@ -1201,12 +1278,13 @@ if __name__ == "__main__":
1201 print("{} {} {} against {} for {}.".format(action.attacker.get_monster_name(), action.message, action.spell, action.target.get_monster_name(), action.damage)) 1278 print("{} {} {} against {} for {}.".format(action.attacker.get_monster_name(), action.message, action.spell, action.target.get_monster_name(), action.damage))
1202 if isinstance(action, DefeatAction): 1279 if isinstance(action, DefeatAction):
1203 print("{} {} {} gains {} xp.".format(action.target.get_monster_name(), action.message, action.attacker.get_monster_name(), action.xp)) 1280 print("{} {} {} gains {} xp.".format(action.target.get_monster_name(), action.message, action.attacker.get_monster_name(), action.xp))
1204 action.attacker.hp = 500 1281 #print(action.attacker.add_xp(action.xp))
1205 print("{} {}".format(action.target.hp, action.attacker.hp)) 1282 print("{} {}".format(action.target.hp, action.attacker.hp))
1206 fighting = False 1283 fighting = False
1207 break 1284 break
1208 print("\n\nhp: {} {}\nmp: {} {}\n\n".format(monster.hp, monster2.hp, monster.mp, monster2.mp)) 1285 print("\n\nhp: {} {}\nmp: {} {}\n\n".format(monster.hp, monster2.hp, monster.mp, monster2.mp))
1209 print("\n{} {}% - {} {}%\n".format(monster.get_monster_name(), monster.get_hp_percent(), monster2.get_monster_name(), monster2.get_hp_percent())) 1286 print("\n{} {}% - {} {}%\n".format(monster.get_monster_name(), monster.get_hp_percent(), monster2.get_monster_name(), monster2.get_hp_percent()))
1287 print("\n{} Memory: {}\n\n{} Memory: {}\n\n".format(monster.get_monster_name(), monster.battle_memory, monster2.get_monster_name(), monster2.battle_memory))
1210 1288
1211 1289
1212 1290
......