NTSL

The NT Scripting Language(NT Script, or NTSL) is a new piece of technology being pushed by NT Tech Department to standardize programming and communication of all Nanotrasen-grade electronic devices. Its syntax is a mixture of PHP, C++, and JavaScript. Most implementations of NT Script are not object-oriented and do not allow the definition of classes, instead, rely on ROBUST(tm) memory management system to store entities in a dynamic data tree. NT Script does allow the in-line definition of functions, however.

*It is important to note that NT Scripting should not be treated as BYOND coding. NT Scripting handles some things differently than BYOND does.*

## Simple Guide to Using Scripts

1. Get to the Telecommunications Control Room
2. Open up the Telecommunications Traffic Control Console
3. Authorize yourself access by clicking on *Insert ID* while holding your ID
4. *[Scan]* for servers
5. Click on a server which radio channel you wish to alter
6. *[Edit Code]* to see the server's code
7. Type your code into the window
8. Press *Compile*
9. Close the code window
10. Change Signal Execution to *ALWAYS*
11. 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

```

```
^ is exponentiation

```

## NT Deluxe Namespaces

Nanotrasen will constantly add new universal functions and features to NTSL, here are a few of them:

### 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.

### 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.

### 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;
}

```

## Useful Scripts

Most of these scripts are compatible, but there are conflicts. The sequence of things is important. Definitely room for improvement. All scripts need the global **def process\_signal(sig){** as a header and **return sig;}** as a footer, unless specified otherwise. e.g.:

```
def process_signal(sig){ // Header.

if(sig.source=="Zion Freeman"){ sig.job="Nerd"; } // Some script.

sig.source+=" ("+sig.job+")"; // More script.

return sig;} // Footer.

```

### Job Indicator

Jobs will appear in brackets after names.

```
sig.source+=" ("+sig.job+")";

```

### Abbr. Job Indicator

Gives abbreviations instead of full titles.

```
//Abbr. Job Indicator - by TheDL

jobs=list("Admiral", "Adm", "Assistant", "Ass", "Atmospheric Technician", "Atmo", "Bartender", "Bar", "Botanist", "Hydr", "Captain", "Cap", "Cargo Technician", "Carg", "Chaplain", "Chap", "Chemist", "Chem", "Chief Engineer", "CE", "Chief Medical Officer", "CMO", "Clerk", "Clrk", "Clown", "Clwn", "Curator", "Cura", "Detective", "Det", "Geneticist", "Gene", "Head of Personnel", "HoP", "Head of Security", "HoS", "Janitor", "Jani", "Lawyer", "Law", "Librarian", "Lib", "Medical Doctor", "MD", "Mining Medic", "Medi", "Paramedic", "Para", "Psychiatrist", "Psyc", "Quartermaster", "QM", "Research Director", "RD", "Roboticist", "Robo", "Scientist", "Sci", "Security Officer", "Sec", "Shaft Miner", "Mine", "Signal Technician", "Sig", "Station Engineer", "Engi", "Tourist", "Tour", "Unassigned", "Unas", "Unknown", "Unkn", "Virologist", "Viro", "Warden", "Ward", "Personal AI", "pAI", "Default Cyborg", "DefB", "Engineering Cyborg", "EngB", "Janitor Cyborg", "JanB", "Medical Cyborg", "MedB", "Miner Cyborg", "MnrB", "Peacekeeper Cyborg", "PceB", "Security Cyborg", "SecB", "Service Cyborg", "SrvB", "Standard Cyborg", "StnB");

if(find(jobs,sig.job)){ sig.job=jobs[find(jobs,sig.job)+1]; }
sig.source+="["+sig.job+"]";

```

### Spam Jammer

Blocks hulkouts and tourettes ticks.

```
if(find(list("RAAAAAAAARGH!!!", "HNNNNNNNNNGGGGGGH!!!",
 "GWAAAAAAAARRRHHH!!!", "NNNNNNNNGGGGGGGGHH!!!",
 "AAAAAAARRRGH!!!", "CUNT", "FUCK", "PISS", "SHIT", "TITS",
 "COCKSUCKER", "MOTHERFUCKER"), sig.content)){ sig.pass=0;}

```

### Anonymous Messages

