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",
74 "initial_state = {'pc_hp': 50, 'mana': 500, 'boss_hp': 58, 'boss_damage': 9, 'ongoing': [], \n",
75 " 'spent': 0, 'cast': []}"
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": 5,
110 "{'boss_damage': 9,\n",
112 " 'cast': ['Magic missile'],\n",
119 "execution_count": 5,
121 "output_type": "execute_result"
125 "cast_spell(spells[0], initial_state)"
130 "execution_count": 6,
138 "{'boss_damage': 9,\n",
147 "execution_count": 6,
149 "output_type": "execute_result"
158 "execution_count": 7,
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": 7,
188 "output_type": "execute_result"
192 "s2 = cast_spell(spells[2], initial_state)\n",
193 "cast_spell(spells[3], s2)"
198 "execution_count": 37,
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 spell['name'] == 'Magic missile' and state['cast'] and state['cast'][-1] == 'Drain':\n",
216 " add_this_spell = False\n",
217 " if add_this_spell:\n",
218 " valid_spells += [spell]\n",
219 " return valid_spells"
224 "execution_count": 57,
232 "[{'boss_hp': -4, 'cost': 53, 'name': 'Magic missile'},\n",
233 " {'boss_hp': -2, 'cost': 73, 'name': 'Drain', 'pc_hp': 2},\n",
235 " 'name': 'Shield',\n",
236 " 'ongoing': [{'armour': 7},\n",
241 " {'armour': 7}]},\n",
243 " 'name': 'Poison',\n",
244 " 'ongoing': [{'boss_hp': -3},\n",
245 " {'boss_hp': -3},\n",
246 " {'boss_hp': -3},\n",
247 " {'boss_hp': -3},\n",
248 " {'boss_hp': -3},\n",
249 " {'boss_hp': -3}]},\n",
251 " 'name': 'Recharge',\n",
252 " 'ongoing': [{'mana': 101},\n",
259 "execution_count": 57,
261 "output_type": "execute_result"
265 "valid_spells(spells, initial_state)"
270 "execution_count": 58,
278 "{'boss_damage': 9,\n",
280 " 'cast': ['Shield', 'Poison'],\n",
282 " 'ongoing': [[{'armour': 7},\n",
287 " {'armour': 7}],\n",
288 " [{'boss_hp': -3},\n",
289 " {'boss_hp': -3},\n",
290 " {'boss_hp': -3},\n",
291 " {'boss_hp': -3},\n",
292 " {'boss_hp': -3},\n",
293 " {'boss_hp': -3}]],\n",
298 "execution_count": 58,
300 "output_type": "execute_result"
304 "s2 = cast_spell(spells[2], initial_state)\n",
305 "s3 = cast_spell(spells[3], s2)\n",
311 "execution_count": 59,
319 "[{'boss_hp': -4, 'cost': 53, 'name': 'Magic missile'},\n",
320 " {'boss_hp': -2, 'cost': 73, 'name': 'Drain', 'pc_hp': 2}]"
323 "execution_count": 59,
325 "output_type": "execute_result"
329 "valid_spells(spells, s3)"
334 "execution_count": 60,
342 "[{'boss_hp': -2, 'cost': 73, 'name': 'Drain', 'pc_hp': 2}]"
345 "execution_count": 60,
347 "output_type": "execute_result"
351 "s4 = cast_spell(spells[1], s3)\n",
352 "valid_spells(spells, s4)"
357 "execution_count": 61,
365 "[{'boss_hp': -4, 'cost': 53, 'name': 'Magic missile'},\n",
366 " {'boss_hp': -2, 'cost': 73, 'name': 'Drain', 'pc_hp': 2}]"
369 "execution_count": 61,
371 "output_type": "execute_result"
375 "s4 = cast_spell(spells[0], s3)\n",
376 "valid_spells(spells, s4)"
381 "execution_count": 12,
387 "def boss_turn(state):\n",
388 " new_state = apply_ongoing(state)\n",
389 " if new_state['boss_hp'] > 0:\n",
390 " new_state['pc_hp'] -= max(new_state['boss_damage'] - new_state['armour'], 1)\n",
396 "execution_count": 13,
402 "def apply_ongoing(state):\n",
403 " new_state = copy.deepcopy(state)\n",
404 " new_state['armour'] = 0\n",
405 " new_state['ongoing'] = []\n",
406 " for status in state['ongoing']:\n",
407 " for k in status[0]:\n",
408 " new_state[k] += status[0][k]\n",
409 " if len(status) > 1:\n",
410 " new_state['ongoing'] += [status[1:]]\n",
416 "execution_count": 44,
425 " 'boss_damage': 9,\n",
427 " 'cast': ['Shield', 'Poison'],\n",
429 " 'ongoing': [[{'armour': 7},\n",
433 " {'armour': 7}],\n",
434 " [{'boss_hp': -3},\n",
435 " {'boss_hp': -3},\n",
436 " {'boss_hp': -3},\n",
437 " {'boss_hp': -3},\n",
438 " {'boss_hp': -3}]],\n",
443 "execution_count": 44,
445 "output_type": "execute_result"
454 "execution_count": 45,
463 " 'boss_damage': 8,\n",
465 " 'cast': ['Poison'],\n",
467 " 'ongoing': [[{'boss_hp': -3},\n",
468 " {'boss_hp': -3},\n",
469 " {'boss_hp': -3},\n",
470 " {'boss_hp': -3},\n",
471 " {'boss_hp': -3}]],\n",
476 "execution_count": 45,
478 "output_type": "execute_result"
482 "test_state_1 = {'pc_hp': 10, 'mana': 250, 'boss_hp': 13, 'boss_damage': 8, 'ongoing': [], 'spent': 0, 'cast': []}\n",
483 "s2 = cast_spell([s for s in spells if s['name'] == 'Poison'][0], test_state_1)\n",
484 "s3 = boss_turn(s2)\n",
490 "execution_count": 46,
499 " 'boss_damage': 8,\n",
501 " 'cast': ['Poison', 'Magic missile'],\n",
503 " 'ongoing': [[{'boss_hp': -3}, {'boss_hp': -3}, {'boss_hp': -3}]],\n",
508 "execution_count": 46,
510 "output_type": "execute_result"
514 "s4 = apply_ongoing(s3)\n",
515 "s5 = cast_spell([s for s in spells if s['name'] == 'Magic missile'][0], s4)\n",
516 "s6 = boss_turn(s5)\n",
522 "execution_count": 47,
531 " 'boss_damage': 8,\n",
533 " 'cast': ['Recharge'],\n",
535 " 'ongoing': [[{'mana': 101}, {'mana': 101}, {'mana': 101}, {'mana': 101}]],\n",
540 "execution_count": 47,
542 "output_type": "execute_result"
546 "test_state_2 = {'pc_hp': 10, 'mana': 250, 'boss_hp': 14, 'boss_damage': 8, 'ongoing': [], 'spent': 0, 'cast': []}\n",
547 "s2 = cast_spell([s for s in spells if s['name'] == 'Recharge'][0], test_state_2)\n",
548 "s3 = boss_turn(s2)\n",
554 "execution_count": 48,
563 " 'boss_damage': 8,\n",
565 " 'cast': ['Recharge', 'Shield'],\n",
567 " 'ongoing': [[{'mana': 101}, {'mana': 101}],\n",
568 " [{'armour': 7}, {'armour': 7}, {'armour': 7}, {'armour': 7}, {'armour': 7}]],\n",
573 "execution_count": 48,
575 "output_type": "execute_result"
579 "s4 = apply_ongoing(s3)\n",
580 "s5 = cast_spell([s for s in spells if s['name'] == 'Shield'][0], s4)\n",
581 "s6 = boss_turn(s5)\n",
587 "execution_count": 49,
596 " 'boss_damage': 8,\n",
598 " 'cast': ['Recharge', 'Shield', 'Drain'],\n",
600 " 'ongoing': [[{'armour': 7}, {'armour': 7}, {'armour': 7}]],\n",
605 "execution_count": 49,
607 "output_type": "execute_result"
611 "s7 = apply_ongoing(s6)\n",
612 "s8 = cast_spell([s for s in spells if s['name'] == 'Drain'][0], s7)\n",
613 "s9 = boss_turn(s8)\n",
619 "execution_count": 50,
628 " 'boss_damage': 8,\n",
630 " 'cast': ['Recharge', 'Shield', 'Drain', 'Poison'],\n",
632 " 'ongoing': [[{'armour': 7}],\n",
633 " [{'boss_hp': -3},\n",
634 " {'boss_hp': -3},\n",
635 " {'boss_hp': -3},\n",
636 " {'boss_hp': -3},\n",
637 " {'boss_hp': -3}]],\n",
642 "execution_count": 50,
644 "output_type": "execute_result"
648 "s10 = apply_ongoing(s9)\n",
649 "s11 = cast_spell([s for s in spells if s['name'] == 'Poison'][0], s10)\n",
650 "s12 = boss_turn(s11)\n",
656 "execution_count": 51,
665 " 'boss_damage': 8,\n",
667 " 'cast': ['Recharge', 'Shield', 'Drain', 'Poison', 'Magic missile'],\n",
669 " 'ongoing': [[{'boss_hp': -3}, {'boss_hp': -3}, {'boss_hp': -3}]],\n",
674 "execution_count": 51,
676 "output_type": "execute_result"
680 "s13 = apply_ongoing(s12)\n",
681 "s14 = cast_spell([s for s in spells if s['name'] == 'Magic missile'][0], s13)\n",
682 "s15 = boss_turn(s14)\n",
688 "execution_count": 22,
694 "def finished(state):\n",
695 " return state['boss_hp'] <= 0 or state['pc_hp'] <= 0\n",
697 "def victory(state):\n",
698 " return finished(state) and state['pc_hp'] > 0\n",
700 "def defeat(state):\n",
701 " return finished(state) and state['pc_hp'] <= 0"
706 "execution_count": 23,
712 "def ahistoric(state):\n",
713 " return {k: state[k] for k in state if k != 'cast'}"
718 "execution_count": 30,
727 " 'boss_damage': 9,\n",
729 " 'cast': ['Poison',\n",
736 " 'Magic missile',\n",
737 " 'Magic missile'],\n",
739 " 'ongoing': [[{'boss_hp': -3}, {'boss_hp': -3}]],\n",
744 "execution_count": 30,
746 "output_type": "execute_result"
750 "agenda = [initial_state]\n",
753 " current_state = agenda[0]\n",
754 " new_states = []\n",
755 " if ahistoric(current_state) not in closed:\n",
756 " closed += [ahistoric(current_state)]\n",
757 " # print(current_state)\n",
758 " if victory(current_state):\n",
759 " # return current_state\n",
761 " for spell in valid_spells(spells, current_state):\n",
762 " s2 = cast_spell(spell, current_state)\n",
763 " if victory(s2):\n",
764 " new_states += [s2]\n",
766 " s3 = boss_turn(s2)\n",
767 " if victory(s3):\n",
768 " new_states += [s3]\n",
769 " if not finished(s3):\n",
770 " new_states += [apply_ongoing(s3)]\n",
771 " # print(new_states)\n",
772 " states_to_add = [s for s in new_states \n",
773 " if ahistoric(s) not in closed\n",
774 " if len(s['cast']) <= 50]\n",
775 " agenda = sorted(states_to_add + agenda[1:], key=lambda s: s['spent'])\n",
776 " # agenda = new_states + agenda[1:]\n",
782 "execution_count": 31,
793 "execution_count": 31,
795 "output_type": "execute_result"
799 "len(agenda), len(closed)"
804 "execution_count": 65,
813 " 'boss_damage': 9,\n",
815 " 'cast': ['Poison',\n",
822 " 'Magic missile',\n",
823 " 'Magic missile'],\n",
825 " 'ongoing': [[{'boss_hp': -3}, {'boss_hp': -3}]],\n",
830 "execution_count": 65,
832 "output_type": "execute_result"
836 "agenda = [initial_state]\n",
839 " current_state = agenda[0]\n",
840 " new_states = []\n",
841 " # print(current_state)\n",
842 " if victory(current_state):\n",
843 " # return current_state\n",
845 " for spell in valid_spells(spells, current_state):\n",
846 " s2 = cast_spell(spell, current_state)\n",
847 " if victory(s2):\n",
848 " new_states += [s2]\n",
850 " s3 = boss_turn(s2)\n",
851 " if victory(s3):\n",
852 " new_states += [s3]\n",
853 " if not finished(s3):\n",
854 " new_states += [apply_ongoing(s3)]\n",
855 " # print(new_states)\n",
856 " states_to_add = [s for s in new_states \n",
857 " if len(s['cast']) <= 50]\n",
858 " agenda = sorted(states_to_add + agenda[1:], key=lambda s: s['spent'])\n",
859 " # agenda = new_states + agenda[1:]\n",
865 "execution_count": 66,
876 "execution_count": 66,
878 "output_type": "execute_result"
882 "len(agenda), len(closed)"
886 "cell_type": "markdown",
894 "execution_count": 25,
900 "def player_bleed(state):\n",
901 " new_state = copy.deepcopy(state)\n",
902 " new_state['pc_hp'] -= 1\n",
908 "execution_count": 32,
917 " 'boss_damage': 9,\n",
919 " 'cast': ['Poison',\n",
926 " 'Magic missile',\n",
927 " 'Magic missile'],\n",
929 " 'ongoing': [[{'boss_hp': -3}]],\n",
934 "execution_count": 32,
936 "output_type": "execute_result"
940 "agenda = [initial_state]\n",
943 " current_state = agenda[0]\n",
944 " new_states = []\n",
945 " if ahistoric(current_state) not in closed:\n",
946 " closed += [ahistoric(current_state)]\n",
947 " # print(current_state)\n",
948 " if victory(current_state):\n",
949 " # return current_state\n",
951 " for spell in valid_spells(spells, current_state):\n",
952 " s2 = cast_spell(spell, current_state)\n",
953 " if victory(s2):\n",
954 " new_states += [s2]\n",
956 " s3 = boss_turn(s2)\n",
957 " if victory(s3):\n",
958 " new_states += [s3]\n",
959 " s4 = player_bleed(s3)\n",
960 " if not finished(s4):\n",
961 " new_states += [apply_ongoing(s4)]\n",
962 " # print(new_states)\n",
963 " states_to_add = [s for s in new_states \n",
964 " if ahistoric(s) not in closed\n",
965 " if len(s['cast']) <= 50]\n",
966 " agenda = sorted(states_to_add + agenda[1:], key=lambda s: s['spent'])\n",
967 " # agenda = new_states + agenda[1:]\n",
973 "execution_count": 33,
984 "execution_count": 33,
986 "output_type": "execute_result"
990 "len(agenda), len(closed)"
995 "execution_count": null,
1005 "display_name": "Python 3",
1006 "language": "python",
1010 "codemirror_mode": {
1014 "file_extension": ".py",
1015 "mimetype": "text/x-python",
1017 "nbconvert_exporter": "python",
1018 "pygments_lexer": "ipython3",