NC Scripting Language
The NC Scripting Language (NC Script, or NCSL) is a new piece of technology being pushed by NC Tech Department to standardize programming and communication of all NovusCorp-grade electronic devices. Its syntax is a mixture of PHP, C++, and JavaScript. Most implementations of NC Script are not object-oriented and do not allow the definition of classes, instead, rely on ROBUST™ memory management system to store entities in a dynamic data tree. NC Script does allow the in-line definition of functions, however.
It is important to note that NC Scripting should not be treated as BYOND coding. NC Scripting handles some things differently than BYOND does.
Contents 1 Simple Guide to Using Scripts 2 Syntax Guide 2.1 Variables 2.2 Functions 2.3 Code Blocks 2.4 Lists 2.5 Conditionals 3 Math 4 NT Deluxe Namespaces 4.1 Number 4.2 String 4.3 List 4.4 Miscellaneous Definitions 4.5 Prefab Variables 5 Traffic Control Systems Implementation 5.1 Realtime signal modification 5.2 Functions 5.2.1 signal() 5.2.2 broadcast() 5.2.3 remote_signal() 5.2.4 mem() 6 Examples 6.1 Chat calculator 6.2 Magic 8-Ball
Simple Guide to Using Scripts Get to the Telecommunications Control Room Open up the Telecommunications Traffic Control Console Authorize yourself access by clicking on Insert ID while holding your ID [Scan] for servers Click on a server which radio channel you wish to alter [Edit Code] to see the server's code Type your code into the window Press Compile Close the code window Change Signal Execution to ALWAYS Congratulations, you're done! Repeat steps 5 to 10 for each desired channel Syntax Guide NT Script follows a simple-to-use syntax designed for users of all levels of programming expertise. Whitespace is ignored, semicolon break points are required, and curly brackets are required.
Variables Variables are used to temporarily store any form of data that can be accessed somewhere else in the code. For simplicity, we'll ignore the fact that you can only use variables in children scope. Here is how you create a variable:
myVariable = 5; You can alternatively assign the same variable a text value, or a string.
myVariable = “Hello world!”;
Functions Functions can be used and defined dynamically. There are different pre-defined functions for each NTSL implementation, however the basic ones will remain the same. Here is how you use a function:
$myVariable = getNumber(); In this example, $myVariable is assigned whatever value getNumber() returns. Each function returns a value, even if a value return is explicitly not defined. Here are some more examples of how to use functions:
broadcast($myVariable); broadcast(“Hello world!”); broadcast(“Griffing assistants in T-minus ” + $myVariable + “ seconds.”);
You can also define your own functions, using the def keyword.
def getNumber() {
return 5;
}
Code Blocks Blocks of code are called when a specific piece of code signals that it is a representation of a block of code. Variables defined in one code block cannot be applied or changed in other nonrelated code blocks; this is known as scope. For example:
myGlobalVariable = getNumber();
while(myGlobalVariable != 0) {
myLocalVariable = 0; myGlobalVariable = myLocalVariable;
}
myLocalVariable = 50; this is invalid; myLocalVariable does not exist in this scope Once the interpreter reads the closing bracket, it destroys all variable definitions within the scope, therefore you cannot use any of the variables that existed in that particular block of code. Lists You can create new lists using list() and access elements using the [] operator. my_list = list(“something”, “something else”, “lynch the signal tech”); sig.content += my_list[1]; adds “something” You can also create associative lists.
my_list = list(“a” = “something”, “b” = “something else”); sig.content += my_list[“a”]; adds “something” You can also use the [] operator on strings some_string = “something”; sig.content += some_string[4]; adds “e” since its the 4th character of “something” Conditionals The while() loop in the previous example is considered a conditional because it only continues executing when the condition between the parentheses is true. The != is known as a relational operator which returns true to the interpreter if myGlobalVariable does not equal 0. It can be read as “while myGlobalVariable does not equal 0, execute the following block of code”.
Here is a list of all relational operators:
== : Equals != : Does not equal < : Less than
: Greater than
⇐ : Less than or equal to
= : Greater than or equal to
Relational operators can be used in if(), and elseif(), statements, which are used the following way:
if($myVariableNumber == 50) if my number is 50 { code block } elseif($myVariableNumber ⇐ 30) if not, is my number 30 or less? { code block } else if not either 50 OR 30 or more, do this instead { code block } Math The math operators are for the most part pretty standard, the only one to watch out for is division which is not the expected / (as that would clash with comments in the naive ntsl parser)
* is multiplication + is addition - is subtraction / is division
NT Deluxe Namespaces Nanotrasen will constantly add new universal functions and features to NTSL, here are a few of them:
Number Syntax Returns Description prob(number) number Returns nonzero is the probability succeeded. Returns zero if the probability failed. sqrt(number) number Returns the square root of Arg.1. abs(number) number Returns the magnitude of Arg.1. floor(number) number Returns the Arg.1 rounded down to nearest integer. ceil(number) number Returns the Arg.1 rounded up to nearest integer. round(number) number Returns the Arg.1 rounded to nearest integer. 1.5 becomes 2, 1.49 becomes 1. clamp(number, number, number) number Clamps Arg.1 between min(Arg.2) and max(Arg.3). clamp(30, -30, 25) = 25 inrange(number, number, number) number Returns 1 if Arg.1 is inbetween min(Arg.2) and max(Arg.3). min(…) number Returns the smallest value of all arguments. max(…) number Returns the largest value of all arguments. tostring(number) string Returns a sting value of the number. rand(number, number) number Returns a random integer that is inbetween min(Arg.1) and max(Arg.2). rand(number) number Returns a random integer that is inbetween 0 and max(Arg.1). rand() number Returns a random float that is inbetween 0 and 1. randseed(number) Resets the RNG with this value. sin(value) number Returns the sine of the value. cos(value) number Returns the cosine of the value. asin(value) number Returns the arcsine of the value. acos(value) number Returns the arcossine of the value. log(value) number Returns the logarithm of the value. String A string is a sequence of characters. A string is defined by two quote marks. “Hello world!” is a string. A strings length is the amount of letters and blankspaces it contains. Syntax Returns Description find(string, string) number Returns the position of the first occurrence of Arg.2 in Arg.1 or 0 if no matches were found. length(string) number Returns the length of the string. substr(string, number, number) string Returns a substring from Arg.1 based on start (Arg.2) to end (Arg.3). replace(string, string, string) string Returns a instance of the string (Arg.1) where all occurences of Arg.2 are replaced by Arg.3. lower(string) string Converts the string to lowercase. upper(string) string Converts the string to uppercase. proper(string) string Converts the first character to uppercase, rest to lowercase. explode(string, string) list This will split the string(Arg.1) at every place that matches the separator(Arg.2) in to a list. explode(“Hello there young friend”, “ ”), will produce a list with 4 indices, “Hello”, “there”, “young”, “friend”. This is very useful for chat commands: if(at(explode($content, “ ”),1)==“/bot”){dostuff} will make dostuff only run if the first word was /bot. repeat(string, number) string Repeats the string n(Arg.2) amount of times. reverse(string) string Reverses the string. tonum(string) number Converts the string in to a number. List Vectors are resizeable data containers for storing any form of entities inside. They are very useful for serving as lists; their members can be instantly accessed provided you have an appropriate position. People call them arrays in other languages. Vector indexes in NTSL start at 1, unlike in other languages where arrays are usually zero-indexed.
Syntax Returns Description list(…) list Returns a listwith a given number of entities. You can add an infinite number of entries, or no entries at all. my_list.Copy(number, number) list Returns a new list based on my_list, ranging from minimum index Arg.1 to Arg.2. my_list.Add(…) Adds Arg.1 (and every item after) to the end of the list. Deprecated by the += operator. my_list.Remove(…) Loops through the list and deletes the items matching the Args. my_list.Cut(number, number) Cuts out entries from Arg.1 to Arg.2 in my_list. my_list.Swap(number, number) Swaps the entries's position at Arg.1 and Arg.2 in my_list. my_list.Insert(number, var) Inserts Arg.2 into my_list at index Arg.1. my_list.Find(list, var) var Searches my_list for Arg.1, returns 0 if not found. length(list) number Returns the length of the list. (amount of indices) my_list.Join(string) string This will join the my_list in a string separating the indices with the separator(Arg.1) and returns that string. Miscellaneous Definitions Syntax Returns Description pick(…) var Returns a randomly-selected entry from the parameters. Note: list parameters will add their entries into the “raffle”. The function will never return a list. time() number Returns the real time of the server in a number. You can then use this to see how much time has passed since the code has last been run via mem(). timestamp(format) string Returns a string of the time, formatted by the parameter. E.g: “DDD MMM DD hh:mm:ss YYYY” or “hh:mm:ss” or “DD MM YY”. Prefab Variables PI = 3.141592653; E = 2.718281828; SQURT2 = 1.414213562; FALSE = 0; true/false are just Boolean shortcuts to 0 and 1 TRUE = 1; NORTH = 1; SOUTH = 2; EAST = 4; WEST = 8; channels.common = 1459 channels.science = 1351 channels.command = 1353 channels.medical = 1355 channels.engineering = 1357 channels.security = 1359 channels.supply = 1347 channels.service = 1349 languages.human = 1 languages.monkey = 2 languages.robot = 4 languages.polysmorph = 8 languages.draconic = 16 languages.beachtongue = 32 filter_types.robot = “robot” filter_types.loud = “yell” filter_types.emphasis = “italics” filter_types.wacky = “sans” filter_types.commanding = “command_headset” Traffic Control Systems Implementation The Telecommunications system is directly tied to the TCS scripting implementation. It comes with the following functions and features. Realtime signal modification If the code is set to execute automatically, signals will first execute the process_signal function. def process_signal(sig) { sig.content += “ HONK”; return sig; not returning anything will cause the signal to not be broadcast. } Signal information is stored in the following variables:
sig.source the source of the signal sig.uuid the name of the person the AI will track if it tries to trace the transmission sig.content the content of the signal sig.freq the frequency of the signal sig.job the job (only for radio messages) of the operator sig.language the language of the signal. Can be any of HUMAN, MONKEY, ALIEN, ROBOT, SLIME or DRONE. Or a combination of them sig.filters The voice filter of the signal. Includes bolding, italics, as well as silicon and wacky fonts. These must be given as a list! sig.pass Whether the signal will be broadcasted. Is a boolean, set to 0 to stop the signal from passing. sig.say The verb used in a radio messages ending in “.” sig.ask The verb used in messages ending in “?”. Example: COMMON SERVER asks, “Why?” sig.exclaim The verb used in a radio messages ending in “!” Note that having more exclamation points changes it to “$yell”. sig.yell The verb used in a radio messages ending in “!!” or more exclamation points. By default, these messages are bolded. Functions TCS also comes with the following functions (parameters may be ignored for automatic assignment):
signal() signal(message, frequency, source, job) Creates a signal with the following parameters.
message: The radio message frequency: The frequency to broadcast to source: The name of the broadcaster. If the source name is not in a server-side voice databank (voice analysis is performed every time a person speaks over a channel) the name will appear in UPPERCASE and Italicized to indicate a synthesized voice job job: The job of the orator.
Examples:
sig = signal(“Hello world!”); defaults: frequency: 1459 source: the server name job: None
broadcast(signal(“HELP GRIEFF”, 1459, “Burer”, “Security Officer”)); broadcast() broadcast(sig) Broadcast a signal, created using the signal() function
remote_signal() remote_signal(frequency, code) Sends a signal to the frequency, with the code. This works exactly like a remote signaler.
frequency: The frequency to send to. code: The code to attach to the signal.
Examples:
remote_signal(1359, 25); defaults: frequency: 1459 code: 30
mem() mem(key, value) Variables declared in a script expire after the script has finished executing (duh). The mem function allows you to save persistent information to the server's memory to be retrieved by future executions of the script. Each telecommunications server contains its own separate databank, which is basically a hash table/dictionary, a data structure consisting of a set of key-value pairs. When called with just the key as an argument, mem will return the associated value. When called with two arguments, mem will set the value associated with the key.
key: A string used to identify the variable to be saved. value: The information you want to store for future use. Can be any type.
Examples:
sig.source = “Jarsh Mellow”; mem(sig.source + “'s Mom”); returns the value associated with the key “Jarsh Mellow's Mom”. Returns null/0 if not found mem(sig.source + “'s Mom”, “Lindsay Donk”); sets the value associated with the key “Jarsh Mellow's Mom” to “Lindsay Donk”. Examples Here are a few examples. You can find more useful snippets here.
Chat calculator A simple chat calculator. Type “/calc 1+1” in chat and watch the magic happen. NB: division is not implemented due to budget cuts.
def process_signal(sig) {
$expld1 = explode(sig.content, " "); if($expld1[1] == "/calc") { $s = $expld1[2]; $found = 0; if(find($s, "+") && $found == 0) { $expld2 = explode($s, "+"); broadcast($s + " = " + tostring(tonum($expld2[1]) + tonum($expld2[2])), $freq, "LINDSAY", "CALCULATER"); $found = 1; } if(find($s, "-") && $found == 0) { $expld2 = explode($s, "-"); broadcast($s + " = " + tostring(tonum($expld2[1]) - tonum($expld2[2])), $freq, "LINDSAY", "CALCULATER"); $found = 1; } if(find($s, "*") && $found == 0) { $expld2 = explode($s, "*"); broadcast($s + " = " + tostring(tonum($expld2[1]) * tonum($expld2[2])), $freq, "LINDSAY", "CALCULATER"); $found = 1; } } return sig;
} Magic 8-Ball A simple Magic 8-Ball that will answer anyone's question. Type in “/8ball <your question>” and you will get a magical response!
def process_signal(sig) {
$explodeString = explode(sig.content, " "); if($explodeString[1] == "/8ball") { //By Giacomand $8ball = pick("It is certain", "It is decidedly so", "Without a doubt", "Yes – definitely", "You may rely on it", "As I see it, yes", "Most likely", "Outlook good", "Yes", "Signs point to yes", "Reply hazy, try again","Ask again later","Better not tell you now","Cannot predict now","Concentrate and ask again","Don't count on it","My reply is no", "My sources say no","Outlook not so good","Very doubtful"); $content = substr(sig.content, 7, length($content)+1); broadcast(signal("Magic 8-Ball... " + $content, $freq, $source, $job)); broadcast(signal($8ball + ".", $common, "Magic 8-Ball", "Magic 8-Ball")); return null; } return sig;
}
Overview NTSL2+ is the programming language used aboard the station for modular computers and telecommunications, you can design a lot of interesting things with it, this guide will act as a starting place and reference for enterprising programmers aboard the Aurora.
Functions Reference Global Functions Global Functions These functions can typically be used globally. print(x) Prints its argument to the output and appends a new line. write(x) Prints its argument to the output. type(x) Returns the type of x. tostring(x) Returns X as string. tonumber(x) Returns X as number.
Math Library Math Library An assortment of math related functions. math.sin(x) Returns the sine of X. Probably uses radians, maybe. math.cos(x) Returns the cosine of X. math.tan(x) Returns the tangent of X math.asin(x) Returns the inverse sine of X, as in, what angle gives a sine of X. X is between -1 and 1. math.acos(x) Inverse cosine function, x is between -1 and 1 math.atan(x, y) OR math.atan(x) Inverse tangent function, either from a pair of coordinates (x and y) or a slope (x) math.floor(x[, r]) Rounds X to the greatest integer lower than it. Rounds to r places, or after the decimal point by default. math.atan(x, y) OR math.atan(x) Inverse tangent function, either from a pair of coordinates (x and y) or a slope (x) math.floor(x[, r]) Rounds X to the greatest integer lower than it. Rounds to r places, or after the decimal point by default. math.atan(x, y) OR math.atan(x) Inverse tangent function, either from a pair of coordinates (x and y) or a slope (x) math.floor(x[, r]) Rounds X to the greatest integer lower than it. Rounds to r places, or after the decimal point by default. math.atan(x, y) OR math.atan(x) Inverse tangent function, either from a pair of coordinates (x and y) or a slope (x) math.floor(x[, r]) Rounds X to the greatest integer lower than it. Rounds to r places, or after the decimal point by default. math.acos(x) Inverse cosine function, x is between -1 and 1 math.ceil(x[, r]) Rounds X to the smallest integer greater than it. Rounds to r places, or after the decimal point by default. math.round(x[, r]) Rounds X according to the principle of “round up on 5 or above, round down otherwise” Rounds to r places, or after the decimal point by default. math.max(x, y) Returns the largest of its two arguments. math.clamp(low, num, high) If num is lower than low, returns low. If num is higher than high, returns high. Otherwise, it returns numb. Equivalent to math.max(low, math.min(high, num)) math.random(high o math.random(low, high) math.random(high) returns a random decimal between 0 and high. math.random(low, high) returns a random number between low and high. math.abs(x) Returns the absolute value of X. math.deg(x) Converts x from radians to degrees. math.rad(x) Converts x from degrees to radian. math.pi Pi. String Library String Library
String Library These are strings. string.sub(string, start[, end]) Returns the substring of string from position start to position end. If end is not specified, it is the end of the string. string.match(string, pattern) Searches string for instances of pattern and returns the matched value of the matched groups. If there are multiple, then it returns as a list.. Can use regex. string.gmatch(string, pattern) Returns an iterator function that finds all matches (similar to string.match) in a string. string.gsub(string, pattern, replacement) Replaces all instances of pattern with replacement. Can use regex. string.upper(string) Returns string but uppercase. string.lower(string) Returns string but lowercase. string.reverse(string) Reverses the string.
Term Library Term Library These are terms. term.set_foreground(r, g, b) Sets the text color to (r, g, b). Scaled from 0 - 1. term.get_foreground() Returns the text color. term.set_background(r, g, b) Sets the background color to (r, g, b). Scaled from 0 - 1. term.get_background() Returns the background color. term.set_cursor(x, y) Sets the cursor to the position x, y. The top left is 0, 0. term.set_cursor_x(x) Sets the cursor's x position to x. The left side is 0. term.set_cursor_y(y) Sets the cursor's y position to y. The top line is 0. term.get_cursor(), term.get_cursor_x(), term.get_cursor_y() Returns the cursor's position, the cursor's x position, or the cursor's y position, respectively. term.clear() Clears the screen with the preset background colour. term.write() Same as write(). term.get_size() Gets the size of the terminal. term.get_width() Returns the width of the terminal. term.get_height() Returns the height of the terminal. term.set_topic(x, y, width, height, topic_name) Creates a button/link at (x, y) with width width and height height, and a corresponding topic topic_name. If topic_name begins with ?, it allows you to input text, and the corresponding topic will be “topic_name?input”. If text is written over this with write or similar, this will be cleared.
Syntax Variables must start with a letter, but can otherwise contain any alphanumeric character. Variables can be assigned to with name = value.
Local variables can be made with var name = value or local name = value.
Tables are values that can be indexed and can contain multiple values. They are also sometimes referred to as lists. They are constructed in the following format: {key1 = value1, key2 = value2, key3 = value3…} The final value can have a comma after it, but it is not mandatory. Tables can be indexed as name[index].
Functions can be made in the following format (the default value parameters are optional and can be left out): function funcname(arg1=defaultvalue1, arg2=defaultvalue2){
...code...
} Arguments can have any name a variable can take, and can be assigned default values. Varargs are also usable:
function funcname(... args){...code...}
The various arguments provided to the function will be combined into a list and stored in the local variable args, or whatever name is provided. Brackets for arguments are optional if you have an anonymous function with one argument: funcname = function arg{…code…} They can even be constructed in lambda calculus style (the default value parameters are optional and can be left out): (arg1=defaultvalue1, arg2=defaultvalue2) ⇒ {…code…} In the function style, function can be abbreviated to func. Varargs can also be used in the lambda calculus style. Single variable lambda calculus functions can be further simplified into
arg ⇒ {…code…} Member functions of an object can be called in the form object.function(object, other_arguments) or object::function(other_arguments). These function identically. Strings can be constructed in three ways: “content”, ‘content’, or `content`. These are functionally identical except for in the last case, where expressions in square brackets will be evaluated and inserted into the string. This means that `con[expression]tent` is equivalent to instead performing two concatenation operations and one tostring call, “con” .. tostring(expression) .. “tent” Program Flow/Structure IF/ELSE: IF/ELSE conditionals are part of the main program flow:
if(condition){ ...code… } else { ...code... }
WHEN: WHEN conditionals are similar to IF conditionals, but are asynchronous and occur outside of the main program’s flow. They also expose their arguments to the scope of its block. A typical case is the topic variable which is set in term.topic events.
when(event){ ...code… }
WITH: WITH block exposes a list/table to the scope of its block, typically used for making library referencing easier:
with(event){ ...code... }
An example is used in Telecomms scripts to save the constant references to tcomm:
with(tcomm){ when onmessage{ broadcast(...) } }
FOR: FOR loops have two alternate forms. List Iteration FOR Loop:
for(var in list){ ...code... }
In this form, it iterates over the contents of list, setting var equal to them one at a time. list can instead be an iterator function as well, such as string.gmatch OR Variable Iteration FOR Loop:
for(i=initial; condition; step){ ...code... }
Where i is any variable, initial is the initial value, condition is any condition (presumably involving said variable, but not necessarily), step is some form of increment/decrement such as i++, i–, ++i, –i, etc. This runs the for loop until condition is false, executing step after every iteration.
WHILE loop:
while(condition){ ...code... }
SWITCH block: Evaluates condition, runs whichever code block's label corresponds to that condition or, if none is found, the block labelled default. If a break or return isn’t reached, the program will fall through to the next condition.
switch(condition){ :label1 ...code... :label2 ...code... :default ...code... ... }
Ternary: Evaluates expression, if expression is true returns on_true, otherwise returns on_false.
expression ? on_true : on_false
Eval: A very powerful, very dangerous function. Produces a function from NTSL2+ code contained in a string. Format is eval expression.
The Deoperator: Takes the form of either @operator or @expression. In the case of an operator, returns a function that behaves like that operator (With priority to binary operators). So @+ is equivalent to (a,b)⇒a+b, though runs slightly faster. When an expression is used, this functions as a niladic operator, so is equivalent to ()⇒expression.
+, -, *, /, ^, %, and/&&, or/||, <, >, ⇐, >=, ==, and != all operate as expected.
Concatenation is performed by expr1 .. expr2.
The length of the text representation of a string, or the number of elements in a list, can be found with #expression.
Logical negation is performed with !expression, binary negation is performed with ~expression, decimal unary negation is performed with -expression.
Integer division can be performed with expression1 expression2. Modulo can be performed with expression1 % expression2. Bitwise operators are also available, such as |, &, «, », &, and expression1 ~ expression2 (xor, do not confuse with unary base 2 negation)