Built-in functions are available in every Chasm file without any import. They are implemented in the runtime (chasm_rt.h) and called directly from generated C code.
Math
These functions operate on float unless noted. Integer arguments are automatically widened.
| Function | Returns | Description |
|---|---|---|
abs(v) | float | Absolute value. abs(-3.5) → 3.5 |
sqrt(v) | float | Square root. sqrt(9.0) → 3.0 |
pow(b, e) | float | b raised to the power e. pow(2.0, 10.0) → 1024.0 |
sin(v) | float | Sine of v in radians |
cos(v) | float | Cosine of v in radians |
tan(v) | float | Tangent of v in radians |
atan2(y, x) | float | Angle in radians from the origin to (x, y). Use instead of atan to handle all quadrants |
floor(v) | float | Round down to nearest integer. floor(3.7) → 3.0 |
ceil(v) | float | Round up to nearest integer. ceil(3.2) → 4.0 |
round(v) | float | Round to nearest integer. round(3.5) → 4.0 |
fract(v) | float | Fractional part. fract(3.7) → 0.7 |
sign(v) | float | -1.0 if negative, 0.0 if zero, 1.0 if positive |
min(a, b) | float | Smaller of two values |
max(a, b) | float | Larger of two values |
clamp(v, lo, hi) | float | Restrict v to the range [lo, hi]. clamp(150.0, 0.0, 100.0) → 100.0 |
wrap(v, lo, hi) | float | Wrap v into [lo, hi). Useful for looping angles |
snap(v, step) | float | Round v to the nearest multiple of step. snap(7.3, 4.0) → 8.0 |
scale(v, factor) | float | Multiply v by factor. Useful with |> |
lerp(a, b, t) | float | Linear interpolation. lerp(0.0, 10.0, 0.3) → 3.0. t=0 returns a, t=1 returns b |
smooth_step(a, b, t) | float | Hermite interpolation, starts and ends slowly, eases in the middle |
smoother_step(a, b, t) | float | 5th-order interpolation, even smoother than smooth_step |
ping_pong(t, len) | float | Bounce t back and forth between 0 and len. Useful for pulsing effects |
move_toward(cur, target, step) | float | Move cur toward target by at most step. Never overshoots |
angle_diff(a, b) | float | Shortest signed angle difference between two angles in radians. Handles wrap-around |
deg_to_rad(d) | float | Convert degrees to radians. deg_to_rad(180.0) → 3.14159... |
rad_to_deg(r) | float | Convert radians to degrees |
Common patterns
# Clamp player position to screen
@player_x = clamp(@player_x + dx * dt, 0.0, screen_w - player_w)
# Smooth follow camera
@cam_x = lerp(@cam_x, @target_x, 5.0 * dt)
# Rotate smoothly toward target angle
@angle = @angle + angle_diff(@angle, @target_angle) * 8.0 * dt
# Pulsing scale effect
scale = 1.0 + sin(@time * 4.0) * 0.05Vector Math
2D vector operations, all take component pairs rather than a struct type:
| Function | Returns | Description |
|---|---|---|
vec2_len(x, y) | float | Length (magnitude) of vector (x, y) |
vec2_dot(ax, ay, bx, by) | float | Dot product. Positive means same direction, negative means opposite |
vec2_dist(ax, ay, bx, by) | float | Distance between points (ax, ay) and (bx, by) |
vec2_angle(x, y) | float | Angle of vector in radians. vec2_angle(1.0, 0.0) → 0.0 |
vec2_cross(ax, ay, bx, by) | float | 2D cross product (scalar). Sign tells you which side of the line |
vec2_norm_x(x, y) | float | X component of the normalized (unit length) vector |
vec2_norm_y(x, y) | float | Y component of the normalized (unit length) vector |
# Move entity toward target at constant speed
dx = target_x - @enemy_x
dy = target_y - @enemy_y
dist = vec2_len(dx, dy)
if dist > 0.0 do
@enemy_x = @enemy_x + vec2_norm_x(dx, dy) * speed * dt
@enemy_y = @enemy_y + vec2_norm_y(dx, dy) * speed * dt
endType Conversion
| Function | Returns | Description |
|---|---|---|
to_int(v) | int | Float → int. Truncates toward zero. to_int(3.9) → 3 |
to_float(v) | float | Int → float. to_float(7) → 7.0 |
to_bool(v) | bool | Int → bool. 0 is false, anything else is true |
Chasm never implicitly converts between int and float. If the compiler gives you a type mismatch, one of these is the fix.
Color
Colors in Chasm are packed 32-bit integers in 0xRRGGBBAA format, red, green, blue, alpha, each 0–255.
| Function | Returns | Description |
|---|---|---|
rgb(r, g, b) | int | Pack RGB into 0xRRGGBBFF (fully opaque) |
rgba(r, g, b, a) | int | Pack RGBA into 0xRRGGBBAA |
color_r(c) | int | Extract red channel (0–255) |
color_g(c) | int | Extract green channel (0–255) |
color_b(c) | int | Extract blue channel (0–255) |
color_a(c) | int | Extract alpha channel (0–255) |
color_lerp(a, b, t) | int | Interpolate between two packed colors. t=0 returns a, t=1 returns b |
color_mix(a, b, t) | int | Alias for color_lerp |
red = rgb(255, 0, 0) # 0xff0000ff
semi = rgba(255, 0, 0, 128) # 50% transparent red
flash = color_lerp(red, 0xffffffff, @flash_t)Bitwise
All bitwise functions operate on int:
| Function | Returns | Description |
|---|---|---|
bit_and(a, b) | int | Bitwise AND. bit_and(0b1010, 0b1100) → 0b1000 |
bit_or(a, b) | int | Bitwise OR |
bit_xor(a, b) | int | Bitwise XOR. Toggle bits |
bit_not(v) | int | Bitwise NOT (complement) |
bit_shl(v, n) | int | Shift v left by n bits, multiply by 2ⁿ |
bit_shr(v, n) | int | Shift v right by n bits, divide by 2ⁿ |
# Check a flag
flags = 0b00001101
if bit_and(flags, 0b0100) != 0 do
print("flag 2 is set")
end
# Set a flag
flags = bit_or(flags, 0b0010)
# Clear a flag
flags = bit_and(flags, bit_not(0b0100))String Conversion
| Function | Returns | Description |
|---|---|---|
int_to_str(v) | string | Integer to decimal string. int_to_str(42) → "42" |
float_to_str(v) | string | Float to string. float_to_str(3.14) → "3.14" |
bool_to_str(v) | string | Bool to string. bool_to_str(true) → "true" |
str_from_char(c) | string | Byte value to 1-character string. str_from_char(65) → "A" |
String interpolation "#{x}" calls these automatically, so explicit calls are rarely needed.
I/O and Debug
| Function | Description |
|---|---|
print(x) | Print x followed by a newline. Works on int, float, bool, string |
log(x) | Alias for print |
assert(cond) | Abort the process if cond is false. Use for invariants |
todo() | Mark a code path as not yet implemented, aborts with a message |
defp get_tier(score :: int) :: string do
if score < 0 do
assert(false) # score cannot be negative
end
if score < 100 do return "bronze" end
if score < 500 do return "silver" end
return "gold"
endFile I/O
| Function | Returns | Description |
|---|---|---|
file_read(path) | string | Read entire file contents into the persistent arena |
file_write(path, content) | Overwrite file with string | |
file_exists(path) | bool | Check whether a file exists at path |
file_read allocates into the persistent arena, the result is valid for the life of the process. Use it in on_init for config files, level data, and other assets:
@level_data :: persistent = ""
def on_init() do
if file_exists("levels/1.json") do
@level_data = file_read("levels/1.json")
end
end