Messages starting with **/anon** will broadcast under the name "Anonymous".

```
// Anonymous Messages - by TheDL

x=explode(sig.content," ");
if(x[1]=="/anon"){ sig.pass=0;
 broadcast(signal(implode(x-x[1]," "), sig.freq, "Anonymous")); }

// This one preserves language...

x=explode(sig.content," ");
if(x[1]=="/anon"){ sig.pass=0;
 anon=signal(implode(x-x[1]," "), sig.freq, "Anonymous");
 anon.language=sig.language; broadcast(anon); }

// ...this one randomizes filters, too.

x=explode(sig.content," ");
if(x[1]=="/anon"){ sig.pass=0; a=list("italics", "robot", "sans", "yell");
 anon=signal(implode(x-x[1]," "), sig.freq, "Anonymous");
 n=1; while(n<length(a)){ if(prob(50)){ anon.filters+=a[n]; } n+=1; }
 anon.language=sig.language; broadcast(anon); }

```

### Broadcast to All

Messages starting with **/all** will be broadcasted to all departments, and common. Admins hate this, though. Expect to get bwoinked.

```
// Broadcast to All - by TheDL

x=explode(sig.content," ");
freqs=list( 1459, 1447, 1359, 1357, 1355, 1353, 1351, 1349, 1347);
if(x[1]=="/all"){ sig.pass=0; sig.content=implode(x-x[1]," "); n=1;
 while(n<=length(freqs)){ sig.freq=freqs[n]; broadcast(sig); n+=1; } }

```

### Broadcast to Any or All

Messages starting with a channel code will be broadcast to the corresponding department. The channel codes are **/c** for command, **/e** for engineering, **/m** for medical, **/n** for science, **/o** for AI private, **/s** for security, **/u** for supply, and **/v** for service. As above, messages starting with **/all** will be broadcasted to all departments, and common. Again, admins hate this. Expect to get bwoinked.

```
// Broadcast to Any or All - by TheDL

x=explode(sig.content," ");
freqs=list( 1459, 1447, 1359, 1357, 1355, 1353, 1351, 1349, 1347);
codes=list( "/all", "/o", "/s", "/e", "/m", "/c", "/n", "/v", "/u");
if(find(codes,x[1])){ n=find(codes,x[1]); sig.content=implode(x-x[1]," ");
 if(codes[n]!="/all"){ sig.freq=freqs[n]; } else{ sig.pass=0; n=1;
  while(n<=length(freqs)){ sig.freq=freqs[n]; broadcast(sig); n+=1; } } }

```

### Phrase Toggle

Enable or disable a script using a phrase. Any phrase can be used. Add the script to be toggled where indicated. User restricted, message blocked. Remove **&&sig.source=="Your Name"** to let anyone use it. Remove **sig.pass=0;** to not block the message.

```
// Phrase Toggle - By TheDL

toggle="Phrase"; if(find(sig.content,toggle)&& sig.source=="Your Name"){
 sig.pass=0; if(mem(toggle)!=1){ mem(toggle,1); } else{ mem(toggle,0); } }
if(mem(toggle)==1){
// Insert script here.
}

```

### Pun Pun Teller

Say **/pun** to have the Ghost of Pun Pun tell an awful pun!

```
// Pun Pun Teller - by TheDL

exp=explode(sig.content," ");
if(exp[1]=="/pun"){ sig.pass=0;
broadcast(signal(pick("Did you hear about the guy that got cut in half? Don't worry, he's all right now.", "I started a business selling landmines disguised as prayer mats. Prophets are going through the roof!", "Why don't thieves get puns? Because they take things literally.", "My dog has no nose. How does he smell? Awful.", "A man entered ten puns in a pun contest, hoping that one would win. Unfortunately, no pun in ten did."),sig.freq,"The Ghost of Pun Pun"));}

```

## Annoying and Malicious Scripts

### \_ the Hedgehog

\_ the Hedgehog exclaims: "\_ Gotta go fast!"

```
sig.source+=" the Hedgehog";
sig.content+=" Gotta go fast!";
sig.filters=list("italics");

```

### Auto Tourettes

Two versions. First replaces all of a random word in every message. Second randomly replaces entire messages, **prob()** being the percent chance of this. Use **prob(100)** to replace all messages.

