Skip to content

Extendible s-expression scripting language enabling users to safely mod Roblox games themselves.

License

Notifications You must be signed in to change notification settings

insitux/rbxts-Insitux

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

37 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Insitux logo Extensible scripting language written in portable TypeScript.
Website Try online Talk with us Discord logo

Usage

Include https://github.com/insitux/rbxts-Insitux into your Roblox-TS project: npm i @rbxts/insitux

Exposed are invoke() and invokeFunction(). Both require a Ctx instance, along with a generated source ID.
Further explanation can be found in the docstring of most functions and types like invoke, Ctx, symbols, etc.

export type Ctx = {
  set: (key: string, val: Val) => undefined | string;
  get: (key: string) => ValOrErr;
  exe: (name: string, args: Val[]) => ValOrErr;
  functions: ExternalFunction[];
  print: (str: string, withNewline: boolean) => void;
  env: Env;
  loopBudget: number;
  rangeBudget: number;
  callBudget: number;
  recurBudget: number;
};
  • set and get should be used to directly write/read values in your game.
  • functions lets you define your own Insitux functions, with the same arity and type-checking as internal operations!
  • exe is used to handle function calls any time Insitux fails to dereference an expression head as something internal or previously defined through Ctx.functions[]. For example (abc 123), unless abc is an already defined let/var/function it will call exe with abc as name, and [{t: "num" v: 123}] as args.
  • print is called when print or print-str is used within Insitux
  • env persists user defined variables and functions.
  • The budgets set a limit on looping, range creation, function calls and explicit recurs. This will vary between games so start with a safe 1000 and increase steadily.

If anybody could improve this guide please make a PR!

Various examples

; Test if 2D point is inside 2D area
(function inside-2d? X Y areaX areaY areaW areaH
  (and (<= areaX X (+ areaX areaW))
       (<= areaY Y (+ areaY areaH))))

(inside-2d? 50 50 0 0 100 100)  → true
(inside-2d? 50 150 0 0 100 100) → false


; Recursive Fibonacci solver
(function fib n
  (if (< n 2) n
      (+ (fib (dec n))
         (fib (- n 2)))))

(fib 13) → 233

; and iterative

(function fib n
  (when (zero? n) (return 0))
  (let a 1 b 0)
  (loop n i
    (let t (+ a b) a b b t)))

(fib 35) → 9227465


; FizzBuzz with match syntax
(function fizzbuzz n
  (match (map (rem n) [3 5])
    [0 0] "FizzBuzz"
    [0 _] "Fizz"
    [_ 0] "Buzz"
    n))

(map fizzbuzz (range 10 16))
→ ["Buzz" 11 "Fizz" 13 14 "FizzBuzz"]


; Filter for vectors and strings above a certain length
(filter 2 [[1] [:a :b :c] "hello" "hi"])
→ [[:a :b :c] "hello"]


; Flatten a vector one level deep
(.. .. vec [[0 1] 2 3 [4 5]])
→ [0 1 2 3 4 5]


