|
7 | 7 | fractions [Fraction :as f/]
|
8 | 8 | enum [Enum]
|
9 | 9 | toolz [unique]
|
10 |
| - simalq.util [DamageType StatusEffect next-in-cycle mixed-number] |
| 10 | + simalq.util [DamageType StatusEffect next-in-cycle mixed-number seq] |
11 | 11 | simalq.geometry [Direction at dist adjacent? dir-to turn-and-pos-seed ray]
|
12 | 12 | simalq.game-state [G]
|
13 | 13 | simalq.tile [Tile Actor Damageable]
|
|
65 | 65 | (not (adjacent? (or mon-pos @pos) G.player.pos))
|
66 | 66 | (not @sees-invisible)))
|
67 | 67 |
|
68 |
| - (defmeth try-to-attack-player [[dry-run F] [shots-ignore-obstacles F]] |
| 68 | + (defmeth try-to-attack-player [[dry-run F] [shots-ignore-obstacles F] [pos None]] |
69 | 69 | "Try to melee or shoot the player, if the monster can. Return true
|
70 | 70 | if it succeeded. If `dry-run` is true, the attack isn't actually
|
71 | 71 | made."
|
72 | 72 |
|
73 |
| - (setv d (dir-to @pos G.player.pos)) |
| 73 | + (setv pos (or pos @pos)) |
| 74 | + (setv d (dir-to pos G.player.pos)) |
74 | 75 | (setv attack None)
|
75 | 76 |
|
76 |
| - (when (= @pos G.player.pos) |
| 77 | + (when (= pos G.player.pos) |
77 | 78 | ; If we're on the player's square, we can't attack her.
|
78 | 79 | (return F))
|
79 | 80 |
|
|
83 | 84 | ; Try a melee attack first.
|
84 | 85 | (when (and
|
85 | 86 | @damage-melee
|
86 |
| - (adjacent? @pos G.player.pos) |
87 |
| - (in (get (walkability @pos d :monster? T) 1) |
| 87 | + (adjacent? pos G.player.pos) |
| 88 | + (in (get (walkability pos d :monster? T) 1) |
88 | 89 | ['bump 'walk]))
|
89 | 90 | (setv attack 'melee))
|
90 | 91 |
|
91 | 92 | ; Otherwise, try a ranged attack.
|
92 | 93 | (when (and (not attack) @damage-shot)
|
93 |
| - (for [target (ray :pos @pos :direction d :length |
| 94 | + (for [target (ray :pos pos :direction d :length |
94 | 95 | (min (or @shot-range Inf) G.rules.reality-bubble-size))]
|
95 | 96 | (when (= target G.player.pos)
|
96 | 97 | (setv attack 'shot)
|
|
747 | 748 | :flavor "A wretched organic structure, fashioned from fiendish flesh. It twists about to aim its toothy maw, from which it belches flame. It's immobile, but dark magics make it almost invulnerable… almost.")
|
748 | 749 |
|
749 | 750 |
|
| 751 | +(deftile "W " "a teleporting mage" Monster |
| 752 | + :color 'purple |
| 753 | + :iq-ix 186 ; invisible mage |
| 754 | + :destruction-points 100 |
| 755 | +
|
| 756 | + :field-defaults (dict |
| 757 | + :shot-power (f/ 0)) |
| 758 | + :mutable-fields #("shot_power") |
| 759 | + :info-bullets (meth [#* extra] |
| 760 | + (.info-bullets (super) |
| 761 | + #("Shot power" @shot-power))) |
| 762 | +
|
| 763 | + :damage-shot 10 |
| 764 | + :!shot-frequency (f/ 3 4) |
| 765 | +
|
| 766 | + :act (meth [] |
| 767 | + (doc f"Teleport Attack — If the monster has line of sight to you, it adds {@shot-frequency} to its shot power. If this is ≥1, it subtracts 1 to shoot you. If it doesn't shoot you, it tries to teleport into line of sight, preferring to be as close as possible to you without being adjacent. Its destination must lie in the reality bubble.") |
| 768 | + ; Teleporting mages' movement is much smarter than that of IQ's |
| 769 | + ; invisible mages, which compensates for the loss of their main |
| 770 | + ; ability. |
| 771 | + (when (@player-invisible-to?) |
| 772 | + (return)) |
| 773 | + (when (@try-to-attack-player :dry-run T) |
| 774 | + (+= @shot-power @shot-frequency) |
| 775 | + (when (pop-integer-part @shot-power) |
| 776 | + (@try-to-attack-player) |
| 777 | + (return))) |
| 778 | + (for [ |
| 779 | + dist-from-player [#* (seq 2 G.rules.reality-bubble-size) 1] |
| 780 | + direction Direction.all |
| 781 | + :if (setx target (.+n G.player.pos dist-from-player direction))] |
| 782 | + (when (and |
| 783 | + (or |
| 784 | + (= target @pos) |
| 785 | + (not (nogo? target :monster? T :ethereal-to #()))) |
| 786 | + (@try-to-attack-player :dry-run T :pos target)) |
| 787 | + (@move target) |
| 788 | + (return)))) |
| 789 | +
|
| 790 | + :flavor "This academic has perfected the art of avoiding faculty meetings, thesis committees, institutional review boards, classes, and his own office hours, preferring instead to transport himself to conferences in tropical destinations. His strategy for evaluating students (such as yourself) is to observe them from afar and see how they perform under pressure.") |
| 791 | +
|
| 792 | +
|
750 | 793 | (deftile "W " "an archmage" Approacher
|
751 | 794 | :iq-ix 163
|
752 | 795 | :destruction-points 75
|
|
0 commit comments