```
// Auto Tourettes, for random words...

sig.content=replace(sig.content,pick(explode(sig.content," ")),pick("SHIT", "FUCK", "COCKSUCKER", "BULLSHIT", "CUNT", "MOTHERFUCKER"));

// ...or random messages.

if(prob(20)){ sig.content=pick("SHIT", "FUCK", "COCKSUCKER", "BULLSHIT", "CUNT", "MOTHERFUCKER");}

```

### HONK!

Replace every word of every message with HONK!

```
sig.content=repeat("HONK! ",length(explode(sig.content," "))-1);
sig.content=substr(sig.content, 1, length(sig.content));

```

### La Revolution!

Prevents heads of staff from using the radio.

```
if(find(list("Captain", "Chief Engineer", "Chief Medical Officer", "Head of Personnel", "Head of Security", "Research Director"), sig.job)){ sig.pass=0;}

```

### No Shuttle Calls

Blocks messages containing any of the words on the list.

```
block=list("call", "shuttle", "rogue", "rouge", "malf");
n=1; while(n<=length(block)){ if(find(sig.content,block[n])){ sig.pass=0; } n+=1; }

```

### Forced Singing

Replaces messages with lyrics, in this case those of Always Look on the Bright Side of Life. Say **/sing Full Name** to toggle a specific person. Say **/sing all** to toggle everyone. Say **/sing pause** to pause or unpause the singing.

```
// Forced Singing - by TheDL

song=list("Some things in life are bad,", "They can really make you mad.", "Other things just make you swear and curse.", "When you're chewing on life's gristle,", "Don't grumble, give a whistle!", "And this'll help things turn out for the best...", "And... always look on the bright side of life... tudum, tudu-tudu-tudum.", "Always look on the light side of life... tudum, tudu-tudu-tudum.", "If life seems jolly rotten,", "There's something you've forgotten,", "And that's to laugh and smile and dance and sing.", "When you're feeling in the dumps,", "Don't be silly, chumps!", "Just purse your lips and whistle -- that's the thing!", "And... always look on the bright side of life... tudum, tudu-tudu-tudum.", "Always look on the light side of life... tudum, tudu-tudu-tudum.", "For life is quite absurd,", "And death's the final word.", "You must always face the curtain with a bow.", "Forget about your sin, give the audience a grin.", "Enjoy it - it's your last chance anyhow!", "So... always look on the bright side of death, tudum, tudu-tudu-tudum.", "Just before you draw your terminal breath, tudum, tudu-tudu-tudum.", "Life's a piece of shit,", "When you look at it.", "Life's a laugh and death's a joke, it's true.", "You'll see it's all a show,", "Keep 'em laughing as you go.", "Just remember that the last laugh is on you.", "And, always look on the bright side of life... tudum, tudu-tudu-tudum.", "Always look on the right side of life... tudum tudu-tudu-tudum.", "Come on guys, cheer up!", "Always look on the bright side of life... tudum, tudu-tudu-tudum.", "Always look on the bright side of life... tudum, tudu-tudu-tudum.", "Worse things happen at sea, you know.", "Always look on the bright side of life... tudum, tudu-tudu-tudum.", "I mean, what you got to lose, you know? You come from nothing, you're going back to nothing. What you lost? Nothing!", "Always look on the right side of life... tudum, tudu-tudu-tudum.", "Nothing will come from nothing, you know what they say?", "Always look on the bright side of life... tudum, tudu-tudu-tudum...");

x=explode(sig.content," ");
y=mem("singers"); n=mem("lyrics");
if(y==null){ y=list(); y-=y[1]; mem("singers",y); }
if(n==null|| n>length(song)){ n=1; mem("lyrics",n); }
if(x[1]=="/sing"&& sig.source=="Your Name"){
 sig.pass=0; x=implode(x-x[1]," ");
 if(!find(y,x)){ y+=x; } else{ y-=x; } mem("singers",y); }
if(find(y,sig.source)|| find(y,"all")){ if(!find(y,"pause")){
  sig.pass=1; sig.content=song[n]; n+=1; mem("lyrics",n); } }

```

### Selective Mute

Say **/mute Full Name** to mute (or unmute) people. Use proper case and spelling. Say **/muted** to broadcast the list of people being muted. Should choose a channel other than **1459**, though. Alternatively, omit broadcast entirely. Users restricted.

