mt-lang 0.3.2 → 0.3.5
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/core/c_backend/feature_detection.rb +27 -55
- data/lib/milk_tea/core/c_backend/format_helpers.rb +551 -0
- data/lib/milk_tea/core/c_backend/runtime_helpers.rb +0 -542
- data/lib/milk_tea/core/c_backend/type_collectors.rb +51 -204
- data/lib/milk_tea/core/c_backend.rb +2 -0
- data/lib/milk_tea/core/compatibility_helpers.rb +1 -1
- data/lib/milk_tea/core/lowering/async/lowering.rb +147 -141
- data/lib/milk_tea/core/lowering/block.rb +759 -725
- data/lib/milk_tea/core/lowering/expressions.rb +94 -0
- data/lib/milk_tea/core/lowering/loops.rb +49 -0
- data/lib/milk_tea/core/lowering/resolve.rb +221 -214
- data/lib/milk_tea/core/lowering/utils.rb +0 -222
- data/lib/milk_tea/core/module_loader.rb +29 -48
- data/lib/milk_tea/core/parser/declarations.rb +2 -2
- data/lib/milk_tea/core/parser/recovery.rb +1 -1
- data/lib/milk_tea/core/parser.rb +1 -1
- data/lib/milk_tea/core/semantic_analyzer/expressions.rb +3 -120
- data/lib/milk_tea/core/semantic_analyzer/foreign_functions.rb +116 -113
- data/lib/milk_tea/core/semantic_analyzer/generics.rb +346 -343
- data/lib/milk_tea/core/semantic_analyzer/statements.rb +37 -12
- data/lib/milk_tea/core/types/predicates.rb +501 -499
- data/lib/milk_tea/core/types/visitor.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 +15 -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.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Long (Teefan) Tran
|
|
@@ -195,6 +195,7 @@ files:
|
|
|
195
195
|
- lib/milk_tea/core/c_backend/control_flow_emission.rb
|
|
196
196
|
- lib/milk_tea/core/c_backend/expressions.rb
|
|
197
197
|
- lib/milk_tea/core/c_backend/feature_detection.rb
|
|
198
|
+
- lib/milk_tea/core/c_backend/format_helpers.rb
|
|
198
199
|
- lib/milk_tea/core/c_backend/reachability.rb
|
|
199
200
|
- lib/milk_tea/core/c_backend/reinterpret.rb
|
|
200
201
|
- lib/milk_tea/core/c_backend/runtime_helpers.rb
|
|
@@ -401,6 +402,7 @@ files:
|
|
|
401
402
|
- std/binary.mt
|
|
402
403
|
- std/binary_heap.mt
|
|
403
404
|
- std/bitset.mt
|
|
405
|
+
- std/blackboard.mt
|
|
404
406
|
- std/box2d.mt
|
|
405
407
|
- std/bytes.mt
|
|
406
408
|
- std/c/box2d.mt
|
|
@@ -463,6 +465,8 @@ files:
|
|
|
463
465
|
- std/cgltf.mt
|
|
464
466
|
- std/cjson.mt
|
|
465
467
|
- std/cli.mt
|
|
468
|
+
- std/cmd.mt
|
|
469
|
+
- std/color.mt
|
|
466
470
|
- std/cookie.mt
|
|
467
471
|
- std/counter.mt
|
|
468
472
|
- std/crypto.mt
|
|
@@ -486,8 +490,10 @@ files:
|
|
|
486
490
|
- std/graph.mt
|
|
487
491
|
- std/gzip.mt
|
|
488
492
|
- std/hash.mt
|
|
493
|
+
- std/htn.mt
|
|
489
494
|
- std/http.mt
|
|
490
495
|
- std/http/server.mt
|
|
496
|
+
- std/input.mt
|
|
491
497
|
- std/intern.mt
|
|
492
498
|
- std/iter.mt
|
|
493
499
|
- std/jobs.mt
|
|
@@ -526,6 +532,7 @@ files:
|
|
|
526
532
|
- std/net/stun.mt
|
|
527
533
|
- std/net/sync.mt
|
|
528
534
|
- std/net/turn.mt
|
|
535
|
+
- std/noise.mt
|
|
529
536
|
- std/oauth2.mt
|
|
530
537
|
- std/option.mt
|
|
531
538
|
- std/ordered_map.mt
|
|
@@ -533,6 +540,7 @@ files:
|
|
|
533
540
|
- std/path.mt
|
|
534
541
|
- std/pcre2.mt
|
|
535
542
|
- std/pcre2/runtime.mt
|
|
543
|
+
- std/pool.mt
|
|
536
544
|
- std/priority_queue.mt
|
|
537
545
|
- std/process.mt
|
|
538
546
|
- std/queue.mt
|
|
@@ -554,6 +562,7 @@ files:
|
|
|
554
562
|
- std/sdl3/runtime.mt
|
|
555
563
|
- std/serialize.mt
|
|
556
564
|
- std/set.mt
|
|
565
|
+
- std/signal.mt
|
|
557
566
|
- std/simd.mt
|
|
558
567
|
- std/sparse_set.mt
|
|
559
568
|
- std/spatial.mt
|
|
@@ -567,6 +576,7 @@ files:
|
|
|
567
576
|
- std/stb_vorbis.mt
|
|
568
577
|
- std/stdio.mt
|
|
569
578
|
- std/steamworks.mt
|
|
579
|
+
- std/steering.mt
|
|
570
580
|
- std/str.mt
|
|
571
581
|
- std/string.mt
|
|
572
582
|
- std/sync.mt
|
|
@@ -575,11 +585,14 @@ files:
|
|
|
575
585
|
- std/testing.mt
|
|
576
586
|
- std/thread.mt
|
|
577
587
|
- std/time.mt
|
|
588
|
+
- std/timer.mt
|
|
578
589
|
- std/tls.mt
|
|
579
590
|
- std/toml.mt
|
|
580
591
|
- std/tracy.mt
|
|
592
|
+
- std/tween.mt
|
|
581
593
|
- std/uri.mt
|
|
582
594
|
- std/url.mt
|
|
595
|
+
- std/utility.mt
|
|
583
596
|
- std/vec.mt
|
|
584
597
|
- std/zstd.mt
|
|
585
598
|
homepage: https://teefan.github.io/mt-lang/
|
|
@@ -589,7 +602,7 @@ metadata:
|
|
|
589
602
|
homepage_uri: https://teefan.github.io/mt-lang/
|
|
590
603
|
source_code_uri: https://github.com/teefan/mt-lang
|
|
591
604
|
post_install_message: |
|
|
592
|
-
Milk Tea 0.3.
|
|
605
|
+
Milk Tea 0.3.5 installed!
|
|
593
606
|
|
|
594
607
|
System requirements:
|
|
595
608
|
- A C compiler (gcc or clang) must be available on PATH
|