~technomancy/tremendous-quest-iv

tremendous-quest-iv/dialog.fnl -rw-r--r-- 4.2 KiB
a3c24536Phil Hagelberg Bump to Fennel 0.9.1; fix some bugs. 5 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
(local talk-range 128)
(local max-length 38)

(λ ask [convo prompt choices]
  (match (type prompt)
    :string (when (< max-length (# prompt))
              (dbg "Warning: prompt is too long:" prompt))
    :table (each [_ pl (ipairs prompt)]
             (when (< max-length (# pl))
               (dbg "Warning: prompt is too long:" pl))))
  (each [_ c (ipairs choices)]
    (when (< max-length (# c))
      (dbg "Warning: choice is too long:" c)))
  (match (type prompt)
    :string (do (set convo.said prompt)
                (set convo.said-height 1))
    :table (do (set convo.said (table.concat prompt "\n"))
               (set convo.said-height (# prompt))))
  (set convo.choices choices)
  (coroutine.yield))

(λ say [convo ...]
  (let [sayings [...]
        saying (table.concat sayings "\n")]
    (each [_ s (ipairs sayings)]
      (when (< max-length (# s))
        (dbg "Warning: dialog is too long:" s)))
    (set convo.said saying)
    (set convo.said-height (# sayings))
    (set convo.choices nil)
    (coroutine.yield)))

(fn interject [convo interjector ...]
  (set convo.interjector interjector)
  (say convo ...)
  (set convo.interjector nil))

(local convos [#(do (say $ "just one more level.")
                    (say $ "then I'll log off and get some sleep.")
                    (say $ "honest."))
               #(say $ "man, I just beat a really tough boss.")
               #(say $ "wait, have I really been playing for"
                     "six hours??")
               #(say $ "wonder if I'll find any good gear"
                     "over in this direction...")
               #(say $ "these bugs are driving me nuts!")
               #(say $ "I think I need a new strategy...")
               #(say $ "what on earth is wrong with"
                     "the ladders in this realm?")
               #(say $ "kobolds seem to drop the best loot.")
               #(say $ "is it just me, or are paladins just"
                     "a bit overpowered?")
               #(say $ "did they even test this latest patch?")
               #(say $ "I haven't collected enough shells yet")
               #(say $ "not sure where to go next...")
               #(say $ "that shop in the village is a ripoff")])

(fn conversation-for [character convo]
  (if character.convo
      (partial character.convo convo)
      (match character.ai.task.name
        :combat
        #(say convo (lume.randomchoice ["hey can't you see I'm busy?"
                                        "I'm fighting a monster here!"
                                        "eat flaming death"
                                        "uh this one's tougher than it looked"
                                        "LEEEEEEROOOOOOOOY JENKINS!!!!"]))
        :stuck
        #(say convo (lume.randomchoice ["it's that movement bug again!"
                                        "ugh; I can't move--halp!"
                                        "aw come on; arrow keys don't work?!"]))
        :ragequit
        #(say convo (lume.randomchoice ["I hate this game"
                                        "I'm gonna quit; this is the worst"
                                        "UUUUUGGGGGGHHHHHH"]))
        _ (partial (lume.randomchoice convos) convo))))

(fn ok [character convo]
  (assert (coroutine.resume convo.coro convo.selection))
  (when (= (coroutine.status convo.coro) :dead)
    (set convo.done? true)))

(fn change [dir]
  (fn [convo]
    (when convo
      (pp convo)
      (set convo.selection (-> (+ convo.selection dir)
                               (math.min (# convo.choices))
                               (math.max 1))))))

(fn start [state character]
  (when (<= (lume.distance character.x character.y
                           state.player.x state.player.y) talk-range)
    (let [convo {:selection 1 :ok (partial ok character)
                 :up (change -1) :down (change 1)
                 :name character.name}
          f (conversation-for character convo)]
      (when f
        (dbg :dialog character.name)
        (set convo.coro (doto (coroutine.create f)
                          (coroutine.resume)))
        (let [char (lume.match state.characters #(= character.name $.name))]
          (set char.talked-to? true)
          (set char.new-convo? false))
        convo))))

{: start : talk-range : say : ask : interject}