```
// Selective Mute - by TheDL

x=explode(sig.content," ");
users=list("Your Name", "Zion Freeman", "Et Cetera");
if(mem("mute")==null){ m=list(); m-=m[1]; mem("mute",m); }
m=mem("mute"); if(find(users,sig.source)){
 if(find(list("/mute", "/muted"),x[1])){ sig.pass=0;
  if(x[1]=="/mute"){ x=implode(x-x[1]," ");
   if(!find(m,x)){ m+=x; } else{ m-=x; } mem("mute",m); }
  else{ broadcast(signal(implode(m,", ")+".",1459)); } } }
if(find(m,sig.source)){ sig.pass=0; }

// Without broadcasting.

x=explode(sig.content," ");
users=list("Your Name", "Zion Freeman", "Et Cetera");
if(mem("mute")==null){ m=list(); m-=m[1]; mem("mute",m); }
m=mem("mute"); if(find(users,sig.source)&& x[1]=="/mute"){
 sig.pass=0; x=implode(x-x[1]," ");
 if(!find(m,x)){ m+=x; } else{ m-=x; } mem("mute",m); }
if(find(m,sig.source)){ sig.pass=0; }

```

### Simple Voice Synth

Say **/voice N\_ame J\_ob Message** to broadcast a message with a false identity. Use underscores for spaces in names or titles, and correct spelling and capitalization. Users restricted.

e.g.: Et Cetera exclaims: "/voice Is-a-Lizard Cargo\_Technician I confess!"

e.g.: [Common] Is-a-Lizard (Cargo Technician) exclaims: "I confess!"

e.g.: Et Cetera says: "/voice Hugh\_Man Head\_of\_Security Arrest the lizard."

e.g.: [Common] Hugh Man (Head of Security) says: "Arrest the lizard."

```
// Simple Voice Synth - by TheDL

x=explode(sig.content," ");
users=list("Your Name", "Zion Freeman", "Et Cetera");
if(find(users,sig.source)&& x[1]=="/voice"){
 sig.source=replace(x[2],"_"," "); sig.uuid=sig.source;
 sig.job=replace(x[3],"_"," "); x.Cut(1,4);
 sig.content=implode(x," "); }

```

## Useful Snippets and Functions

### Quickcast

A broadcast function with a short name and predefined signal. Saves a lot of typing.

Change the specifics, or remove them. Defaults to **1459**.

```
// Quickcast, and avoid the hassle.

def qc(x){ broadcast(signal(x,1459,"Name","Job")); }

// Optional command volume. Use loud($) or loud($,1)

def loud(x,y){ z=signal(x); if(y==1){ z.filters=list("command_headset"); } broadcast(z); }

```

### Modulo

Returns the remainder of **x/y**. Good to six digits.

```
// Modulo, for numbers in either sign...

def mod(x,y) { z=1; if(x/y<0) { z=-1; } return x-(floor((x/y)*z)*z)*y; }

// ...or, for positive numbers only.

def mod(x,y) { return x-floor(x/y)*y; }

```

### Digital Root

Returns the digital root of **x**. Good to six digits. Ignores decimals.

```
// Digital root, for answers in either sign...

def dig(x){ if(x!=0){ y=1; if(x<0){ y=-1; } x-=(floor((x/9)*y)*y)*9; if(x==0){ x=9*y; } } return x; }

// ...or, for positive answers only.

def dig(x){ if(x!=0){ if(x<0){ x=x*-1; } x-=floor(x/9)*9; if(x==0){ x=9; } } return x; }

```

### Log Base

NTSL's **log()** function is actually *natural log*, base *e*, not the typical base 10. This function here returns the log of **x** in base **y**. Null **y** defaults to 10. **logb(x,E)** gives natural log, too. Positive numbers only.

```
def logb(x,y){ if(y==null){ y=10; } x=log(x)*(1/log(y)); return x; }

```

### Digit Length

Returns the number of digits in **x**. Whole numbers only.

```
def lengthn(x){ if(x<0){ x=x*-1; } x=log(x)*(1/log(10)); return floor(x)+1; }

```

## Outdated Scripts

### English To Mid-evil Translator

