def successors(game_state): """Return a dict of {state:action} pairs. A state is a (wizard, boss, timed_effects) tuple, wizard: (hit_points, armor, mana); boss: (hit_points)""" result = {} w, b, in_use_spells_state = game_state spells_in_use = [name for name, timer in in_use_spells_state if timer > 1] # apply_effects gets callend once before launch spell is called # this clears up spells that have just timer=1 left spells = [magic_missile, drain, shield, poison, recharge] available_spells = [s for s in spells if s().name not in spells_in_use] for available_spell in available_spells: boss = Boss(damage=boss_damage, hit_points=b) h,a,m = w wizard = Wizard(mana=m, hit_points=h, armor=a) gs = GameState(wizard, boss) candidate_spell = available_spell() # restore timed spells for name, timer in in_use_spells_state: gs.spells.append(get_spell_by_name(name)(timer)) gs.apply_effects() if not boss.is_alive(): result[represent(gs)] = None # boss is killed by existing spells else: wizard.launch_spell(gs, spell=candidate_spell) if not wizard.is_alive(): continue if not boss.is_alive(): # boss killed by spell result[represent(gs)] = candidate_spell.name else: gs.apply_effects() if not boss.is_alive(): # boss killed by timed effect result[represent(gs)] = candidate_spell.name else: boss.attack(wizard) if wizard.is_alive(): result[represent(gs)] = candidate_spell.name return result
def successors_2(game_state): """Return a dict of {state:action} pairs. A state is a (wizard, boss, timed_effects) tuple, wizard: (hit_points, armor, mana); boss: (hit_points)""" result = {} w, b, in_use_spells_state = game_state spells_in_use = [name for name, timer in in_use_spells_state if timer > 1] # apply_effects gets callend once before launch spell is called # this clears up spells that have just timer=1 left spells = [magic_missile, drain, shield, poison, recharge] available_spells = [s for s in spells if s().name not in spells_in_use] # print game_state for available_spell in available_spells: boss = Boss(damage=boss_damage, hit_points=b) h,a,m = w wizard = Wizard(mana=m, hit_points=h, armor=a) gs = GameState(wizard, boss, level='hard') candidate_spell = available_spell() # print 'candidate_spell: %s' % candidate_spell.name # restore timed spells for name, timer in in_use_spells_state: gs.spells.append(get_spell_by_name(name)(timer)) gs.apply_effects('before_wizard') if not wizard.is_alive(): # can't happen at easy level # print 'wizard is dead by hard level 1' # print represent(gs) continue if not boss.is_alive(): # if boss dies by existing effects it is not necessary to add # a new spell result[represent(gs)] = None # boss is killed by existing spells else: # here boss is alive wizard.launch_spell(gs, spell=candidate_spell) if not wizard.is_alive(): # print 'wizard is dead launching spell' # print represent(gs) continue if not boss.is_alive(): # boss killed by spell result[represent(gs)] = candidate_spell.name else: gs.apply_effects('before_boss') if not wizard.is_alive(): # print 'wizard is dead by hard level 2' # print represent(gs) continue if not boss.is_alive(): # boss killed by timed effect result[represent(gs)] = candidate_spell.name else: boss.attack(wizard) if wizard.is_alive(): # if wizard is alive I log the launched spell # or else I don't care about this state result[represent(gs)] = candidate_spell.name return result
s = wizard.launch_spell(game_state) assert s.name == 'Recharge' # -- Boss turn -- # - Player has 10 hit points, 0 armor, 21 mana assert hit_armor_mana(wizard) == (10, 0, 21) # - Boss has 14 hit points assert boss.hit_points == 14 fxs = game_state.apply_effects() # Recharge provides 101 mana; its timer is now 4. assert len(fxs) == 1 assert fxs['Recharge']['timer'] == 4 # Boss attacks for 8 damage! boss.attack(wizard) # -- Player turn -- # - Player has 2 hit points, 0 armor, 122 mana assert hit_armor_mana(wizard) == (2, 0, 122) # - Boss has 14 hit points assert boss.hit_points == 14 fxs = game_state.apply_effects() # Recharge provides 101 mana; its timer is now 3. assert len(fxs) == 1 assert fxs['Recharge']['timer'] == 3 # Player casts Shield, increasing armor by 7. f = wizard.launch_spell(game_state) assert f.name == 'Shield'