mt-lang 0.3.2 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/milk_tea/base.rb +1 -1
- data/lib/milk_tea/lsp/diagnostics.rb +1 -1
- data/lib/milk_tea/tooling/linter/imports_platform.rb +14 -13
- data/std/blackboard.mt +100 -0
- data/std/cmd.mt +132 -0
- data/std/color.mt +245 -0
- data/std/graph.mt +237 -0
- data/std/htn.mt +254 -0
- data/std/input.mt +132 -0
- data/std/noise.mt +201 -0
- data/std/pool.mt +82 -0
- data/std/signal.mt +66 -0
- data/std/steering.mt +132 -0
- data/std/timer.mt +81 -0
- data/std/tween.mt +374 -0
- data/std/utility.mt +208 -0
- metadata +14 -2
data/std/tween.mt
ADDED
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
## Tweening and easing — smooth value interpolation.
|
|
2
|
+
##
|
|
3
|
+
## Normalized easing functions map [0,1] linear progress to
|
|
4
|
+
## eased progress, following the Robert Penner convention.
|
|
5
|
+
## A Tween struct tracks elapsed time and computes the
|
|
6
|
+
## current interpolated value.
|
|
7
|
+
##
|
|
8
|
+
## import std.tween as tw
|
|
9
|
+
## var t = tw.Tween.create(0.0, 100.0, 2.0, tw.Easing.ease_out_cubic)
|
|
10
|
+
## while t.active:
|
|
11
|
+
## let v = t.value()
|
|
12
|
+
## apply_position(v)
|
|
13
|
+
## t.step(dt)
|
|
14
|
+
|
|
15
|
+
import std.math as math
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
public enum Easing: ubyte
|
|
19
|
+
linear = 0
|
|
20
|
+
ease_in_quad = 1
|
|
21
|
+
ease_out_quad = 2
|
|
22
|
+
ease_in_out_quad = 3
|
|
23
|
+
ease_in_cubic = 4
|
|
24
|
+
ease_out_cubic = 5
|
|
25
|
+
ease_in_out_cubic = 6
|
|
26
|
+
ease_in_quart = 7
|
|
27
|
+
ease_out_quart = 8
|
|
28
|
+
ease_in_out_quart = 9
|
|
29
|
+
ease_in_quint = 10
|
|
30
|
+
ease_out_quint = 11
|
|
31
|
+
ease_in_out_quint = 12
|
|
32
|
+
ease_in_sine = 13
|
|
33
|
+
ease_out_sine = 14
|
|
34
|
+
ease_in_out_sine = 15
|
|
35
|
+
ease_in_expo = 17
|
|
36
|
+
ease_out_expo = 18
|
|
37
|
+
ease_in_out_expo = 19
|
|
38
|
+
ease_in_circ = 20
|
|
39
|
+
ease_out_circ = 21
|
|
40
|
+
ease_in_out_circ = 22
|
|
41
|
+
ease_in_back = 23
|
|
42
|
+
ease_out_back = 24
|
|
43
|
+
ease_in_out_back = 25
|
|
44
|
+
ease_in_elastic = 26
|
|
45
|
+
ease_out_elastic = 27
|
|
46
|
+
ease_in_out_elastic = 28
|
|
47
|
+
ease_in_bounce = 29
|
|
48
|
+
ease_out_bounce = 30
|
|
49
|
+
ease_in_out_bounce = 31
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
public struct Tween:
|
|
53
|
+
duration: float
|
|
54
|
+
elapsed: float
|
|
55
|
+
from: float
|
|
56
|
+
to: float
|
|
57
|
+
easing: Easing
|
|
58
|
+
active: bool
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
# ── math helpers ──
|
|
62
|
+
|
|
63
|
+
function pow_f(base: float, exp: float) -> float:
|
|
64
|
+
return float<-(math.pow(double<-(base), double<-(exp)))
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
function sin_f(x: float) -> float:
|
|
68
|
+
return float<-(math.sin(double<-(x)))
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
function cos_f(x: float) -> float:
|
|
72
|
+
return float<-(math.cos(double<-(x)))
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
function sqrt_f(x: float) -> float:
|
|
76
|
+
return float<-(math.sqrt(double<-(x)))
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
function ease_out_bounce_f(t: float) -> float:
|
|
80
|
+
let n1 = 7.5625
|
|
81
|
+
let d1 = 2.75
|
|
82
|
+
if t < 1.0 / d1:
|
|
83
|
+
return n1 * t * t
|
|
84
|
+
if t < 2.0 / d1:
|
|
85
|
+
let t1 = t - 1.5 / d1
|
|
86
|
+
return n1 * t1 * t1 + 0.75
|
|
87
|
+
if t < 2.5 / d1:
|
|
88
|
+
let t1 = t - 2.25 / d1
|
|
89
|
+
return n1 * t1 * t1 + 0.9375
|
|
90
|
+
let t1 = t - 2.625 / d1
|
|
91
|
+
return n1 * t1 * t1 + 0.984375
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
# ── tween ──
|
|
95
|
+
|
|
96
|
+
extending Tween:
|
|
97
|
+
public static function apply_easing(easing: Easing, t: float) -> float:
|
|
98
|
+
if easing == Easing.linear:
|
|
99
|
+
return t
|
|
100
|
+
|
|
101
|
+
if easing == Easing.ease_in_quad:
|
|
102
|
+
return t * t
|
|
103
|
+
if easing == Easing.ease_out_quad:
|
|
104
|
+
return t * (2.0 - t)
|
|
105
|
+
if easing == Easing.ease_in_out_quad:
|
|
106
|
+
if t < 0.5:
|
|
107
|
+
return 2.0 * t * t
|
|
108
|
+
return -1.0 + (4.0 - 2.0 * t) * t
|
|
109
|
+
|
|
110
|
+
if easing == Easing.ease_in_cubic:
|
|
111
|
+
return t * t * t
|
|
112
|
+
if easing == Easing.ease_out_cubic:
|
|
113
|
+
let t1 = t - 1.0
|
|
114
|
+
return t1 * t1 * t1 + 1.0
|
|
115
|
+
if easing == Easing.ease_in_out_cubic:
|
|
116
|
+
if t < 0.5:
|
|
117
|
+
return 4.0 * t * t * t
|
|
118
|
+
let t1 = -2.0 * t + 2.0
|
|
119
|
+
return 1.0 - t1 * t1 * t1 / 2.0
|
|
120
|
+
|
|
121
|
+
if easing == Easing.ease_in_quart:
|
|
122
|
+
return t * t * t * t
|
|
123
|
+
if easing == Easing.ease_out_quart:
|
|
124
|
+
let t1 = t - 1.0
|
|
125
|
+
return 1.0 - t1 * t1 * t1 * t1
|
|
126
|
+
if easing == Easing.ease_in_out_quart:
|
|
127
|
+
if t < 0.5:
|
|
128
|
+
return 8.0 * t * t * t * t
|
|
129
|
+
let t1 = t - 1.0
|
|
130
|
+
return 1.0 - 8.0 * t1 * t1 * t1 * t1
|
|
131
|
+
|
|
132
|
+
if easing == Easing.ease_in_quint:
|
|
133
|
+
return t * t * t * t * t
|
|
134
|
+
if easing == Easing.ease_out_quint:
|
|
135
|
+
let t1 = t - 1.0
|
|
136
|
+
return 1.0 + t1 * t1 * t1 * t1 * t1
|
|
137
|
+
if easing == Easing.ease_in_out_quint:
|
|
138
|
+
if t < 0.5:
|
|
139
|
+
return 16.0 * t * t * t * t * t
|
|
140
|
+
let t1 = -2.0 * t + 2.0
|
|
141
|
+
return 1.0 - t1 * t1 * t1 * t1 * t1 / 2.0
|
|
142
|
+
|
|
143
|
+
if easing == Easing.ease_in_sine:
|
|
144
|
+
return 1.0 - cos_f(t * 1.5707963)
|
|
145
|
+
if easing == Easing.ease_out_sine:
|
|
146
|
+
return sin_f(t * 1.5707963)
|
|
147
|
+
if easing == Easing.ease_in_out_sine:
|
|
148
|
+
return -(cos_f(3.14159265 * t) - 1.0) / 2.0
|
|
149
|
+
|
|
150
|
+
if easing == Easing.ease_in_expo:
|
|
151
|
+
if t <= 0.0: return 0.0
|
|
152
|
+
return pow_f(2.0, 10.0 * (t - 1.0))
|
|
153
|
+
if easing == Easing.ease_out_expo:
|
|
154
|
+
if t >= 1.0: return 1.0
|
|
155
|
+
return 1.0 - pow_f(2.0, -10.0 * t)
|
|
156
|
+
if easing == Easing.ease_in_out_expo:
|
|
157
|
+
if t <= 0.0: return 0.0
|
|
158
|
+
if t >= 1.0: return 1.0
|
|
159
|
+
if t < 0.5:
|
|
160
|
+
return pow_f(2.0, 20.0 * t - 10.0) / 2.0
|
|
161
|
+
return (2.0 - pow_f(2.0, -20.0 * t + 10.0)) / 2.0
|
|
162
|
+
|
|
163
|
+
if easing == Easing.ease_in_circ:
|
|
164
|
+
return 1.0 - sqrt_f(1.0 - t * t)
|
|
165
|
+
if easing == Easing.ease_out_circ:
|
|
166
|
+
return sqrt_f(1.0 - (t - 1.0) * (t - 1.0))
|
|
167
|
+
if easing == Easing.ease_in_out_circ:
|
|
168
|
+
if t < 0.5:
|
|
169
|
+
return (1.0 - sqrt_f(1.0 - 4.0 * t * t)) / 2.0
|
|
170
|
+
return (sqrt_f(1.0 - (-2.0 * t + 2.0) * (-2.0 * t + 2.0)) + 1.0) / 2.0
|
|
171
|
+
|
|
172
|
+
if easing == Easing.ease_in_back:
|
|
173
|
+
let c1 = 1.70158
|
|
174
|
+
return (c1 + 1.0) * t * t * t - c1 * t * t
|
|
175
|
+
if easing == Easing.ease_out_back:
|
|
176
|
+
let c1 = 1.70158
|
|
177
|
+
let t1 = t - 1.0
|
|
178
|
+
return 1.0 + (c1 + 1.0) * t1 * t1 * t1 + c1 * t1 * t1
|
|
179
|
+
if easing == Easing.ease_in_out_back:
|
|
180
|
+
let c1 = 1.70158
|
|
181
|
+
let c2 = c1 * 1.525
|
|
182
|
+
if t < 0.5:
|
|
183
|
+
return (4.0 * t * t * ((c2 + 1.0) * 2.0 * t - c2)) / 2.0
|
|
184
|
+
let t1 = t - 1.0
|
|
185
|
+
return (4.0 * t1 * t1 * ((c2 + 1.0) * 2.0 * t1 + c2) + 2.0) / 2.0
|
|
186
|
+
|
|
187
|
+
if easing == Easing.ease_in_elastic:
|
|
188
|
+
if t <= 0.0: return 0.0
|
|
189
|
+
if t >= 1.0: return 1.0
|
|
190
|
+
return -pow_f(2.0, 10.0 * t - 10.0) * sin_f((t * 10.0 - 10.75) * 2.0943951)
|
|
191
|
+
if easing == Easing.ease_out_elastic:
|
|
192
|
+
if t <= 0.0: return 0.0
|
|
193
|
+
if t >= 1.0: return 1.0
|
|
194
|
+
return pow_f(2.0, -10.0 * t) * sin_f((t * 10.0 - 0.75) * 2.0943951) + 1.0
|
|
195
|
+
if easing == Easing.ease_in_out_elastic:
|
|
196
|
+
if t <= 0.0: return 0.0
|
|
197
|
+
if t >= 1.0: return 1.0
|
|
198
|
+
if t < 0.5:
|
|
199
|
+
return -(pow_f(2.0, 20.0 * t - 10.0) * sin_f((20.0 * t - 11.125) * 1.3962634)) / 2.0
|
|
200
|
+
return (pow_f(2.0, -20.0 * t + 10.0) * sin_f((20.0 * t - 11.125) * 1.3962634)) / 2.0 + 1.0
|
|
201
|
+
|
|
202
|
+
if easing == Easing.ease_in_bounce:
|
|
203
|
+
return 1.0 - ease_out_bounce_f(1.0 - t)
|
|
204
|
+
if easing == Easing.ease_out_bounce:
|
|
205
|
+
return ease_out_bounce_f(t)
|
|
206
|
+
if easing == Easing.ease_in_out_bounce:
|
|
207
|
+
if t < 0.5:
|
|
208
|
+
return (1.0 - ease_out_bounce_f(1.0 - 2.0 * t)) / 2.0
|
|
209
|
+
return (1.0 + ease_out_bounce_f(2.0 * t - 1.0)) / 2.0
|
|
210
|
+
|
|
211
|
+
return t
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
public static function create(from: float, to: float, duration: float, easing: Easing) -> Tween:
|
|
215
|
+
return Tween(
|
|
216
|
+
duration = duration,
|
|
217
|
+
elapsed = 0.0,
|
|
218
|
+
from = from,
|
|
219
|
+
to = to,
|
|
220
|
+
easing = easing,
|
|
221
|
+
active = true
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
public function value() -> float:
|
|
226
|
+
if this.duration <= 0.0:
|
|
227
|
+
return this.to
|
|
228
|
+
let progress = this.elapsed / this.duration
|
|
229
|
+
if progress >= 1.0:
|
|
230
|
+
return this.to
|
|
231
|
+
if progress <= 0.0:
|
|
232
|
+
return this.from
|
|
233
|
+
let eased = Tween.apply_easing(this.easing, progress)
|
|
234
|
+
return this.from + (this.to - this.from) * eased
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
public editable function step(dt: float) -> bool:
|
|
238
|
+
if not this.active:
|
|
239
|
+
return false
|
|
240
|
+
this.elapsed = this.elapsed + dt
|
|
241
|
+
if this.elapsed >= this.duration:
|
|
242
|
+
this.elapsed = this.duration
|
|
243
|
+
this.active = false
|
|
244
|
+
return true
|
|
245
|
+
return false
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
public editable function reset(from: float, to: float, duration: float, easing: Easing) -> void:
|
|
249
|
+
this.from = from
|
|
250
|
+
this.to = to
|
|
251
|
+
this.duration = duration
|
|
252
|
+
this.easing = easing
|
|
253
|
+
this.elapsed = 0.0
|
|
254
|
+
this.active = true
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
public editable function stop() -> void:
|
|
258
|
+
this.active = false
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
# ── multi-type tweens ──
|
|
262
|
+
|
|
263
|
+
public struct Tween2:
|
|
264
|
+
x: Tween
|
|
265
|
+
y: Tween
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
public struct Tween3:
|
|
269
|
+
x: Tween
|
|
270
|
+
y: Tween
|
|
271
|
+
z: Tween
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
public struct Tween4:
|
|
275
|
+
x: Tween
|
|
276
|
+
y: Tween
|
|
277
|
+
z: Tween
|
|
278
|
+
w: Tween
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
extending Tween2:
|
|
282
|
+
public static function create(from: vec2, to: vec2, duration: float, easing: Easing) -> Tween2:
|
|
283
|
+
return Tween2(
|
|
284
|
+
x = Tween.create(from.x, to.x, duration, easing),
|
|
285
|
+
y = Tween.create(from.y, to.y, duration, easing)
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
public function value() -> vec2:
|
|
290
|
+
return vec2(x = this.x.value(), y = this.y.value())
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
public editable function step(dt: float) -> bool:
|
|
294
|
+
let done_x = this.x.step(dt)
|
|
295
|
+
let done_y = this.y.step(dt)
|
|
296
|
+
return done_x or done_y
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
public editable function reset(from: vec2, to: vec2, duration: float, easing: Easing) -> void:
|
|
300
|
+
this.x.reset(from.x, to.x, duration, easing)
|
|
301
|
+
this.y.reset(from.y, to.y, duration, easing)
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
public editable function stop() -> void:
|
|
305
|
+
this.x.stop()
|
|
306
|
+
this.y.stop()
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
extending Tween3:
|
|
310
|
+
public static function create(from: vec3, to: vec3, duration: float, easing: Easing) -> Tween3:
|
|
311
|
+
return Tween3(
|
|
312
|
+
x = Tween.create(from.x, to.x, duration, easing),
|
|
313
|
+
y = Tween.create(from.y, to.y, duration, easing),
|
|
314
|
+
z = Tween.create(from.z, to.z, duration, easing)
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
public function value() -> vec3:
|
|
319
|
+
return vec3(x = this.x.value(), y = this.y.value(), z = this.z.value())
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
public editable function step(dt: float) -> bool:
|
|
323
|
+
let dx = this.x.step(dt)
|
|
324
|
+
let dy = this.y.step(dt)
|
|
325
|
+
let dz = this.z.step(dt)
|
|
326
|
+
return dx or dy or dz
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
public editable function reset(from: vec3, to: vec3, duration: float, easing: Easing) -> void:
|
|
330
|
+
this.x.reset(from.x, to.x, duration, easing)
|
|
331
|
+
this.y.reset(from.y, to.y, duration, easing)
|
|
332
|
+
this.z.reset(from.z, to.z, duration, easing)
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
public editable function stop() -> void:
|
|
336
|
+
this.x.stop()
|
|
337
|
+
this.y.stop()
|
|
338
|
+
this.z.stop()
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
extending Tween4:
|
|
342
|
+
public static function create(from: vec4, to: vec4, duration: float, easing: Easing) -> Tween4:
|
|
343
|
+
return Tween4(
|
|
344
|
+
x = Tween.create(from.x, to.x, duration, easing),
|
|
345
|
+
y = Tween.create(from.y, to.y, duration, easing),
|
|
346
|
+
z = Tween.create(from.z, to.z, duration, easing),
|
|
347
|
+
w = Tween.create(from.w, to.w, duration, easing)
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
public function value() -> vec4:
|
|
352
|
+
return vec4(x = this.x.value(), y = this.y.value(), z = this.z.value(), w = this.w.value())
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
public editable function step(dt: float) -> bool:
|
|
356
|
+
let dx = this.x.step(dt)
|
|
357
|
+
let dy = this.y.step(dt)
|
|
358
|
+
let dz = this.z.step(dt)
|
|
359
|
+
let dw = this.w.step(dt)
|
|
360
|
+
return dx or dy or dz or dw
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
public editable function reset(from: vec4, to: vec4, duration: float, easing: Easing) -> void:
|
|
364
|
+
this.x.reset(from.x, to.x, duration, easing)
|
|
365
|
+
this.y.reset(from.y, to.y, duration, easing)
|
|
366
|
+
this.z.reset(from.z, to.z, duration, easing)
|
|
367
|
+
this.w.reset(from.w, to.w, duration, easing)
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
public editable function stop() -> void:
|
|
371
|
+
this.x.stop()
|
|
372
|
+
this.y.stop()
|
|
373
|
+
this.z.stop()
|
|
374
|
+
this.w.stop()
|
data/std/utility.mt
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
## Utility AI — score-based action selection.
|
|
2
|
+
##
|
|
3
|
+
## Agents evaluate candidate actions by scoring them against
|
|
4
|
+
## the current context. The action with the highest score wins.
|
|
5
|
+
## Considerations return 0..1 values, combined via geometric
|
|
6
|
+
## mean (default), average, min, max, or multiplicative.
|
|
7
|
+
##
|
|
8
|
+
## import std.utility as util
|
|
9
|
+
## var selector = util.Selector[MyContext].create()
|
|
10
|
+
## selector.add_action(util.Action[MyContext].create("fight", util.CombineMode.geometric))
|
|
11
|
+
## let chosen = selector.select(ptr_of(ctx))
|
|
12
|
+
## if chosen.selected: execute(chosen.name)
|
|
13
|
+
|
|
14
|
+
import std.vec as vec
|
|
15
|
+
import std.math as math
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
public enum CombineMode: ubyte
|
|
19
|
+
geometric = 0
|
|
20
|
+
average = 1
|
|
21
|
+
minimum = 2
|
|
22
|
+
maximum = 3
|
|
23
|
+
multiplicative = 4
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
public struct Consideration[Context]:
|
|
27
|
+
name: str
|
|
28
|
+
score: fn(context: ptr[Context]) -> float
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
public struct Action[Context]:
|
|
32
|
+
name: str
|
|
33
|
+
considerations: vec.Vec[Consideration[Context]]
|
|
34
|
+
combine: CombineMode
|
|
35
|
+
weight: float
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
public struct Selector[Context]:
|
|
39
|
+
actions: vec.Vec[Action[Context]]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
public struct Selection:
|
|
43
|
+
index: ptr_uint
|
|
44
|
+
name: str
|
|
45
|
+
score: float
|
|
46
|
+
selected: bool
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# ── internal helpers ──
|
|
50
|
+
|
|
51
|
+
function combine_scores(mode: CombineMode, scores: ref[vec.Vec[float]]) -> float:
|
|
52
|
+
let n = scores.len()
|
|
53
|
+
if n == 0:
|
|
54
|
+
return 0.0
|
|
55
|
+
|
|
56
|
+
if mode == CombineMode.geometric:
|
|
57
|
+
var product: float = 1.0
|
|
58
|
+
var i: ptr_uint = 0
|
|
59
|
+
while i < n:
|
|
60
|
+
let s_ptr = scores.get(i) else:
|
|
61
|
+
return 0.0
|
|
62
|
+
let s = unsafe: read(s_ptr)
|
|
63
|
+
if s <= 0.0:
|
|
64
|
+
return 0.0
|
|
65
|
+
product = product * s
|
|
66
|
+
i += 1
|
|
67
|
+
let exponent = 1.0 / float<-(n)
|
|
68
|
+
return float<-(math.pow(double<-(product), double<-(exponent)))
|
|
69
|
+
|
|
70
|
+
if mode == CombineMode.multiplicative:
|
|
71
|
+
var product: float = 1.0
|
|
72
|
+
var i: ptr_uint = 0
|
|
73
|
+
while i < n:
|
|
74
|
+
let s_ptr = scores.get(i) else:
|
|
75
|
+
return 0.0
|
|
76
|
+
let s = unsafe: read(s_ptr)
|
|
77
|
+
if s <= 0.0:
|
|
78
|
+
return 0.0
|
|
79
|
+
product = product * s
|
|
80
|
+
i += 1
|
|
81
|
+
return product
|
|
82
|
+
|
|
83
|
+
if mode == CombineMode.average:
|
|
84
|
+
var sum: float = 0.0
|
|
85
|
+
var i: ptr_uint = 0
|
|
86
|
+
while i < n:
|
|
87
|
+
let s_ptr = scores.get(i) else:
|
|
88
|
+
break
|
|
89
|
+
sum = sum + unsafe: read(s_ptr)
|
|
90
|
+
i += 1
|
|
91
|
+
return sum / float<-(n)
|
|
92
|
+
|
|
93
|
+
if mode == CombineMode.minimum:
|
|
94
|
+
var best: float = 1.0
|
|
95
|
+
var i: ptr_uint = 0
|
|
96
|
+
while i < n:
|
|
97
|
+
let s_ptr = scores.get(i) else:
|
|
98
|
+
break
|
|
99
|
+
let s = unsafe: read(s_ptr)
|
|
100
|
+
if s < best:
|
|
101
|
+
best = s
|
|
102
|
+
i += 1
|
|
103
|
+
return best
|
|
104
|
+
|
|
105
|
+
# CombineMode.maximum
|
|
106
|
+
var best: float = 0.0
|
|
107
|
+
var i: ptr_uint = 0
|
|
108
|
+
while i < n:
|
|
109
|
+
let s_ptr = scores.get(i) else:
|
|
110
|
+
break
|
|
111
|
+
let s = unsafe: read(s_ptr)
|
|
112
|
+
if s > best:
|
|
113
|
+
best = s
|
|
114
|
+
i += 1
|
|
115
|
+
return best
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
# ── public types: extensions ──
|
|
119
|
+
|
|
120
|
+
extending Consideration[Context]:
|
|
121
|
+
public static function create(
|
|
122
|
+
name: str,
|
|
123
|
+
score: fn(context: ptr[Context]) -> float
|
|
124
|
+
) -> Consideration[Context]:
|
|
125
|
+
return Consideration[Context](name = name, score = score)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
extending Action[Context]:
|
|
129
|
+
public static function create(
|
|
130
|
+
name: str,
|
|
131
|
+
combine: CombineMode
|
|
132
|
+
) -> Action[Context]:
|
|
133
|
+
return Action[Context](
|
|
134
|
+
name = name,
|
|
135
|
+
considerations = vec.Vec[Consideration[Context]].create(),
|
|
136
|
+
combine = combine,
|
|
137
|
+
weight = 1.0
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
public editable function set_weight(w: float) -> void:
|
|
142
|
+
this.weight = w
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
public editable function add_consideration(c: Consideration[Context]) -> void:
|
|
146
|
+
this.considerations.push(c)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
public function evaluate(context: ptr[Context]) -> float:
|
|
150
|
+
let n = this.considerations.len()
|
|
151
|
+
if n == 0:
|
|
152
|
+
return 0.0
|
|
153
|
+
|
|
154
|
+
var scores = vec.Vec[float].with_capacity(n)
|
|
155
|
+
defer scores.release()
|
|
156
|
+
|
|
157
|
+
for entry in this.considerations:
|
|
158
|
+
unsafe:
|
|
159
|
+
scores.push(read(entry).score(context))
|
|
160
|
+
|
|
161
|
+
return combine_scores(this.combine, ref_of(scores)) * this.weight
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
public editable function release() -> void:
|
|
165
|
+
this.considerations.release()
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
extending Selector[Context]:
|
|
169
|
+
public static function create() -> Selector[Context]:
|
|
170
|
+
return Selector[Context](
|
|
171
|
+
actions = vec.Vec[Action[Context]].create()
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
public editable function add_action(action: Action[Context]) -> void:
|
|
176
|
+
this.actions.push(action)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
public function action_count() -> ptr_uint:
|
|
180
|
+
return this.actions.len()
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
public function select(context: ptr[Context]) -> Selection:
|
|
184
|
+
var best_index: ptr_uint = 0
|
|
185
|
+
var best_name: str = ""
|
|
186
|
+
var best_score: float = -1.0
|
|
187
|
+
var found: bool = false
|
|
188
|
+
|
|
189
|
+
var i: ptr_uint = 0
|
|
190
|
+
for entry in this.actions:
|
|
191
|
+
unsafe:
|
|
192
|
+
let action = read(entry)
|
|
193
|
+
let score = action.evaluate(context)
|
|
194
|
+
if score > 0.0 and score > best_score:
|
|
195
|
+
best_score = score
|
|
196
|
+
best_index = i
|
|
197
|
+
best_name = action.name
|
|
198
|
+
found = true
|
|
199
|
+
i += 1
|
|
200
|
+
|
|
201
|
+
return Selection(index = best_index, name = best_name, score = best_score, selected = found)
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
public editable function release() -> void:
|
|
205
|
+
for entry in this.actions:
|
|
206
|
+
unsafe:
|
|
207
|
+
read(entry).release()
|
|
208
|
+
this.actions.release()
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mt-lang
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Long (Teefan) Tran
|
|
@@ -401,6 +401,7 @@ files:
|
|
|
401
401
|
- std/binary.mt
|
|
402
402
|
- std/binary_heap.mt
|
|
403
403
|
- std/bitset.mt
|
|
404
|
+
- std/blackboard.mt
|
|
404
405
|
- std/box2d.mt
|
|
405
406
|
- std/bytes.mt
|
|
406
407
|
- std/c/box2d.mt
|
|
@@ -463,6 +464,8 @@ files:
|
|
|
463
464
|
- std/cgltf.mt
|
|
464
465
|
- std/cjson.mt
|
|
465
466
|
- std/cli.mt
|
|
467
|
+
- std/cmd.mt
|
|
468
|
+
- std/color.mt
|
|
466
469
|
- std/cookie.mt
|
|
467
470
|
- std/counter.mt
|
|
468
471
|
- std/crypto.mt
|
|
@@ -486,8 +489,10 @@ files:
|
|
|
486
489
|
- std/graph.mt
|
|
487
490
|
- std/gzip.mt
|
|
488
491
|
- std/hash.mt
|
|
492
|
+
- std/htn.mt
|
|
489
493
|
- std/http.mt
|
|
490
494
|
- std/http/server.mt
|
|
495
|
+
- std/input.mt
|
|
491
496
|
- std/intern.mt
|
|
492
497
|
- std/iter.mt
|
|
493
498
|
- std/jobs.mt
|
|
@@ -526,6 +531,7 @@ files:
|
|
|
526
531
|
- std/net/stun.mt
|
|
527
532
|
- std/net/sync.mt
|
|
528
533
|
- std/net/turn.mt
|
|
534
|
+
- std/noise.mt
|
|
529
535
|
- std/oauth2.mt
|
|
530
536
|
- std/option.mt
|
|
531
537
|
- std/ordered_map.mt
|
|
@@ -533,6 +539,7 @@ files:
|
|
|
533
539
|
- std/path.mt
|
|
534
540
|
- std/pcre2.mt
|
|
535
541
|
- std/pcre2/runtime.mt
|
|
542
|
+
- std/pool.mt
|
|
536
543
|
- std/priority_queue.mt
|
|
537
544
|
- std/process.mt
|
|
538
545
|
- std/queue.mt
|
|
@@ -554,6 +561,7 @@ files:
|
|
|
554
561
|
- std/sdl3/runtime.mt
|
|
555
562
|
- std/serialize.mt
|
|
556
563
|
- std/set.mt
|
|
564
|
+
- std/signal.mt
|
|
557
565
|
- std/simd.mt
|
|
558
566
|
- std/sparse_set.mt
|
|
559
567
|
- std/spatial.mt
|
|
@@ -567,6 +575,7 @@ files:
|
|
|
567
575
|
- std/stb_vorbis.mt
|
|
568
576
|
- std/stdio.mt
|
|
569
577
|
- std/steamworks.mt
|
|
578
|
+
- std/steering.mt
|
|
570
579
|
- std/str.mt
|
|
571
580
|
- std/string.mt
|
|
572
581
|
- std/sync.mt
|
|
@@ -575,11 +584,14 @@ files:
|
|
|
575
584
|
- std/testing.mt
|
|
576
585
|
- std/thread.mt
|
|
577
586
|
- std/time.mt
|
|
587
|
+
- std/timer.mt
|
|
578
588
|
- std/tls.mt
|
|
579
589
|
- std/toml.mt
|
|
580
590
|
- std/tracy.mt
|
|
591
|
+
- std/tween.mt
|
|
581
592
|
- std/uri.mt
|
|
582
593
|
- std/url.mt
|
|
594
|
+
- std/utility.mt
|
|
583
595
|
- std/vec.mt
|
|
584
596
|
- std/zstd.mt
|
|
585
597
|
homepage: https://teefan.github.io/mt-lang/
|
|
@@ -589,7 +601,7 @@ metadata:
|
|
|
589
601
|
homepage_uri: https://teefan.github.io/mt-lang/
|
|
590
602
|
source_code_uri: https://github.com/teefan/mt-lang
|
|
591
603
|
post_install_message: |
|
|
592
|
-
Milk Tea 0.3.
|
|
604
|
+
Milk Tea 0.3.4 installed!
|
|
593
605
|
|
|
594
606
|
System requirements:
|
|
595
607
|
- A C compiler (gcc or clang) must be available on PATH
|