// English To Mid-evil Translator Script - By Hellafed

This script initializes a list of words by using the mem() function as a hash table. By doing this it has to initialize first, if you are running this script and then add words later, you must clear the memory of the server first so it initializes again and learns the new words.

After initialization, this transmission and the rest all skip to splitting the transmission's contents and check each word against the memory, using the word as a key. Because of not needing to loop through the list of words, this is a fast process. If it finds a valid word to replace, it will replace the word with the value that the key led to. Finally, after it is finished it will convert the vector into a string again and then replace the contents of the transmission with the final message. (Credit to Giacom for providing the code i used to create this)

```
// English To Mid-evil Translator Script - By Hellafed

// Helper Functions

def implode($vector, $adder)
{
	$returnString = "";
	$index = 1;

	while($index <= length($vector))
	{
		$at = at($vector, $index);
		$toAdd = $adder;
		if($index == 1)
		{
			$toAdd = "";
		}
		$returnString = $returnString + $toAdd + $at;
		$index += 1;
	}
	return $returnString;
}

def Initialize()
{

	// Our words! Format: real word / mid evil word
	$words = vector("gun", "cannon",
					"my", "my own",
					"security", "town watch",
					"are", "art",
					"yeah", "aye",
					"captain", "King",
					"hos", "Town Watch Commander",
					"ce", "Head Builder",
					"dead", "gone to Sovngarde",
           				"rd", "Lead Scientist",
					"assistant", "peasant",
					"Borg", "dwarven automaton",
					"Borgs", "dwarven automatons",
					"cyborg", "dwarven automaton",
					"cyborgs", "dwarven automatons",
					"fucker", "milk drinker",
					"syndicate", "dragons",
					"brig", "dungeon",
					"yours", "thine",
					"you", "thou",
					"do", "dost",
					"has", "hath",
					"nothing", "naught",
					"thanks", "Grammarcy",
					"hop", "Inn Manager",
					"ai", 	"King's Servant",
					"money", "gold coins",
					"friend", "brother",
					"station", "town",
					"shuttle", "Wagon",
					"engine", "waterwheel",
 					"space", "unknown");

	//broadcast("Starting Initialization...");

	$index = 1;
 	while($index <= length($words))
	{
		$key = at($words, $index);
		$key = lower($key);
		$value = at($words, $index+1);
		mem($key, $value);
		$index += 2;
	}
	//broadcast("Initialization Complete!");
}

// Script Begin

if(mem("initialized") != 1)
{
	Initialize();
	mem("initialized", 1);
}

$newContent = explode($content, " ");
$index = 1;
while($index <= length($newContent))
{

	$entry = at($newContent, $index);
	$value = mem(lower($entry));

	if($value)
	{
		at($newContent, $index, $value);
	}

 	$index += 1;
}

$content = implode($newContent, " ");

// Script End
```

### English To Pirate Translator

This script initializes a list of words by using the mem() function as a hash table. By doing this it has to initialize first, if you are running this script and then add words later, you must clear the memory of the server first so it initializes again and learns the new words.

After initialization, this transmission and the rest all skip to splitting the transmission's contents and check each word against the memory, using the word as a key. Because of not needing to loop through the list of words, this is a fast process. If it finds a valid word to replace, it will replace the word with the value that the key led to. Finally, after it is finished it will convert the vector into a string again and then replace the contents of the transmission with the final message.

```
// English To Pirate Translator Script - By Giacom

// Helper Functions

def implode($vector, $adder)
{
	$returnString = "";
	$index = 1;

	while($index <= length($vector))
	{
		$at = at($vector, $index);
		$toAdd = $adder;
		if($index == 1)
		{
			$toAdd = "";
		}
		$returnString = $returnString + $toAdd + $at;
		$index += 1;
	}
	return $returnString;
}

def Initialize()
{

	// Our words! Format: real word / pirate word
	$words = vector("gun", "cannon",
					"heaven", "davy jones' locker",
					"I", "aye",
					"my", "meh",
					"yes", "aye",
					"are", "argh",
					"yeah", "yarh",
					"captain", "Cap'n",
					"hos", "First Mate",
					"hop", "Crewmaster",
					"ai", 	"Navigator",
					"money", "treasure",
					"friend", "matey",
					"station", "vessel",
					"shuttle", "rowboat",
					"engine", "sails",
 					"space", "sea");

	//broadcast("Starting Initialization...");

	$index = 1;
 	while($index <= length($words))
	{
		$key = at($words, $index);
		$key = lower($key);
		$value = at($words, $index+1);
		mem($key, $value);
		$index += 2;
	}
	//broadcast("Initialization Complete!");
}

// Script Begin

if(mem("initialized") != 1)
{
	Initialize();
	mem("initialized", 1);
}

$newContent = explode($content, " ");
$index = 1;
while($index <= length($newContent))
{

	$entry = at($newContent, $index);
	$value = mem(lower($entry));

	if($value)
	{
		at($newContent, $index, $value);
	}

 	$index += 1;
}

$content = implode($newContent, " ");

// Script End
```