; Triple every vector item, four different ways
(for * [0 1 2 3 4] [3])
(map #(* 3 %) [0 1 2 3 4])
(map @(* 3) [0 1 2 3 4])
(map (* 3) [0 1 2 3 4])
→ [0 3 6 9 12]


; Primes calculator
(reduce
  (fn primes num
    (if (find zero? (map (rem num) primes))
      primes
      (append num primes)))
  [2]
  (range 3 1000))


; Generate random strong password
(-> #(map rand-int [97 65 48 33] [123 91 58 48])
    (times 4)
    flatten
    shuffle
    (map char-code)
    (.. str))

→ "d$W1iP*tO9'V9(y8"


; Palindrome checker
;Note: returning non-false or non-null is truthy in Insitux
(function palindrome? x
  (.. and (map = x (reverse x))))
;or
(function palindrome? x
  (= x (reverse x))) ;Works even for vectors due to deep equality checks

(palindrome? "aabbxbbaa") → true
(palindrome? "abcd")      → false
(palindrome? [0 1 2])     → false
(palindrome? [2 1 2])     → true


; Matrix addition, subtraction, transposition
(var A [[3  8] [4  6]]
     B [[4  0] [1 -9]])

(map (map +) A B)
→ [[7 8] [5 -3]]

(var M [[2 -4] [7 10]])

(map (map -) M)
→ [[-2 4] [-7 -10]]

(var M [[0 1 2] [3 4 5]])

(@(.. map vec) M)
→ [[0 3] [1 4] [2 5]]


; Find first repeated letter
(function find-two-in-row text
  (-> (map (.. ==) text (skip 1 text))
      (find val)))

(find-two-in-row "Hello") → "l"


; Add thousands separator
(var thousands (comp str reverse (partition 3) reverse (join ",")))
(thousands 1234567890) → "1,432,765,098"

; Clojure's comp
(function comp f
  (let funcs (sect args))
  #(do (let 1st (... f args))
       (reduce #(%1 %) 1st funcs)))

(map (comp + inc) [0 1 2 3 4] [0 1 2 3 4])
→ [1 3 5 7 9]


; Time a function call
(function measure
  (let [start result end] [(time) (... . args) (time)])
  (str result " took " (- end start) "ms"))

(measure fib 35)
→ "9227465 took 22914ms"


;Insitux quine
(#(join(char-code 34)[% %(char-code 41)])"(#(join(char-code 34)[% %(char-code 41)])")
→ (#(join(char-code 34)[% %(char-code 41)])"(#(join(char-code 34)[% %(char-code 41)])")


; Display the Mandelbrot fractal as ASCII
(function mandelbrot width height depth
  (.. str (for #(do
    (let c_re (/ (* (- % (/ width 2)) 4) width)
         c_im (/ (* (- %1 (/ height 2)) 4) width))
    (let x 0 y 0 i 0)
    (while (and (<= (+ (** x) (** y)) 4)
                (< i depth))
      (let x2 (+ c_re (- (** x) (** y)))
           y  (+ c_im (* 2 x y))
           x  x2
           i  (inc i)))
    (str ((zero? %) "\n" "") (i "ABCDEFGHIJ ")))
    (range width) (range height))))

(mandelbrot 56 32 10)


; Convert nested arrays and dictionaries into HTML
(function vec->html v
  (if! (vec? v) (return v))
  (let [tag attr] v
       from-key   @((key? %) (-> % str sect))
       has-attr   (dict? attr)
       make-attr  (fn [k v] (str " " (from-key k) "=\"" v "\""))
       attr       (if has-attr (map make-attr attr) "")
       tag        (from-key tag)
       body       (sect v (has-attr 2 1))
       body       (map vec->html body))
  (if (["link" "meta" "input" "img"] tag)
    (.. str "<" tag attr " />")
    (.. str "<" tag attr ">" body "</" tag ">")))

(vec->html
  [:div
    [:h2 "Hello"]
    [:p "PI is " [:b (round 2 PI)] "."]
    [:p "Find out about Insitux on "
       [:a {:href "https://insitux.github.io"}
          "Github"]]])
→ "<div><h2>Hello</h2><p>PI is <b>3.14</b>.</p><p>Find out about Insitux on <a href=\"https://insitux.github.io\">Github</a></p></div>"


; Neural network for genetic algorithms with two hidden layers
(function sigmoid (/ 1 (inc (** E (neg %)))))
(function m (< .8 (rand)))

(function make-brain  num-in num-out num-hid
  (let make-neuron #{:bias 0 :weights (repeat 1 %)})
  [(repeat (make-neuron num-in)  num-hid)
   (repeat (make-neuron num-hid) num-hid)
   (repeat (make-neuron num-hid) num-out)])

(function mutate  brain
  (let mutate-neuron
    #{:bias    ((m) (rand -2 2) (:bias %))
      :weights (map @((m) (rand -1 1)) (:weights %))})
  (map (map mutate-neuron) brain))

(function neuron-think  inputs neuron
  (let weighted (map * (:weights neuron) inputs)
       avg      (average weighted))
  (sigmoid (+ avg (:bias neuron))))

(function think  brain inputs
  (reduce (fn in layer (map @(neuron-think in) layer))
          inputs brain))

(var brain (mutate (make-brain 5 5 5)))
(-> (repeat #(rand-int) 5)
   @(think brain)
    (map @(round 2)))
→ [0.23 0.41 0.63 0.64 0.57]

About

Extendible s-expression scripting language enabling users to safely mod Roblox games themselves.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published