Manyland

The Brain type allows you to program behavior of yourself, explorers you open in anonymous windows, or others who attach the Brain.

To get started, just login, hit Create, select Brain, draw something, name the creation, and hit the Save button. Leaving the text field empty means you've created an empty Brain, which can be overloaded dynamically when putting it on, ideal during development. Now go to an area where you're editor, place the Brain, and walk over it and hit Space to put it on. A code editor opens. A bit of sample code should be preloaded.

Tip: Others can't bring their own Brains into your area if they're not an editor, but you can place an empty Brain there (or one with the attribute "offers editing") to give them a chance to dynamically overload it.

Tip: If you're looking for a good font, try our Doid.ttf, which is a spin on Droid especially suited for programming. After saving locally and installing as font on your machine, you can adjust your browser settings to use this as default monospace font.

What Brain code looks like

To program Brains, you need to know some JavaScript (there's many great resources available). Here's a sample code structure:

// An example script

var chanceForMovement = 25;

function update(my) {
    var reaction = {
            left: false, right: false, up: false, down: false};
    
    if ( chance(chanceForMovement) ) { reaction.left = true; }
    
    return reaction;
}

The default update routine is called 15 times a second and needs to be present in every script. It receives a my parameter which contains a variety of information you're receiving: what the world around you looks like, what other people or items are there, what you're currently touching and more.

Using this input, you can then determine what to do and return it as part of a reaction structure.

In above script, we're defining a Brain-global variable called chanceForMovement, set to 25. We're also using the native chance function. Whenever the given chance of 25% is true, we're setting the reaction to move left. We're finally returning the reaction. When we hit the Start button on this script, we can see ourself moving a bit left randomly. Try setting the chanceForMovement value to something higher, like 75, and you find the movement changes when you hit Stop and Start again.

Once you're happy with a script, you can copy it from the editor, create a new type Brain, hit the text button at the top, and paste the code into it. This Brain is now shareable with others by placing it in the world (its code contents can then be peeked at from the item context menu, but the brain cannot be directly overloaded). You can also click it from your panel to use it. While a Brain is attached, everyone sees a little dot in the place of your name.

The My object with example values

my

The Reaction object with example values

Here's a full list of values you can set in the reaction object (all properties are optional to pass):

reaction

Logging

You can use the following functions to log debug information when the script editor is opened (you can pass as many parameters as you like):

log('my status', my.status);

logOnce(my.velocity.x); // only logs once per run

logFresh(1 + 1); // clears the log and logs something new

logFresh(); // clears the log

Types

To check a placement's type, you can use (where someBlock is e.g. my.touch.forward):

if (someBlock.type == enumType.thingInFront) { ... }

The enumType integer value is persistent and won't ever change.

If you are only interested in whether or not a type is solid, or harmful, you can use these groups instead:

if (someBlock.isSolid) { ... }

if (someBlock.isHarmful) { ... }

Here are all type names (you can check for them using e.g. enumType.back):

Allowing any brain-equipped person to affect others

By default, only people in one's friend list can affect someone with e.g. a harmful emitter. If you want to create brain-equipped enemies in an area, you can allow them to affect others by including the following in e.g. an area-global interacting:

Someone Arrives: /they can be affected by brain-equippers

Here's some more rights you can set.

Sound

You can add a sound to Brains.

Limits

You may use up to 3 brain-equipped sessions at once.

Fullscreen

Note you can enter fullscreen mode at any time, also when the Brain editor is opened, by pressing F11.

Native functions

The following functions are available in addition to JavaScript's native functions:

// True or false, depending on a chance of 0 - 100%
chance(percent);

// Returns a random integer from minInt to maxInt.
// The value is deterministic for Happenings and Generators so
// that everyone sees the same (same for Math.random()).
getRandomInt(minInt, maxInt);

// For use with the Changer,
// converts pixels from palette indexes to rgba:
convertToFullColor(creation);

// Returns a copy of the object so that
// changes won't affect the original:
cloneObject(object);

// Limits a value into the numbers,
// sets to minimum if not numeric:
toLimit(value, min, max);

Examples

Example: Sight

Here, we are converting what we see around us as we move into log output letter art:

function update(my) {    
    var reaction = {}; 

    showMap(my.sight.placements, my.sight.scope);

    return reaction;
}    
 
function showMap(placements, scope) {
    var s = '';
    var scopeY = Math.round(scope / 3);

    for (var y = -scopeY; y <= scopeY; y++) {
        for (var x = -scope; x <= scope; x++) {
            if (x == 0 && y == 0) {
                s += '▣';
            }
            else {
                var block = placements[x + scope][y + scope];
                s += block && block.isSolid ? '■' : '□';
            }
        }
        s += "\n";
    }

    logFresh(s);
}

Example: Touch

In this example, we're moving left or right. When there's a solid or harmful obstacle we change direction by going left or right. If there's a gap in the ground we're jumping. Randomly in-between we're hitting the action button (if we're holding an equipment), so if say we have a hammer equipped, it would swing every now and then. We're also printing something to the log when that happens. On the side, we're looking for a coin item to pick up (we check for the occurrence of the string "coin" in the item's name; note all item names are lower-case).

var reaction = {};
var foundCoinTimer = null;

function update(my) {   
    reaction = {};
    var direction = my.direction; 
   
    if ( my.touch.forward &&  
            (my.touch.forward.isSolid || my.touch.forward.isHarmful) ) {  
        direction *= -1;   
    }   
  
    if (!my.touch.bottomForward || !my.touch.bottomForward.isSolid) {  
        reaction.up = true; 
    }  
      
    if ( my.holdable && my.holdable.type == enumType.equipment && chance(5) ) {
        reaction.actionOnce = true;
        log('Action time!'); 
    }
    
    if (direction == -1) { reaction.left = true; }   
    else                 { reaction.right = true; }  

    handleCoinFinding(my);
   
    return reaction;
}   

function handleCoinFinding(my) {
    if (!my.holdable) {
    
        if (!foundCoinTimer) {
            if ( !my.holdable &&
                    my.touch.center && my.touch.center.type == enumType.item &&
                    my.touch.center.name.indexOf('coin') >= 0 ) {
                foundCoinTimer = new Timer();
                reaction.speech = 'i found a coin!';
                stopMoving();
            }
            
        }
        else {
            reaction.left = false;
            reaction.right = false;
            if ( foundCoinTimer.seconds() >= 1 ) {
                reaction.actionOnce = true;
                foundCoinTimer = null;  
                stopMoving();
            }
            
        }
        
    }
}

function stopMoving() {
    reaction.left = false;
    reaction.right = false;
    reaction.up = false;
}
   
function Timer() {
    this.timeAtStart = Date.now();
    
    this.seconds = function() {
        return ( Date.now() - this.timeAtStart ) / 1000;
    }
    
    this.reset = function() {
        this.timeAtStart = Date.now();
    }
}

Example: Hearing

This time, we react to when others say "jump", "left" or "right". There are different ways to go about this, e.g. you could create a function that accepts a list like {jump: 'up', ...} and applies reaction[mappingFound] = true, and instead of a for-loop there may be a my.hearing.forEach() and so on. Note in below we don't check for the hearing.type "speech", so this may later also react to a sound effect named e.g. "jump".

function update(my) {    
    var reaction = {}; 

    for (var i = 0; i < my.hearing.length; i++) {
        var hearing = my.hearing[i];
        var isMe = hearing.fromId == my.id;
        if (!isMe) {
            switch (hearing.content) {
                case 'jump':  reaction.up = true; break;
                case 'left':  reaction.left = true; break;
                case 'right': reaction.right = true; break;
            }
        }
    }

    return reaction;
}

Example: Looking for gold

Here we try to find gold!

var memory = {didFindGold: false};

function update(my) {
    var reaction = {};

    if (!memory.didFindGold) {
        lookForGold(my, reaction);
    }

    return reaction;
}

function lookForGold(my, reaction) {
    var touchType = my.touch.center ? my.touch.center.type : '';
    var touchName = my.touch.center ? my.touch.center.name : '';

    if (touchType == 'climbable') {
        reaction.up = true;
    }
    else if ( touchName.indexOf('gold') >= 0 ) {
        reaction.speech = 'i found gold!';
        memory.didFindGold = true;
    }
    else {
        moveLeftAndRightAndAvoidGaps(my, reaction);
    }
}

function moveLeftAndRightAndAvoidGaps(my, reaction) {
    var direction = my.direction;
 
    if ( my.touch.forward &&    
            (my.touch.forward.isSolid || my.touch.forward.isHarmful) ) {    
        direction *= -1;
    }     
    
    reaction.up = !my.touch.bottomForward || !my.touch.bottomForward.isSolid;

    if (direction == -1) { reaction.left = true; }   
    else                 { reaction.right = true; }  
}

More...

Also check out the main introductory help and the Interacting help. Got a question which isn't answered here, or new ideas and feedback? Have a look here please.