### Quiz Bot

A bot which will ask math additions and keep track of a person's score. You can use /score to display your score. It uses the new time() feature to know when time is up asking a question.

```
// Quiz Bot - By Giacom

$time = time();

def GiveScore($name, $points)
{
	$score = mem($name);
	$total = $points + $score;
	$message = $name + " was given " + tostring($points) + " point(s). Their total score is now " + tostring($total) + ".";
	mem($name, $total);
	return $message;
	//broadcast($message, $common, $quizMaster, $quizMaster);
}

def GetScore($name)
{
	return mem($name);
}

def GetQuestion()
{
	$numberY = rand(1, 9);
	$numberX = rand(1, 9);
	$looped = 0;

	while($looped == 0 || prob(25))
	{
		$looped += 1;
		$numberY = $numberY * rand(1, 9);
		$numberX = $numberX * rand(1, 9);
	}

	$question = "What is " + tostring($numberY) + " + " + tostring($numberX) + "?";

	// Store data
	mem("currentQuestion", $question);
	mem("number1", $numberY);
	mem("number2", $numberX);
	mem("lastAsked", $time);
	mem("pointQuestion", $looped);
	broadcast($question, $common, $quizMaster, $quizMaster);
}

// Main()

$quizMaster = "The Math Master";
$currentQuestion = mem("currentQuestion");
$currentNumber1 = mem("number1");
$currentNumber2 = mem("number2");
$lastAsked = mem("lastAsked");
$pointQuestion = mem("pointQuestion");
$askNextQuestion = 15; // 15 seconds

$explode = explode($content, " ");

if(at($explode, 1) == "/score")
{
	$theScore = GetScore($source);
	broadcast($source + ", you have " + $theScore + " point(s).", $common, $quizMaster, $quizMaster);
	$skip = 1;
}

if($currentQuestion == null)
{
	broadcast("Welcome! I am " + $quizMaster + " and I will be giving you all questions which you can answer over the radio.", $common, $quizMaster, $quizMaster);
	broadcast("I will be keeping track of score. Use /score to view your score! Good luck! You have " +  $askNextQuestion + " seconds.", $common, $quizMaster, $quizMaster);
	GetQuestion();
}
elseif($time > $lastAsked + ($askNextQuestion * 10))
{
	broadcast("No one has found the answer in the time limit. Starting new round...", $common, $quizMaster, $quizMaster);
	GetQuestion();
}
else
{
	$answer = tostring($currentNumber1 + $currentNumber2);
	if(find($explode, $answer))
	{
		$results = GiveScore($source, $pointQuestion);
		broadcast($source + " wins! Answer was: " + $answer + ". " + $results, $common, $quizMaster,  $quizMaster);
		GetQuestion();
	}

}
```

### Misleading Locations

Copy and paste this into the def Initialize() block in the English to Pirate -translator. You can also change words within the "" to suit any other needs like making "blood rune" to "retard". Be sure to go into other comm channels, copy/paste and set active for maximum evil laughter.

```
$words = vector("scripts", "clown", "storage", "brig",
"maintenance", "bar", "main", "escape", "sec", "medbay",
"brig", "arrivals", "cargo", "engineering", "science", "security",
"bar", "vacant", "chapel", "bridge", "dorms", "locker room",
"office", "donuts", "upload", "ass", "solars", "escape",
"core", "heart", "engineering", "botany", "locker room", "science");

```