24 "[{'boss_hp': -4, 'cost': 53, 'name': 'Magic missile'},\n",
25 " {'boss_hp': -2, 'cost': 73, 'name': 'Drain', 'pc_hp': 2},\n",
27 " 'name': 'Shield',\n",
28 " 'ongoing': [{'armour': 7},\n",
33 " {'armour': 7}]},\n",
35 " 'name': 'Poison',\n",
36 " 'ongoing': [{'boss_hp': -3},\n",
37 " {'boss_hp': -3},\n",
38 " {'boss_hp': -3},\n",
39 " {'boss_hp': -3},\n",
40 " {'boss_hp': -3},\n",
41 " {'boss_hp': -3}]},\n",
43 " 'name': 'Recharge',\n",
44 " 'ongoing': [{'mana': 101},\n",
53 "output_type": "execute_result"
58 " {'name': 'Magic missile', 'cost': 53, 'boss_hp': -4},\n",
59 " {'name': 'Drain', 'cost': 73, 'boss_hp': -2, 'pc_hp': 2},\n",
60 " {'name': 'Shield', 'cost': 113, 'ongoing': [{'armour': 7}] * 6},\n",
61 " {'name': 'Poison', 'cost': 173, 'ongoing': [{'boss_hp': -3}] * 6},\n",
62 " {'name': 'Recharge', 'cost': 229, 'ongoing': [{'mana': 101}] * 5}]\n",
68 "execution_count": 153,
74 "initial_state = {'pc_hp': 50, 'mana': 500, 'boss_hp': 58, 'boss_damage': 9, 'ongoing': [], \n",
75 " 'spent': 0, 'cast': []}"
80 "execution_count": 154,
86 "def cast_spell(spell, state):\n",
87 " new_state = copy.deepcopy(state)\n",
88 " new_state['mana'] -= spell['cost']\n",
89 " new_state['spent'] += spell['cost']\n",
90 " new_state['cast'] += [spell['name']]\n",
91 " if 'boss_hp' in spell:\n",
92 " new_state['boss_hp'] += spell['boss_hp']\n",
93 " if 'pc_hp' in spell:\n",
94 " new_state['pc_hp'] += spell['pc_hp']\n",
95 " if 'ongoing' in spell:\n",
96 " new_state['ongoing'] += [spell['ongoing']]\n",
102 "execution_count": 155,
110 "{'boss_damage': 9,\n",
112 " 'cast': ['Magic missile'],\n",
119 "execution_count": 155,
121 "output_type": "execute_result"
125 "cast_spell(spells[0], initial_state)"
130 "execution_count": 156,
138 "{'boss_damage': 9,\n",
147 "execution_count": 156,
149 "output_type": "execute_result"
158 "execution_count": 157,
166 "{'boss_damage': 9,\n",
168 " 'cast': ['Shield', 'Poison'],\n",
170 " 'ongoing': [[{'armour': 7},\n",
175 " {'armour': 7}],\n",
176 " [{'boss_hp': -3},\n",
177 " {'boss_hp': -3},\n",
178 " {'boss_hp': -3},\n",
179 " {'boss_hp': -3},\n",
180 " {'boss_hp': -3},\n",
181 " {'boss_hp': -3}]],\n",
186 "execution_count": 157,
188 "output_type": "execute_result"
192 "s2 = cast_spell(spells[2], initial_state)\n",
193 "cast_spell(spells[3], s2)"
198 "execution_count": 97,
204 "def valid_spells(spells, state):\n",
205 " valid_spells = []\n",
206 " for spell in spells:\n",
207 " add_this_spell = True\n",
208 " if spell['cost'] > state['mana']:\n",
209 " add_this_spell = False\n",
210 " if 'ongoing' in spell:\n",
211 " for s in spell['ongoing'][0]:\n",
212 " for status in state['ongoing']:\n",
213 " if s in status[0]:\n",
214 " add_this_spell = False\n",
215 " if add_this_spell:\n",
216 " valid_spells += [spell]\n",
217 " return valid_spells"
222 "execution_count": 98,
230 "[{'boss_hp': -4, 'cost': 53, 'name': 'Magic missile'},\n",
231 " {'boss_hp': -2, 'cost': 73, 'name': 'Drain', 'pc_hp': 2},\n",
233 " 'name': 'Shield',\n",
234 " 'ongoing': [{'armour': 7},\n",
239 " {'armour': 7}]},\n",
241 " 'name': 'Poison',\n",
242 " 'ongoing': [{'boss_hp': -3},\n",
243 " {'boss_hp': -3},\n",
244 " {'boss_hp': -3},\n",
245 " {'boss_hp': -3},\n",
246 " {'boss_hp': -3},\n",
247 " {'boss_hp': -3}]},\n",
249 " 'name': 'Recharge',\n",
250 " 'ongoing': [{'mana': 101},\n",
257 "execution_count": 98,
259 "output_type": "execute_result"
263 "valid_spells(spells, initial_state)"
268 "execution_count": 158,
276 "{'boss_damage': 9,\n",
278 " 'cast': ['Shield', 'Poison'],\n",
280 " 'ongoing': [[{'armour': 7},\n",
285 " {'armour': 7}],\n",
286 " [{'boss_hp': -3},\n",
287 " {'boss_hp': -3},\n",
288 " {'boss_hp': -3},\n",
289 " {'boss_hp': -3},\n",
290 " {'boss_hp': -3},\n",
291 " {'boss_hp': -3}]],\n",
296 "execution_count": 158,
298 "output_type": "execute_result"
302 "s2 = cast_spell(spells[2], initial_state)\n",
303 "s3 = cast_spell(spells[3], s2)\n",
309 "execution_count": 159,
317 "[{'boss_hp': -4, 'cost': 53, 'name': 'Magic missile'},\n",
318 " {'boss_hp': -2, 'cost': 73, 'name': 'Drain', 'pc_hp': 2}]"
321 "execution_count": 159,
323 "output_type": "execute_result"
327 "valid_spells(spells, s3)"
332 "execution_count": 48,
338 "def boss_turn(state):\n",
339 " new_state = apply_ongoing(state)\n",
340 " if new_state['boss_hp'] > 0:\n",
341 " new_state['pc_hp'] -= max(new_state['boss_damage'] - new_state['armour'], 1)\n",
347 "execution_count": 67,
353 "def apply_ongoing(state):\n",
354 " new_state = copy.deepcopy(state)\n",
355 " new_state['armour'] = 0\n",
356 " new_state['ongoing'] = []\n",
357 " for status in state['ongoing']:\n",
358 " for k in status[0]:\n",
359 " new_state[k] += status[0][k]\n",
360 " if len(status) > 1:\n",
361 " new_state['ongoing'] += [status[1:]]\n",
367 "execution_count": 160,
376 " 'boss_damage': 9,\n",
378 " 'cast': ['Shield', 'Poison'],\n",
380 " 'ongoing': [[{'armour': 7},\n",
384 " {'armour': 7}],\n",
385 " [{'boss_hp': -3},\n",
386 " {'boss_hp': -3},\n",
387 " {'boss_hp': -3},\n",
388 " {'boss_hp': -3},\n",
389 " {'boss_hp': -3}]],\n",
394 "execution_count": 160,
396 "output_type": "execute_result"
405 "execution_count": 161,
414 " 'boss_damage': 8,\n",
416 " 'cast': ['Poison'],\n",
418 " 'ongoing': [[{'boss_hp': -3},\n",
419 " {'boss_hp': -3},\n",
420 " {'boss_hp': -3},\n",
421 " {'boss_hp': -3},\n",
422 " {'boss_hp': -3}]],\n",
427 "execution_count": 161,
429 "output_type": "execute_result"
433 "test_state_1 = {'pc_hp': 10, 'mana': 250, 'boss_hp': 13, 'boss_damage': 8, 'ongoing': [], 'spent': 0, 'cast': []}\n",
434 "s2 = cast_spell([s for s in spells if s['name'] == 'Poison'][0], test_state_1)\n",
435 "s3 = boss_turn(s2)\n",
441 "execution_count": 162,
450 " 'boss_damage': 8,\n",
452 " 'cast': ['Poison', 'Magic missile'],\n",
454 " 'ongoing': [[{'boss_hp': -3}, {'boss_hp': -3}, {'boss_hp': -3}]],\n",
459 "execution_count": 162,
461 "output_type": "execute_result"
465 "s4 = apply_ongoing(s3)\n",
466 "s5 = cast_spell([s for s in spells if s['name'] == 'Magic missile'][0], s4)\n",
467 "s6 = boss_turn(s5)\n",
473 "execution_count": 163,
482 " 'boss_damage': 8,\n",
484 " 'cast': ['Recharge'],\n",
486 " 'ongoing': [[{'mana': 101}, {'mana': 101}, {'mana': 101}, {'mana': 101}]],\n",
491 "execution_count": 163,
493 "output_type": "execute_result"
497 "test_state_2 = {'pc_hp': 10, 'mana': 250, 'boss_hp': 14, 'boss_damage': 8, 'ongoing': [], 'spent': 0, 'cast': []}\n",
498 "s2 = cast_spell([s for s in spells if s['name'] == 'Recharge'][0], test_state_2)\n",
499 "s3 = boss_turn(s2)\n",
505 "execution_count": 164,
514 " 'boss_damage': 8,\n",
516 " 'cast': ['Recharge', 'Shield'],\n",
518 " 'ongoing': [[{'mana': 101}, {'mana': 101}],\n",
519 " [{'armour': 7}, {'armour': 7}, {'armour': 7}, {'armour': 7}, {'armour': 7}]],\n",
524 "execution_count": 164,
526 "output_type": "execute_result"
530 "s4 = apply_ongoing(s3)\n",
531 "s5 = cast_spell([s for s in spells if s['name'] == 'Shield'][0], s4)\n",
532 "s6 = boss_turn(s5)\n",
538 "execution_count": 165,
547 " 'boss_damage': 8,\n",
549 " 'cast': ['Recharge', 'Shield', 'Drain'],\n",
551 " 'ongoing': [[{'armour': 7}, {'armour': 7}, {'armour': 7}]],\n",
556 "execution_count": 165,
558 "output_type": "execute_result"
562 "s7 = apply_ongoing(s6)\n",
563 "s8 = cast_spell([s for s in spells if s['name'] == 'Drain'][0], s7)\n",
564 "s9 = boss_turn(s8)\n",
570 "execution_count": 166,
579 " 'boss_damage': 8,\n",
581 " 'cast': ['Recharge', 'Shield', 'Drain', 'Poison'],\n",
583 " 'ongoing': [[{'armour': 7}],\n",
584 " [{'boss_hp': -3},\n",
585 " {'boss_hp': -3},\n",
586 " {'boss_hp': -3},\n",
587 " {'boss_hp': -3},\n",
588 " {'boss_hp': -3}]],\n",
593 "execution_count": 166,
595 "output_type": "execute_result"
599 "s10 = apply_ongoing(s9)\n",
600 "s11 = cast_spell([s for s in spells if s['name'] == 'Poison'][0], s10)\n",
601 "s12 = boss_turn(s11)\n",
607 "execution_count": 167,
616 " 'boss_damage': 8,\n",
618 " 'cast': ['Recharge', 'Shield', 'Drain', 'Poison', 'Magic missile'],\n",
620 " 'ongoing': [[{'boss_hp': -3}, {'boss_hp': -3}, {'boss_hp': -3}]],\n",
625 "execution_count": 167,
627 "output_type": "execute_result"
631 "s13 = apply_ongoing(s12)\n",
632 "s14 = cast_spell([s for s in spells if s['name'] == 'Magic missile'][0], s13)\n",
633 "s15 = boss_turn(s14)\n",
639 "execution_count": 90,
645 "def finished(state):\n",
646 " return state['boss_hp'] <= 0 or state['pc_hp'] <= 0\n",
648 "def victory(state):\n",
649 " return finished(state) and state['pc_hp'] > 0\n",
651 "def defeat(state):\n",
652 " return finished(state) and state['pc_hp'] <= 0"
657 "execution_count": 125,
663 "def ahistoric(state):\n",
664 " return {k: state[k] for k in state if k != 'cast'}"
669 "execution_count": 186,
678 " 'boss_damage': 9,\n",
680 " 'cast': ['Poison',\n",
687 " 'Magic missile',\n",
688 " 'Magic missile'],\n",
690 " 'ongoing': [[{'boss_hp': -3}, {'boss_hp': -3}]],\n",
695 "execution_count": 186,
697 "output_type": "execute_result"
701 "agenda = [initial_state]\n",
704 " current_state = agenda[0]\n",
705 " new_states = []\n",
706 " if ahistoric(current_state) not in closed:\n",
707 " closed += [ahistoric(current_state)]\n",
708 " # print(current_state)\n",
709 " if victory(current_state):\n",
710 " # return current_state\n",
712 " for spell in valid_spells(spells, current_state):\n",
713 " s2 = cast_spell(spell, current_state)\n",
714 " if victory(s2):\n",
715 " new_states += [s2]\n",
717 " s3 = boss_turn(s2)\n",
718 " if victory(s3):\n",
719 " new_states += [s3]\n",
720 " if not finished(s3):\n",
721 " new_states += [apply_ongoing(s3)]\n",
722 " # print(new_states)\n",
723 " states_to_add = [s for s in new_states \n",
724 " if ahistoric(s) not in closed\n",
725 " if len(s['cast']) <= 50]\n",
726 " agenda = sorted(states_to_add + agenda[1:], key=lambda s: s['spent'])\n",
727 " # agenda = new_states + agenda[1:]\n",
732 "cell_type": "markdown",
740 "execution_count": 182,
746 "def player_bleed(state):\n",
747 " new_state = copy.deepcopy(state)\n",
748 " new_state['pc_hp'] -= 1\n",
754 "execution_count": 185,
763 " 'boss_damage': 9,\n",
765 " 'cast': ['Poison',\n",
772 " 'Magic missile',\n",
773 " 'Magic missile'],\n",
775 " 'ongoing': [[{'boss_hp': -3}]],\n",
780 "execution_count": 185,
782 "output_type": "execute_result"
786 "agenda = [initial_state]\n",
789 " current_state = agenda[0]\n",
790 " new_states = []\n",
791 " if ahistoric(current_state) not in closed:\n",
792 " closed += [ahistoric(current_state)]\n",
793 " # print(current_state)\n",
794 " if victory(current_state):\n",
795 " # return current_state\n",
797 " for spell in valid_spells(spells, current_state):\n",
798 " s2 = cast_spell(spell, current_state)\n",
799 " if victory(s2):\n",
800 " new_states += [s2]\n",
802 " s3 = boss_turn(s2)\n",
803 " if victory(s3):\n",
804 " new_states += [s3]\n",
805 " s4 = player_bleed(s3)\n",
806 " if not finished(s4):\n",
807 " new_states += [apply_ongoing(s4)]\n",
808 " # print(new_states)\n",
809 " states_to_add = [s for s in new_states \n",
810 " if ahistoric(s) not in closed\n",
811 " if len(s['cast']) <= 50]\n",
812 " agenda = sorted(states_to_add + agenda[1:], key=lambda s: s['spent'])\n",
813 " # agenda = new_states + agenda[1:]\n",
819 "execution_count": null,
829 "display_name": "Python 3",
830 "language": "python",
838 "file_extension": ".py",
839 "mimetype": "text/x-python",
841 "nbconvert_exporter": "python",
842 "pygments_lexer": "ipython3",