text:
Team of The Hill!
This challenge was inspired by @HelkaHomba's excellent challenge Red vs. Blue - Pixel Team Battlebots. That challenge was probably the best one I've seen on this site. Ever.
My challenge is still a lot different, but @HelkaHomba deserves credit for the inspiration.
Overview
This is a team king-of-the-hill where your team wins by having all players alive on your team. In other words, last team standing wins. Draws will be re-done.
You are on a board. You know your position on the first round (tick 0). You also know who is in the area around you:

In this case, you are all alone (or so you think) with no-one around you. You can see surrounding items in the first argument to your ontick handler. More about the API later.
Your team
Your team is determined by your user ID. To find that out, click on your profile picture:

Then find your user ID in the address bar:

If it is odd, you are on the blue team.
If it is even, you are on the red team.
You're welcome for the hand-drawn circles.
Your (bot's) name
Your bot's name starts with the first letter of your team ("r" or "b"). It must match the regex /^(r|b)[A-Za-z_-]$/. Other than that, you can pick your bot's name. Please don't use an already-existing one.
Starting
The red players will start near the top of the map, and the blue will start near the bottom. You are given special info on the first tick (turn) in the environment parameter for the ontick function. I recommend storing that. See the API for details.
On your turn
Turn order is randomized initially, but then stays the same.
Turn actions
You may only do one action per turn.

Move
When you would like to move, you call this.move(num) in the API. num is the cell you would like to move to:

The relative locations of the numbers you can move to are stored in the global constant threeByThree:

[
    [0, 1, 2],
    [3, undefined, 4],
    [5, 6, 7]
]

If you move into a wall, or another player, nothing happens.

Rotate
To rotate, you call this.rotate(num). Num is the direction you want to rotate:

Rotation is absolute.
Kill
If another player (from another team) is in the cell you are facing, you can call this.kill() and kill them. If there is no-one there, or they are on your team, this does nothing. Example:

If you are turned to 0, you can kill green. If you are are turned to 1, you can kill blue. If you are are turned to 2, you can kill orange. If you are are turned to 3, you can kill yellow.
Bomb
Bombing kills all players including you and teammates in the 9 squares around you. Example:

Why would you ever want to do this? Kamikaze. If there are more players not on your team in the 9 cells around you then there are on your team, you might consider bombing. (I suggest you notify your comrades first!)
Place a landmine
This creates a death square for others not on your team. When you place a land mine, you also move so you don't step on it. You call this.landMine(num) where num is the square you want to go to. Example:

Then you call this.landMine(4):

See that "M"? It's a landmine. Others can see it...for now. Anyone, even those not on your team, can see a landmine on the tick it is placed. But after that tick is over, no-one, not even you can see it. But it will explode as soon as an enemy walks over it. Example:

Blue moved on your landmine, and BOOM! You just got another kill.
For every 2 kills you get (from direct killing or land mines), you get 1 extra landmine to place. You also get one at the start.
Dig
When you dig, you look for landmines in a 5x5 area centered around you. This does not show the team of the bot that placed the landmine. (Remember that you can't be killed by a landmine placed by someone on your team.) For example, if this was the grid around you:

Then the return value of this.dig() would be:

[undefined,undefined,undefined,true,undefined,
undefined,undefined,undefined,undefined,undefined,
undefined,undefined,undefined,undefined,
undefined,undefined,true,undefined,undefined,
true,undefined,undefined,undefined,undefined]

The array indexes are from starting in the top left, going right, than down, not including yourself:

There are 23 in total, and their relative locations are stored in the global constant fiveByFive:
[
    [0, 1, 2, 3, 4],
    [5, 6, 7, 8, 9],
    [10, 11, undefined, 12, 13],
    [14, 15, 16, 17, 18],
    [19, 20, 21, 22, 23]
]

Note that dig reveals mines placed on previous ticks, unlike aroundMe.
Communication
When you want to talk to someone, you call this.sendMessage(recipients, team, data). The data can be anything you want, and you can send it to anyone you want, even players on other teams. This can be used to trick poorly-programmed bots, but all players can see who sent a message and who's team they are on.
Example:
Send something to a bot named "redisbest":
this.sendMessage("redisbest", undefined, "Hi!");

Send something to a bot named "redisbest" and "blueiscool":
this.sendMessage(["redisbest", "blueiscool"], undefined, {hello: "there"});

Send something to the entire red team
this.sendMessage(undefined, "red", {hello: "red"});

Send something to everyone
this.sendMessage(undefined, "*", {hello: "everyone"});

Send something to the entire red team and a bot named "blueiscool":
this.sendMessage("blueiscool", "red", {hello: "bots"});

API
Your code must consist of a single call to the createBot function. Nothing else. Sample code:
createBot({
    ontick: function(environment) {
        return new Promise((resolve, reject)=>{
            this.move(0);//example
            resolve();//please call this when you are done
        });
    },
    onmessage: function(data, from, fromBot) {
        console.log("onMessage: " + this.name + " from " + this.team + " got message ", data, " from " + from + ", on team " + fromTeam);
        this.sendMessage(["bot", "otherbot"], "team", "some data");
    },
    team: "red",//your team
    name: "rmyteamname",//team name must begin with the first letter of your team's name
    onkill: function(){
        //say goodbye
    }
});

(You are free to copy-paste this. Just modify it for your team, etc.)
Methods

ontick(environment)
Called when it's your turn. Must return a Promise that resolves in 1 second or less or it will be ignored. This is for performance reasons and has the nice side-effect of not having the tab hang.
 this (when in ontick)

landMines
How many land mines you have left. The more kills you have, the more land mines you get. For every 2 bots you kill, you get 1 more landmine. You also get 1 to start.
direction
The direction you are facing.
storage
Storage that persists between calls to onTick and onMessage. An empty object at start. Modify for any purpose, but make sure it's an array or object always to ensure it persists correctly.
move(num)
Move to the specified position. Does nothing if invalid. See above for details.
rotate(num)
Rotate to the specified position. Does nothing if invalid. See above for details.
kill()
Kills the player you are facing, if exists and is not on your team. See above for details.
bomb()
Kills anyone in the 9 squares around you, including yourself.
landMine(num)
Places a land mine where you are, and then moves to the specified position. Does nothing if invalid num or you have none left. See above for details.
dig() new!
Returns an array of info about the landmines in a 5x5 area centered around you. See above for details.
sendMessage(recipients, team, data)
recipients can either be a single bot (string), an array of bot, or undefined/null. It is who you would like to send the message.
team is a string of the team you would like to send the message. Use "*" to send a message to everyone.
data is anything that can be passed to a JS function. It is send to the recipients. If it is an object or array, it is passed by reference, so you and the recipient(s) can save that to their storage and any modifications to the object affects both bot's copies.
Note that recipients that are in either the list of bots, the exact bot specified in the string, or a bot on the team you specified, it will get the message.

environment
On the first tick

x: Your player's x-position
y: Your player's y-position
gridWidth: The width of the grid (in cells)
gridHeight: The height of the grid (in cells)
On all ticks
aroundMe: An array of players and landmines. The players are objects that look like {name: "bot name", team: "bot team"}, and the landmines are {team: "team of bot who placed mine"}. The indexes of the array:

Note that landmines placed on a tick other than the current one will not be shown.
aroundMe example:
Let's say this is the grid (you are red):

Your aroundMe will look like this:

[
    {name: "bexamplebluebot", team: "blue"},
    undefined,//sparse array, nothing in index 1
    undefined,//there is technically a landmine here, but it wasn't placed this tick, so it is not shown
    undefined,//nothing in 3
    {name: "yexampleyellowbot", team: "yellow"},
    {team: "red"},//this is a landmine, you can tell is not a bot because it has no name. mines have the team name of the player they were placed by. This mine was placed this tick, otherwise you couldn't see it
    //nothing else after index 5, so the array's length is 5.
]

The indexes of the array are explained here:

Your bot effectively sees this:

onmessage(data, fromBot, fromTeam)
 this (when in onmessage)

sendMessage(recipients, team, data) Standard message sending function.
storage Standard storage.

data The data sent from the sender.
fromPlayer The player the message was sent from.
fromTeam The team the message was sent from.
onkill()
 this (when in onkill)

sendMessage(recipients, team, data) Standard message sending function.

Convenient (constant) global arrays:
threeByThree:
[
    [0, 1, 2],
    [3, undefined, 4],
    [5, 6, 7]
]

Useful for passing data to the move function as well as interpreting aroundMe. See above.
fiveByFive :
[
    [0, 1, 2, 3, 4],
    [5, 6, 7, 8, 9],
    [10, 11, undefined, 12, 13],
    [14, 15, 16, 17, 18],
    [19, 20, 21, 22, 23]
]

Useful for the this.dig() function in the ontick handler.
Try it out!
The controller will be run from my machine on localhost for performance reasons, but you can use the CodePen to test your bot out.
Note that you must paste your code in the console and press Enter before you click run. You can paste in as many bots as you'd like. The "Test bots" are examples for you to test against. If you can beat or tie all of them, you have at least a decent bot.
Submissions
Rules
Rules (enforced by the controller)

Your main ontick code must not take more than 1 second. We don't want rounds to take forever. If your code takes > 1 second, it will be stopped.
If you attempt to do more than 1 action per turn, or do an invalid action (eg. this.move(-1) or moving into a wall), it will be ignored.
More may come soon...

Rules (enforced by me, can result in DQ)

Don't write global variables (reading is fine).
Your code must work in Nodejs (in case the controller is ported to Nodejs), so JSON.parse(...) is fine, but alert() is not.
You are not allowed to call createBot or interfere with the controller in any way.
Don't use someone's else's code without permission and significant changes. No copybots.
Please, no loopholes!
More may come soon...

My bots
Here are some bots:
This bot randomly chooses an action. Well, it's a weighted random, but still pretty random. If you can kill this bot (it will eventually kill itself, that doesn't count), than you have at least a decent bot. Post it and see what happens!

createBot({
  ontick: function(environment) {
    return new Promise((resolve, reject)=>{
      if(Math.random() < 0.02){
        this.bomb();
      }else if(Math.random() < 0.1){
        this.kill();
      }else if(Math.random() < 0.3){
        this.rotate(~~(Math.random() * 4));
      }else{
        this.move(~~(Math.random() * 8));
      }
      resolve();
    });
  },
  team: "none",
  name: "xrandomness2",
  onkill: function(){
    console.log("Goodbye world... :(");
  }
});

My bots have a name beginning with "x" and a team of "none". You are welcome to use some of this code, but please do at least some modification. If you can't be bothered to at least tweak a number, you won't win.
Formatting your submission
Please use this format:
# rmyamazingbot

    createBot({
        ontick: function(environment) {
            return new Promise((resolve, reject)=>{
                this.move(0);//example
                resolve();//please call this when you are done
            });
        },
        onmessage: function(data, fromTeam, fromBot) {
            console.log("onMessage: " + this.name + " from " + this.team + " got message ", data, " from " + from + ", on team " + fromTeam);
            this.sendMessage(["bot", "otherbot"], "team", "some data");
        },
        team: "red",//your team
        name: "rmyteamname",//team name must begin with the first letter of your team's name
        onkill: function(){
            //say goodbye
        }
    });

Long, but cool explanation...

Feature requests, bugs, questions, etc?
Comment below! Please check to see if there is already a comment with that. If there is one already, upvote it.
Want to talk to your team?
Use the chat rooms for red and blue.
Language
Currently, only JS and something that compiles to JS is supported, but if you know of a way to get other languages to work with Nodejs I would be happy to port the controller to Nodejs.
Final notes
Strategy ideas
Help your team! Creating a bot that is designed to help another bot and work together. This strategy worked well for Red vs. Blue - Pixel Team Battlebots
Rep seekers
I will accept the highest voted answer on the winning team. Keep in mind that earlier answers tend to get more votes, but their weaknesses are more likely to be found and exploited.
Also, if you answer soon, you might get the +100 bounty.

Comments are not for extended discussion; this conversation has been moved to chat.

May I make more than one bots? (sorry,I know the conversation has been moved, I'm just chatbanned so yeah)

@SIGSEGV yes, but someone else must post it. You could post one bot and give the code of another to someone on your team, but you can't post twice.

About positioning, where is the [0, 0]-indexed cell, is it the top-left cell? Also, does messaging consume your action (per turn)? Thanks.

@Thrax yes, and no. You can even message in response to an message.

I think there's a problem with the command move(0); on your test site, since even your sample bot won't move with this command only. The other values seem fine, though.

@Thrax that moves up and to the left, which would be in the wall if you started in the upper-left. Is it a problem when you are in the middle of the grid?

I started at the bottom right (blue-team), and the bot wouldn't move. I then tried with 1 and 3 and both worked.

What happens if i choose to explode to kill an opponent and, in the same round, he decide to move away from me?

@AlixEisenhardt 1: Which ever happens first. "Turn order is randomized initially but then stays the same". If you happen to go first, the opponent will die before taking a turn. Otherwise, you die without taking a turn.

xscared (non-competing)
createBot({
    ontick: function(environment) {
        var reverse = [0, 1, 2, 3, 4, 5, 6, 7].reverse();
        return new Promise((resolve, reject)=>{
            (this.aroundMe || []).forEach((item,idx)=>{
                this.move(reverse[idx]);
                return resolve();
            });
            this.move(~~(Math.random() * 8));
            return resolve();
        });
    },
    onmessage: function() {
    },
    team: "none",
    name: "xscared",
    onkill: function(){
    }
});

Very scared of people. Goes away from the first person (or landmine) it sees. Otherwise, it moves randomly. Note that this is not competing, just an example. Try to beat it!

backup, a blue bot
As warned in chat, I never wrote anything in javascript in my life, so if you find any mistake, please tell me! (Thanks to @programmer5000 for already helping me with it)
The concept of this bot is that it communicates with other bots from the same team and send them its position along with a map of the mines it found. It tries to join the closest blue bot (if one send its position data [given as an [x,y] array]), and stays near it (with its back to it as much as possible), killing approaching red bots or looking ahead for mines.
createBot({
    team: 'blue',
    name: 'backup',
    ontick: function(environment) {
        return new Promise((resolve, reject) => {
            //if (typeof this.x != "undefined") this.storage['position'] = [this.x, this.y];
            if (typeof environment.x != "undefined") this.storage['position'] = [environment.x, environment.y]; //Modified according to @WasteD
            if (typeof this.storage['map'] == "undefined") { //Create empty map
                var map = [[]];
                //for(i=0;i<this.gridHeight;i++) map[i]=[];
                for(i=0;i<environment.gridHeight;i++) map[i]=[]; //Modified according to @WasteD
                this.storage['map'] = map;
            }
            var blue = []
            var red = []
            var x = this.storage['position'][0];
            var y = this.storage['position'][1];
            var dx = [-1, 0, 1, -1, 0, 1, -1, 0, 1]
            var dy = [1, 1, 1, 0, 0, 0, -1, -1, -1]
            (this.aroundMe || []).forEach((item, idx) => { // Update map and list positions of surrounding blues and reds
                if (item && item.team == 'red' && typeof item.name != "undefined") red += idx;
                if (item && item.team == 'red' && typeof item.name == "undefined") this.storage['map'][x+dx[idx]][y+dy[idx]] = 'M';
                if (item && item.team == 'blue' && typeof item.name != "undefined") blue += idx;
            });
            this.sendMessage(undefined, "blue", {"position": this.storage['position'], 'map': this.storage['map']}); //Send to buddies my position and the map
            if (red.indexOf([1, 4, 6, 3][this.direction]) > -1) this.kill() ; //If red guy is in front of
            else if (red.indexOf([1,4,6,3]) > -1) this.rotate(red.indexOf([1,4,6,3])); //If red guy is next but not in front of
            else if (blue.indexOf(3) > -1){ //If blue buddy on the left
                if (blue.indexOf(4) > -1){ //If another one is on the right
                    if (blue.indexOf(1) > -1 && this.direction != 2) this.rotate(2); //...and a third one at the top
                    else var digging = this.dig();
                    }
                else if (this.direction != 1) this.rotate(1);
                else var digging = this.dig();
            }
            else if (blue.indexOf(1) > -1){
                if (blue.indexOf(6) > -1 && this.direction != 3) this.rotate(3);
                else if (this.direction != 2) this.rotate(2);
                else var digging = this.dig();
            }
            else if (blue.indexOf(4) > -1){
                if (this.direction != 3) this.rotate(3);
                else var digging = this.dig();
            }
            else if (blue.indexOf(6) > -1 && this.direction != 0) this.rotate(0);
            else if (blue.indexOf([0,2]) > -1){ //If no blue next to me but one in diagonal, move next
                this.move(1);
                this.storage['position'][1] = y+1; //Update position
            }
            else if (blue.indexOf([5,7]) > -1){
                this.move(6);
                this.storage['position'][1] = y-1;
            }
            else if (typeof this.storage['other_blue'] != "undefined"){ //Check if buddies said where they were, try to go near the closest one
                var dmin = 99999;
                var pos = []
                (this.storage['other_blue'] || {}).forEach((item, idx) => {
                    var d = Math.sqrt(Math.pow(item['position'][0]-x,2) + Math.pow(item['position'][1]-y,2));
                    if (d < dmin){
                        dmin = d;
                        pos = item['position'];
                        }
                });
                if (pos[0]-x > 0){
                    this.move(4);
                    this.storage['position'][0] = x+1
                }
                else if (pos[0] < 0){
                    this.move(3);
                    this.storage['position'][0] = x-1
                }
                else if (pos[1] > 0){
                    this.move(1);
                    this.storage['position'][1] = y+1
                }
                else{
                    this.move(6);
                    this.storage['position'][1] = y-1
                }
            }
            else var digging = this.dig();
            if (typeof digging != "undefined"){ //Check out surroundings if dig() was played and update the map accordingly
                var dx2 = [-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2];
                var dy2 = [2,2,2,2,2,1,1,1,1,1,0,0,0,0,0,-1,-1,-1,-1,-1,-2,-2,-2,-2,-2];
                (digging || []).forEach((item, idx) => {
                    //if (item && item.team == 'red' && typeof item.name == "undefined") this.storage['map'][x+dx2[idx]][y+dy2[idx]] = 'M';
                    if (item) this.storage['map'][x+dx2[idx]][y+dy2[idx]] = 'M'; //previously misread what dig() returned
                });
            }
            resolve();
        });
    },
    onmessage: function(data, fromTeam, fromBot) {
        if (typeof data['position'] != "undefined" && fromTeam == 'blue') { //If position sent by a blue bot
            if (typeof this.storage['other_blue'] == "undefined") this.storage['other_blue'] = [];
            for (i in this.storage['other_blue']){
                var found = false;
                if ('name' in i){
                    if (i['name'] == fromBot){
                        i['position'] = data['position'];
                        found = true; //Update if position already known from previous ticks
                        }
                }
            }
            if (!found) this.storage['other_blue'] += {'position':data['position'], 'name':fromBot}; //Add position if previously unknown
            this.sendMessage(fromBot, undefined, "roger.");
        }
    },
    onkill: function() {this.sendMessage(undefined, "blue", {"position": this.storage['position'], 'map': this.storage['map']});}
});

Hey You care if I also enter this but (with different name) I am also on blue

@Christopher No i don't mind, but that would be a bit more interesting for you and for the team if you make one at least a bit different (at least to complement the 2 bots that already exists).

Will do that. I will change it up

If I try to run your bot in codepen it doesn't work because you are using this.x and so on but it is environment.x or am I wrong?

@WasteD as I said I don't know Javascript at all, so it's possible. But if it's the case then I guess it should also be environment.gridHeight and environment.aroundMe? In which case then the other bots shouldn't work either since they use this.aroundMe.

For gridHeight and gridWidth yes! But as you can see in the docs at the top for aroundMe he uses this. If you can make it to work I gonna use your bot so our bots can work together!

@WasteD I modified my bot according to your comments (Thanks!). But also: see comments on the question.

Yeah I tested it right now both don't work hmm... Think we have to w8 for @programmer5000

@WasteD see this

Blue, blue, my world is blue
createBot({
    team: 'blue',
    name: 'blue-blue-my-world-is-blue',
    ontick: function(environment) {
        return new Promise((resolve, reject) => {
            var red = 0;
            // See who's around me
            (this.aroundMe || []).forEach((item, idx) => {
                if (item && item.team == 'red') red++;
            });
            // If surrounded, take one for the team
            if (red >= 6) this.bomb();
            else {
                // Translate direction into position
                var kill = [1, 4, 6, 3][this.direction];
                // Random values
                var move = Math.floor(Math.random() * 8);
                var nsew = Math.floor(Math.random() * 4);
                // Lay a landmine if possible
                if (this.landMines) this.landMine(move);
                // Kill if someone is in the way
                else if (this.aroundMe && this.aroundMe[kill] && this.aroundMe[kill].team == 'red' && this.aroundMe[kill].name) this.kill();
                else {
                    // Move somewhere if already in the requested direction
                    if (nsew == this.direction) this.move(move);
                    // Otherwise just rotate to the requested direction
                    else this.rotate(nsew);
                }
            }
            resolve();
        });
    },
    onmessage: function(data, from, fromBot) {},
    onkill: function() {}
});

Mostly random, but will bomb if surrounded, and favors checking around and killing over moving.

Smart! Nice one.

Yo listen up, here is a story, about a little guy who lives in a blue world.

Relaxed-Bomber
This bot searches for a spot with at least 1 free cell on each side then plants a mine. It camps on it until an enemy approaches. When someone draws near, he'll step back back and forth on his mine to bait the other bot on it. He'll also rotate and kill if needed. When he doesn't have any mine left, he'll seek refuge on the top-left corner with its back to the wall and retaliate if he's threatened.
No special teamplay here, apart from broadcasting his position to his team with self keyword.
createBot({
    team: 'red',
    name: 'relaxed-bomber',
    ontick: function(environment) {
        return new Promise((resolve, reject) => {
            if (typeof this.storage['dropped'] == "undefined") {
                this.storage['dropped'] = false;
                this.storage['covered'] = false;
                this.storage['baited'] = false;
            }
            if (typeof environment.x != "undefined" && typeof environment.y != "undefined") {
                this.storage['pos'] = [environment.x, environment.y];
            }
            if (typeof environment.gridWidth != "undefined" && typeof environment.gridHeight != "undefined") {
                this.storage['grid'] = [environment.gridWidth, environment.gridHeight];
            }
            var x = this.storage['pos'][0];
            var y = this.storage['pos'][1];
            var x0 = this.storage['grid'][0];
            var y0 = this.storage['grid'][1];
            var source = [1, 4, 6, 3];
            var dest = [6, 3, 1, 4];
            var rot = [0, 1, 2, 3];
            var movex = [-1, 0, 1, -1, 1, -1, 0, 1];
            var movey = [-1, -1, -1, 0, 0, 1, 1, 1];
            var action = false;
            if (this.landMines > 0) {
                var move = [false, false, false, false];
                var moveIndex = -1;
                if (x <= 0) { move[1] = true; }
                if (x >= x0 - 1) { move[3] = true; }
                if (y <= 0) { move[2] = true; }
                if (y >= y0 - 1) { move[0] = true; }
                if (move[0] && !move[1] && !move[2] && move[3]) { moveIndex = 0; }
                if (move[0] && !move[1] && !move[2] && !move[3]) { moveIndex = 1; }
                if (move[0] && move[1] && !move[2] && !move[3]) { moveIndex = 2; }
                if (!move[0] && !move[1] && !move[2] && move[3]) { moveIndex = 3; }
                if (!move[0] && move[1] && !move[2] && !move[3]) { moveIndex = 4; }
                if (!move[0] && !move[1] && move[2] && move[3]) { moveIndex = 5; }
                if (!move[0] && !move[1] && move[2] && !move[3]) { moveIndex = 6; }
                if (!move[0] && move[1] && move[2] && !move[3]) { moveIndex = 7; }
                if (moveIndex >= 0) {
                    this.storage['pos'] = [ x + movex[moveIndex], y + movey[moveIndex]];
                    this.move(moveIndex);
                } else {
                    this.storage['dropped'] = true;
                    this.storage['covered'] = false;
                    this.landMine(1);
                }
            } else {
                if (this.storage['dropped']) {
                    this.storage['dropped'] = false;
                    this.storage['covered'] = true;
                    this.storage['pos'] = [ x + movex[6], y + movey[6]];
                    this.move(6);
                } else if (this.storage['covered']) {
                    for (var i = 0; i < source.length; i++) {
                        if (typeof environment.aroundMe[source[i]] != "undefined" && typeof environment.aroundMe[source[i]].team != "undefined" && environment.aroundMe[source[i]].team == "blue" && typeof environment.aroundMe[source[i]].name != "undefined") {
                            this.storage['covered'] = false;
                            this.storage['baited'] = true;
                            this.storage['mine'] = this.storage['pos'].slice();
                            this.storage['reverse'] = source[dest[i]];
                            this.storage['pos'] = [ x + movex[dest[i]], y + movey[dest[i]]];
                            this.move(dest[i]);
                            action = true;
                        }
                    }
                    if (!action) {
                        this.dig();
                    }
                } else if (this.storage['baited']) {
                    for (var i = 0; i < source.length; i++) {
                        if (typeof environment.aroundMe[source[i]] != "undefined" && typeof environment.aroundMe[source[i]].team != "undefined" && environment.aroundMe[source[i]].team == "blue" && typeof environment.aroundMe[source[i]].name != "undefined") {
                            if (this.direction == rot[source[i]]) {
                                this.kill();
                                this.storage['baited'] = false;
                                action = true;
                            } else {
                                this.rotate(rot[source[i]]);
                                action = true;
                            }
                        }
                    }
                    if (!action) {
                        if (this.storage['mine'][0] == this.storage['pos'][0] && this.storage['mine'][1] == this.storage['pos'][1]) {
                            this.storage['pos'] = [ x + movex[this.storage['reverse']], y + movey[this.storage['reverse']]];
                            this.move(this.storage['reverse']);
                            this.storage['reverse'] = source[this.storage['reverse']];
                        } else {
                            this.storage['pos'] = [ x + movex[this.storage['reverse']], y + movey[this.storage['reverse']]];
                            this.move(this.storage['reverse']);
                            this.storage['reverse'] = dest[this.storage['reverse']];
                        }
                    }
                } else {
                    for (var i = 0; i < source.length; i++) {
                        if (typeof environment.aroundMe[source[i]] != "undefined" && typeof environment.aroundMe[source[i]].team != "undefined" && environment.aroundMe[source[i]].team == "blue" && typeof environment.aroundMe[source[i]].name != "undefined") {
                            if (this.direction == rot[source[i]]) {
                                this.kill();
                                this.storage['baited'] = false;
                                action = true;
                            } else {
                                this.rotate(rot[source[i]]);
                                action = true;
                            }
                        }
                    }
                    if (!action) {
                        if (x > 0 && y > 0) {
                            this.storage['pos'] = [ x + movex[0], y + movey[0]];
                            this.move(0);
                        } else if (x > 0 && y == 0) {
                            this.storage['pos'] = [ x + movex[3], y + movey[3]];
                            this.move(3);
                        } else if (x == 0 && y > 0) {
                            this.storage['pos'] = [ x + movex[1], y + movey[1]];
                            this.move(1);
                        } else {
                            this.rotate(1);
                        }
                    }
                }
            }
            this.sendMessage(undefined, "red", {'self': this.storage['pos'] });
            resolve();
        });
    },
    onmessage: function(data, fromTeam, fromBot) {},
    onkill: function() {}
});

What team are you on?

@programmer5000 Since the bots' names have to begin with the letter of the team, I guess I'm Team Red :)

Nice bot! I suggest you brodcast what's around you to your team, too.

Backup 1 another blue bot (forgot to do this earlier)
createBot({
    team: 'blue',
    name: 'backup1',
    ontick: function(environment) {
        return new Promise((resolve, reject) => {
            //if (typeof this.x != "undefined") this.storage['position'] = [this.x, this.y];
            if (typeof environment.x != "undefined") this.storage['position'] = [environment.x, environment.y]; //Modified according to @WasteD
            if (typeof this.storage['map'] == "undefined") { //Create empty map
                var map = [[]];
                //for(i=0;i<this.gridHeight;i++) map[i]=[];
                for(i=0;i<environment.gridHeight;i++) map[i]=[]; //Modified according to @WasteD
                this.storage['map'] = map;
            }
            var blue = []
            var red = []
            var x = this.storage['position'][0];
            var y = this.storage['position'][1];
            var dx = [-1, 0, 1, -1, 0, 1, -1, 0, 1]
            var dy = [1, 1, 1, 0, 0, 0, -1, -1, -1]
            (this.aroundMe || []).forEach((item, idx) => { // Update map and list positions of surrounding blues and reds
                if (item && item.team == 'red' && typeof item.name != "undefined") red += idx;
                if (item && item.team == 'red' && typeof item.name == "undefined") this.storage['map'][x+dx[idx]][y+dy[idx]] = 'M';
                if (item && item.team == 'blue' && typeof item.name != "undefined") blue += idx;
            });
            this.sendMessage(undefined, "blue", {"position": this.storage['position'], 'map': this.storage['map']}); //Send to buddies my position and the map
            if (red.indexOf([1, 4, 6, 3][this.direction]) > -1) this.kill() ; //If red guy is in front of
            else if (red.indexOf([1,4,6,3]) > -1) this.rotate(red.indexOf([1,4,6,3])); //If red guy is next but not in front of
            else if (blue.indexOf(3) > -1){ //If blue buddy on the left
                if (blue.indexOf(4) > -1){ //If another one is on the right
                    if (blue.indexOf(1) > -1 && this.direction != 2) this.rotate(2); //...and a third one at the top
                    else var digging = this.dig();
                    }
                else if (this.direction != 1) this.rotate(1);
                else var digging = this.dig();
            }
            else if (blue.indexOf(1) > -1){
                if (blue.indexOf(6) > -1 && this.direction != 3) this.rotate(3);
                else if (this.direction != 2) this.rotate(2);
                else var digging = this.dig();
            }
            else if (blue.indexOf(4) > -1){
                if (this.direction != 3) this.rotate(3);
                else var digging = this.dig();
            }
            else if (blue.indexOf(6) > -1 && this.direction != 0) this.rotate(0);
            else if (blue.indexOf([0,2]) > -1){ //If no blue next to me but one in diagonal, move next
                this.move(1);
                this.storage['position'][1] = y+1; //Update position
            }
            else if (blue.indexOf([5,7]) > -1){
                this.move(6);
                this.storage['position'][1] = y-1;
            }
            else if (typeof this.storage['other_blue'] != "undefined"){ //Check if buddies said where they were, try to go near the closest one
                var dmin = 99999;
                var pos = []
                (this.storage['other_blue'] || {}).forEach((item, idx) => {
                    var d = Math.sqrt(Math.pow(item['position'][0]-x,2) + Math.pow(item['position'][1]-y,2));
                    if (d < dmin){
                        dmin = d;
                        pos = item['position'];
                        }
                });
                if (pos[0]-x > 0){
                    this.move(4);
                    this.storage['position'][0] = x+1
                }
                else if (pos[0] < 0){
                    this.move(3);
                    this.storage['position'][0] = x-1
                }
                else if (pos[1] > 0){
                    this.move(1);
                    this.storage['position'][1] = y+1
                }
                else{
                    this.move(6);
                    this.storage['position'][1] = y-1
                }
            }
            else var digging = this.dig();
            if (typeof digging != "undefined"){ //Check out surroundings if dig() was played and update the map accordingly
                var dx2 = [-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2];
                var dy2 = [2,2,2,2,2,1,1,1,1,1,0,0,0,0,0,-1,-1,-1,-1,-1,-2,-2,-2,-2,-2];
                (digging || []).forEach((item, idx) => {
                    //if (item && item.team == 'red' && typeof item.name == "undefined") this.storage['map'][x+dx2[idx]][y+dy2[idx]] = 'M';
                    if (item) this.storage['map'][x+dx2[idx]][y+dy2[idx]] = 'M'; //previously misread what dig() returned
                });
            }
            resolve();
        });
    },
    onmessage: function(data, fromTeam, fromBot) {
        if (typeof data['position'] != "undefined" && fromTeam == 'blue') { //If position sent by a blue bot
            if (typeof this.storage['other_blue'] == "undefined") this.storage['other_blue'] = [];
            for (i in this.storage['other_blue']){
                var found = false;
                if ('name' in i){
                    if (i['name'] == fromBot){
                        i['position'] = data['position'];
                        found = true; //Update if position already known from previous ticks
                        }
                }
            }
            if (!found) this.storage['other_blue'] += {'position':data['position'], 'name':fromBot}; //Add position if previously unknown
            this.sendMessage(fromBot, undefined, "roger.");
        }
    },
    onkill: function() {this.sendMessage(undefined, "blue", {"position": this.storage['position'], 'map': this.storage['map']});}
});

Blue Fighter
createBot({
  team: "blue",
  name: "blue-fighter",
  ontick: function(environment) {
    return new Promise((resolve, reject)=>{
      let map = environment.aroundMe;
      let sides = [1, 4, 6, 3];
      let facing = sides[this.direction];
      let isTeam = (team,a) => a && a.team === team;
      let isRed = (a)=>isTeam("red",a);
      let isBlue = (a)=>isTeam("blue",a);
      let randomSquare = ()=>Math.floor(Math.random()*8);
      let redNum = map.filter(isRed).length;
      let blueNum =  map.filter(isBlue).length;
      if(redNum > blueNum && redNum > 2){
        this.bomb();
      }else if(isRed(map[facing])){
        this.kill();
      }else if(sides.includes(map.findIndex(isRed))){
        this.rotate(sides.indexOf(map.findIndex(isRed)));
      }else if(Math.random() < 0.5 && this.landMines > 0){
        this.landMine(randomSquare());
      }else{
        this.move(randomSquare());
      }
      resolve();
    });
  },
  onmessage: function(data, from, fromBot) {},
  onkill: function(){}
});

Blue fighter moves and landmines randomly and rotates toward red players. If the surrounding blocks have more red than blue, it bombs. If it is facing a red player, it kills it.


text:
Get a random n digit number with distinct digits and first not a 0
I read this question and thought it would make a nice challenge.
Task
Give an input 0<n<10 generate a random number with

exactly n digits
the first not a 0

so f(n)>10**(n-1)-1

distinct digits

Winning criteria
This is code-golf so shortest code wins.
Random
I mean evenly distributed random. So from the view of the program each possible number has the same chance. If the language you're writing in has a weird random number generator, it's okay to use that one.
Example
The list of values to randomly select from for n=2 is:
[10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98]

Requiring randomness without specifying a distribution should be avoided.

return as an integer, not a string, yes?

@Giuseppe generate a random number

When you say distinct digits you mean a number like 375 is acceptable but 337 is not?

Is pseudo-random allowed? For example I can use current UTC time as a "seed" for a scrambling function so it's not true random because the output can be easily predicted but if you run the program multiple times (seconds apart each time) the output will differ. I guess what I'm asking is, does output have to be RANDOM or just non-static

I think of this every single time someone makes a random number question https://xkcd.com/221/

In chat recently it came up that this challenge is a bit unclear at the lower end. What output is expected for n=0? Is 0 a valid output for n=1? It'd be easiest to set the minimum n to 2 to avoid having to define these corner cases (especially as they may cost quite a few bytes for many of the solutions).

@ais523 "Give an input 0<n<10 generate a random number with"

I agree with ais523, though. I'd like to know if we can output zero for n=1. My answer currently can.

@ais523 no you don't have to handle n=0. In the Task section it says 0<n<10. no 0 isn't a valid output for n=1 since 10**(1-1)-1=0 and  0 is not greater than 0

 Is it acceptabel if the first number is a 0 if it's only 10% of the cases?

Python 2, 77 bytes
from random import*
r=range(10)
while[1]>r:shuffle(r)
print`r`[1:input()*3:3]

Try it online!
Shuffles the list of 10 digits until it doesn't start with 0, then makes a number with the first n digits listed.

Definitely runs faster and with less memory for input of 9 or 10.

Neat solution! Could you explain how the [1::3] works to convert it from a list to a string? I've never seen that before.

@JulianWolf It only works if each element of the list is the same length. It actually takes the string representation of the list, then slices it taking every 3rd character after skipping the first [.

@JulianWolf [1::3] gets the character at index 1, then every third. For [1, 2, 3], that gives 123, skipping the brackets, commas, and spaces.

Shoot, okay—that makes sense. I was forgetting that [1, 2, 3] had already been stringified and that commas and spaces needed skipping. Thanks!

Brachylog, 9 10 bytes
{~lℕ₁≜≠}ᶠṛ

Try it online!
As usual for Brachylog, this is a function submission. The TIO link above has been given a command-line argument to make the function into a full program.
I had to add an extra byte from the first version of this, changing ℕ to ℕ₁, to disallow the output 0 (something that's now been clarified).
Explanation
{~lℕ₁≜≠}ᶠṛ
{      }ᶠṛ  Pick a random value with these properties:
 ~l           it has length equal to the input;
   ℕ₁         it's a positive integer;
     ≜        it's a specific value (not a constraint);
      ≠       all its elements (digits in this case) are different.

Fairly inefficient, because the interpreter generates a list of all possible values and then picks one at random (that's what ᶠṛ means; Brachylog didn't have a "pick a random solution" option at the time this question was asked).
Some comments on the labelization here: if the ≜ is omitted, the section within the braces only produces one value, a constraint representing numbers with the property we want; picking a random result therefore gives us the constraint, and the interpreter outputs the minimum absolute value that meets the constraint (1, 10, 102, 1023, 10234, etc.), which is not what we want. We thus have to force it to construct the list via an explicit labelization.
Most Prolog implementations I've seen have a builtin to find a random result matching a constraint, but typically not with uniform probability; Brachylog didn't have one, though (one got added in response to this challenge, but obviously I can't use it due to loophole rules). If it did, and if it happened to give uniform probability on this problem, this program would just be ~lℕ₁≠ followed by that builtin, for a likely length of 6 bytes.
Brachylog, 8 bytes, in collaboration with @Fatalize
~lℕ₁≠≜ᶠṛ

Try it online!
This is the sort of genius low-level trick that only makes sense with the way Prolog does things, and doesn't make much sense when described mathematically.
As before, ~lℕ₁≠ builds up a value that describes a constraint ("length equal to the input, natural number, all elements different"). Then ≜ᶠ generates all possible values that meet the constraint. The point here is that with Brachylog's evaluation sequence, no actual choices are made until the ≜ appears, so the "find all solutions" operation ᶠ need apply to nothing but the "specific value that fulfils a constraint" operation ≜. That means there's no need for a {…} to select its scope, saving 2 bytes.

I was going to post a solution with ≜₁ before I realized that it was added because of this challenge

Jelly, 9 bytes
⁵*ṖQL$€MX

Try it online! (won't work at TIO for n > 6 due to the inefficiency of the implementation)
or an alternative implementation of the same thing:
⁵*ṖQL$ÐṀX

How?
This is pretty sneaky, and very inefficient! Jelly does some useful things implicitly when an atom expects a list but receives an integer (this is by design).
This code uses a couple of these useful implicit actions:

The monadic atom Ṗ, "pop", when called with an integer input implicitly makes a range from which to pop, so an input of n first makes [1, 2, ..., n], then pops, yielding [1, 2, ..., n-1].
The monadic atom Q, "de-duplicate" or "unique", when called with an integer input implicitly makes a decimal list to de-duplicate, so an input of n where:
n = dk-1×10k-1 + dk-2×10k-2 + ... + d1×10 + d0
first makes
[dk-1, dk-2, ... ,d1, d0]
and then yields the unique values by first appearance.
So, for example, n = 5835518 would yield [5, 8, 3, 1].

Furthermore the monadic atom M, "maximal element indexes", returns the indexes of the maximal items from a list, this saves two bytes over the far more obvious alternative of testing for equality with the input and finding truthy indexes, ⁵*ṖQL$€=⁸TX, or ⁵*ṖðQL⁼ð€TX

⁵*ṖQL$€MX - Main link: n                       e.g. 2
⁵         - literal 10
 *        - exponentiate: 10^n                      100
  Ṗ       - pop (make range 1 to 10^n, then pop)    [1  ,2  ,...,21   ,22 ,23   ,...,97   ,98   ,99]
     $€   - last two links as a monad for €ach:
   Q      -   unique (makes a decimal list first)   [[1],[2],...,[2,1],[2],[2,3],...,[9,7],[9,8],[9]]
    L     -   length                                [1  ,1  ,...,2    ,1  ,2    ,...,2    ,2    ,1  ]
       M  - indexes of maximal elements             [        ...,21       ,23,   ...,97   ,98       ]
          -                                         - i.e. all n-digit numbers with n-distinct digits.
        X - pick a random element from that list

This is all quite quite inefficient, both in time and memory: first a list of 10n integers is made and one is discarded, then for each of these a list of n integers (not some fancy 4-bit object or enum) is made and then de-duplicated. This de-duplication has a completely list-based implementation (no sets, sorted-sets, or dictionaries are involved under-the-hood, each digit is checked for existence in the list that eventually gets output).
Offline n = 7 uses ~0.5GB and takes ~25 seconds, while n = 8 uses ~4GB and takes ~5 minutes - I have not bothered running n = 9 as I only have 16GB ram (I guess it would take ~45 minutes).
The alternative implementation just uses the built-in ÐṀ quick to filter-keep minimal (which here just adds a little overhead in management for the same byte-count).

Oh wow. I was trying something very like this but missed the trick of storing the values to return in the list indexes (via suitably padding out the list), rather than trying to store them separately. This is a trick that comes in useful in Jelly fairly often and I always seem to miss it.

JavaScript (ES6), 72 71 70 69 bytes
f=(x,y="")=>x?!y.match(z=Math.random()*10|0)&&y|z?f(x-1,y+z):f(x,y):y

This is a recursive function that takes in the number of digits x. The second parameter y, initially set to the empty string, keeps track of the number as we generate it digit by digit.
First we generate a random digit z with Math.random()*10|0. Now, we want to check that the y does not contain z, and that y and z are not both 0.
We can calculate the first condition with !y.match(z). y.match(z) returns an array (always truthy) if y contains z, null (falsy) otherwise; the ! converts this to a boolean and inverts it.
The second condition is checked with y|z. Although y is a string, JS implicitly converts it to an integer when using |. This is a positive integer if y already contains digits, 0 otherwise. The net result is that y|z returns 0 iff y is empty and z is 0, or a positive integer otherwise.
If both of these conditions are true, then we append the digit to y, decrement x, and start the process over again. Otherwise, we simply return to the beginning and hope that the next random digit works. When x reaches 0, we simply return the empty string to end the recursion.

Previous version:
f=(x,y)=>x?~y>>(z=Math.random()*10|0)&1&&y|z?z+f(x-1,y|1<<z):f(x,y):""

This is a recursive function that takes in the number of digits. The initially undefined second parameter, y, is a 10-bit lookup table telling us which digits we already have, conveniently stored as an integer.
First we generate a random digit z with Math.random()*10|0. Now, we want to check that the z'th least significant bit of y is not set, and that y and z are not both 0.
We can calculate the first condition with ~y>>z&1; invert y, shift it z bits to the right, and take only the least significant bit. This gives 1 if we have not yet generated the digit in question, or 0 otherwise.
The second condition was initially pretty difficult to figure out (I tried using y/z at first to generate NaN if they're both 0), but at some point I realized that simply y|z would do the trick. The result is 0 iff both y and z are 0; a positive integer otherwise.
If both of these conditions are true (~y>>z&1&&y|z), then we generate the rest of the number and prepend z. The rest of the number is generated by calling the function again with x-1 and y|1<<z (y, but with the bit at index z set to 1). When x reaches 0, we simply return the empty string to end the recursion.

Jelly, 11 bytes
9Xœ|⁵ḶẊ¤ḣ¹Ḍ

Try it online!
How it works
9Xœ|⁵ḶẊ¤ḣ¹Ḍ  Main link. Argument: n

9            Set the return value to 9.
 X           Pick; pseudo-randomly select an integer from [1, ..., 9].
       ¤     Combine the three preceding links into a niladic chain.
    ⁵          Yield 10.
     Ḷ         Unlength; yield [0, ..., 9].
      Ẋ        Shuffle; pseudo-randomly select a permutation of [0, ..., 9].
  œ|         Multiset OR; prepend the selected integer to the selected permutation
             and remove the second occurrence of the first element.
         ¹   Identity; yield n.
        ḣ    Head; keep the first n digits of the permutation.
          Ḍ  Undecimal; convert from base 10 to integer.

That's a very clever way to remove the duplicate...

Python 2, 89 81 80 bytes
from random import*
lambda n:choice([i for i in range(10**n)if`set(`i`)`[5*n:]])

Try it online

I don't think you need a start value for the range.

Nice! That'll slow it down. :D Too bad I can't use a generator instead of a list.

Only by 11%. Drop in a bucket for code golf.

Yeah, I should use 99**n, just to be sure I get them all. :D

I looked at doing it this way too, but got 80, by using if`set(`i`)`[5*n:]].

R, 45 Bytes
k=0
i=scan()
while(!k[1])k=sample(0:9)[1:i]
k

I think you can just set k=0 since it's an implicit vector of length one, and you can use i=scan() to take input from stdin as a number.
I'm also not sure that a list of digits is a "correct" submission, but I'm not the judge.

@Giuseppe Thanks for the input, updated both of your suggestion (on both posts), thanks.

Would while(!k[1]) work to save 2 bytes?

@BLT Updated, thanks.

ClojureScript, 81 79 bytes
#(let[a(subvec(shuffle(range 10))0 %)](if(=(a 0)0)(recur %)(int(apply str a))))

This is an anonymous function, so you have to use it like this:
(#(...) {arguments})

Where you replace {arguments} with your arguments.
You can try the code here (ClojureScript REPL).
Thanks @cliffroot for shaving off 2 bytes!

Expanded code:
(defn random-digits [n]
  (let [num-vector
        (subvec
          (shuffle (range 10))
          0 n)]
    (if (= (num-vector 0) 0)
      (recur n)
      (int (apply str num-vector)))))

Explanation:
I'm going to go through the lines one by one, using an example input of 8.

(defn random-digits [n] ...)

Pretty simple, this defines the function random-digits with one argument, called n. In my answer I used an anonymous function (#(...)), to save bytes.

(let [num-vector ...] ...)

Let's examine inside the let, from inside out:
(shuffle (range 10))

In ClojureScript (and Clojure), (range n) is similar to Python's range(n): it gives you a list with every number from 0 to n - 1 (9 in this case).
shuffle takes a list, and returns a vector (which is slightly different from a list) with all of its elements shuffled. So, using our example, we get something like this:
[1 0 8 3 6 7 9 2 4 5]

(subvec {see above} 0 n)

(subvec vector start end) takes a vector (only a vector), and returns a vector which has all the elements from index start to end. In this case, we're taking elements from the 0th element to the argument given to random-digits. If we apply that to our example, we get:
[1 0 8 3 6 7 9 2]

(if (= (num-vector 0) 0)
  (recur n)
  (int (apply str num-vector)))

This if statement checks if the first element of num-vector is a 0.
If it is 0, then we call the function again, with the argument n, using recur.
If it isn't 0:

(int (apply str num-vector))

(apply function list) takes a list, and spits them into the function as arguments. For example:
(apply + [2 3 4])

Turns into:
(+ 2 3 4)

Which equals 9.
(str items) turns every item in items into a string, and then concatenates them. int converts anything to an integer. So if we apply this to our example, we get:
   (int (apply str [1 0 8 3 6 7 9 2]))
=> (int (str 1 0 8 3 6 7 9 2))
=> (int "10836792")
=> 10836792

Which is our final answer.

Gotta love ClojureScript for allowing (int string) instead of (Integer/parseInt string) :)

@cliffroot I mean, you can do read-string in Clojure, but it's not much better...

2 bytes saved #(let[a(subvec(shuffle(range 10))0 %)](if(=(a 0)0)(recur %)(int(apply str a)))) moves apply str part to the end, allows to compare to 0 instead of \0 and uses subvec instead of take allows to use vector as a function and thus to remove first

@cliffroot Huh, did not know that shuffle turned the collection into a vec. Thanks! Will have to write a new explanation, though...

Bash + GNU utils, 46
seq 1e$[$1-1] 1e$1|egrep -v '(.).*\1'|shuf -n1

Try it online.
This takes a long time for larger n - about 30s for n=7, and increasing 10 times for each increment, so probably 8-9 hours for n=10.

per the question, n=10 doesn't need to even work, much less be fast

Java 10, 150 147 145 134 132 110 bytes
n->{var r="";for(int l,x;(l=r.length())<n;x*=Math.random(),r+=(l<1?x>0:!r.contains(""+x))?x:"")x=10;return r;}

-2 bytes thanks to @TheLethalCoder
-2 bytes thanks to @ceilingcat.
Try it online.
Explanation:
n->{                    // Method with integer parameter and String return-type
  var r="";             //  Result-String, starting empty
  for(int l,x;          //  Temp integers
      (l=r.length())<n  //  Loop until the length of the String is equal to the input:
      ;                 //    After every iteration:
       x*=Math.random(),//     Pick a random digit
       r+=              //     Append to the result-String:
          (l<1?         //      If the String is empty:
            x>0         //       Make sure the first random digit is not 0
           :            //      Else (the String is not empty):
            !r.contains(""+x))
                        //       Check that the String doesn't contain this digit yet
          ?             //      And if that's truthy:
           x            //       Append the random digit
          :             //      Else:
           "")          //       Leave the String the same by appending an empty String
    x=10;               //   (Re)set `x` to 10 for the next random digit
  return r;}            //  Return the result-String

Can you not use a lambda expression here? i.e. n->... or is that Java 8+?

You can also borrow the trick I just used in my answer, set the length in the comparison check i.e. for(int l,x;(l=r.length())<n;) and you should save a byte.

@TheLethalCoder Ah of course, thanks. Great teamwork! ;) And yes, n->... is Java 8. Personally I prefer to codegolf in Java 7, even though 8 is always shorter.

@ceilingcat Thanks. And been able to golf a bit more.

APL (Dyalog), 27 19 17 bytes
Requires ⎕IO←0 which is default on many systems.
10⊥⊢↑{?⍨10}⍣{×⊃⍺}

Try it online!
Shuffles the digits until valid:
10⊥ decode from base-10 digits to regular number,
⊢ the n
↑ first elements of
{…}⍣{…} repeating the function…
 ?⍨10 shuffle the first ten positive integers
until…
 ⊃⍺ the first digit of the last attempt
 × is positive

PHP, 67 Bytes
Online Version
All versions based of shuffle the digits from 0-9
for($a=range(0,9);!$a[0];)shuffle($a);for(;$i<$argn;)echo$a[+$i++];

71 Bytes
for($s="0123456789";!$s[0];)$s=str_shuffle($s);echo substr($s,0,$argn);

73 Bytes
for($a=range(0,9);!$a[0];)shuffle($a);echo join(array_slice($a,0,$argn));

Perl 6, 44 bytes
{(->{+[~] (^10).pick($_)}...*>9 x$_-1).tail}

Try it
Expanded:
{  # bare block with implicit parameter ｢$_｣
  (

    ->{  # pointy block lambda with no parameters

      +                # turn the following into a numeric
      [~]              # concatenate the following

        (^10).pick($_) # grab $_ digits at random from 0..9
    }

    ...                # keep doing that until

    * > 9 x $_-1       # one of them is big enough

  ).tail # return the last one (only valid one)
}

MATL, 15 bytes
`4Y2GZr1)48=]8M

Try it at MATL Online!
Explanation
`        % Do...while
  4Y2    %   Push predefined literal '0123456789'
  G      %   Push input n
  Zr     %   Random sample of n unique characters from that string
  1)     %   Pick the first
  48=    %   Is it 48? This is the loop condition
]        % End. If top of the stack evaluates to true: next iteration
8M       % Push the latest random sample. Implicitly display

Jelly, 12 bytes
9×!X+!Œ?’ḣƓḌ

Currently one byte behind my other Jelly answer, but I really like this one.
Try it online!
How it works
9×!X+!Œ?’ḣƓḌ  Main link. No arguments.

9             Set the argument and the return value to 9.
  !           Yield 9!
 ×            Compute 9 × 9!.
   X          Pick; pseudo-randomly select an integer j from [1, ..., 9 × 9!].
     !        Yield 9!
    +         Compute k := j + 9!.
              The result will belong to [9! + 1, 10!].
      Œ?      Get the permutation P of R := [1, ..., r], with minimal r, such that
              P is the lexicographically k-th permutation of R.
              Since k belongs to [9! + 1, 10!], r = 10 and this generates a per-
              mutation between [2,1,3,4,5,6,7,8,9,10] and [10,9,8,7,6,5,4,3,2,1].
        ’     Subtract 1 from all integers in P.
          Ɠ   Read an integer n from STDIN and yield it.
         ḣ    Head; keep the first n digits of the permutation.
           Ḍ  Undecimal; convert from base 10 to integer.

05AB1E, 9 7 10 9 bytes
°L¨ʒÙgQ}Ω

Very slow for larger \$n\$.
Try it online or verify some more test cases.
+3 +2 bytes because I missed the requirement of an evenly distribution..
Original invalid 7 byter solution:
(can output all random outputs, but not evenly distributed)
žh.rïI£

Try it online or verify some more test cases.
Explanation:
°           # Push 10 to the power of the (implicit) input-integer
 L          # Push a list in the range [1, 10**input]
  ¨         # Remove the last value to make the range [1, 10**input)
   ʒ        # Filter this list by:
     g      #  Where the amount
    Ù       #  of the unique digits
      Q     #  is equal to the (implicit) input-integer
       }Ω   # After the filter: pop and push a random element of the list
            # (after which it is output implicitly as result)

žh          # Push the builtin string "0123456789"
  .r        # Randomly shuffle it
    ï       # Cast it to an integer to remove any potentially leading 0s
     I£     # Only leave the first input amount of digits
            # (after which it is output implicitly as result)

W, 6 bytes
To make this work, you need an extra operand (e.g. ""). After providing it, this W script would ignore this operand.
"▬←l╟B

Uncompressed:
U=a^(Xg

Explanation
  a     % Take a single input
   ^    % 10 ** input
    (   % Decrement by 1 so that special cases like 100 would be avoided
     X  % Filter out all items in the implicit range 1 to operand
U       % Uniquify (the current item)
        % This also implicitly converts the current item to a string
 =      % Check whether (the length of) the current item is equal to (the input)
      g % *Evenly* Pick a random number in the list.

@JonathanAllan It firstly generates a range from 10**(x-1) to 10**x, uniquifies every item of the list, then filters out all numbers of the length of the input.

C (gcc), 123 122 100 95 104 103 99 97 bytes
This one generating an actual random number
j;f(n){for(int i,k=n,s[10]={j=0};n;s[i+=i?0:k==n]=!s[i]?j+=i*pow(10,--n):1)i=rand()%10;return j;}

Try it online!
C (gcc), 87 85 bytes
Here it is printing a string of digits.
f(n){for(int i,k=n,s[10]={0};n;s[i+=i?0:k==n]=!s[i]?--n,putchar(48+i):1)i=rand()%10;}

Try it online!

Bash, 66 bytes
a=0;while [[ $a == 0* ]];do a=`shuf -i0-9 -n$1|xargs`;done;echo $a

Try it online!
Straight forward, usues shuf, xargs is used to join lines and continues to try while the combination starts with 0.
Cant beat 46 char from other answer but thus is fast!

PHP, 65 63 bytes
while(count(count_chars($x=rand(1,10**$argn),1))<$argn);echo$x;

takes input from STDIN; run with -nR.
create random number between 1 and 10^N inclusive;
repeat while count of distinct characters is < N.

while(count(count_chars($x=rand(1,10**$argn),1))<$argn);echo$x; -2 Bytes

Pyth, 15 28 bytes
=+YhO9VtQ#KOTI!hxYK=+YKB;jkY

Try it here

Welcome to PPCG, and great job using a golfing language right off the bat :-) I see 2 small issues: 1) it seems that the second digit is always 0, so I think you'll want to change ^TttQ to ^TtQ (-1 byte, bonus!). 2) all digits in the output must unique, so you'll have to force that to happen somehow.

@ETHproductions  Arg!! Thanks for pointing that out.  I've fixed it.

Python 2, 100 93 92 90 bytes
Thanks to @mbomb007 for shaving off 2 bytes
from random import*
def f(n):k=randint(10**~-n,10**n-1);return(n==len(set(`k`)))*k or f(n)

Tries numbers in the required until one is found with unique digits. I'll bet there's a much cleaner way to do this, but none's coming to mind.

return(n==len(set(\k`)))*k or f(n)`. Try it online

Pyth, 11 bytes
jk<{+OS9.ST
jk<{+OS9.STQ implicit Q

       9     9
      S      [1,2,3,4,5,6,7,8,9]
     O       random element

          T  10
        .S   random permutation of [0,1,2,3,4,5,6,7,8,9]

    +        add the results from the previous two paragraphs together
   {         deduplicate
  <        Q first (input) elements
jk           join by empty string

Uses the same algorithm as Dennis' answer.
Try it online!

Perl, 48 bytes
1until$_=1+int rand 10**$n-1,/.{$n}/&&!/(.).*\1/

Explanation:
Repeatedly generate random integers from 1 to 10**$n-1, rejecting them until there is one of the correct length (so at least 10**($n-1)) with no repeated digits.

C#, 127 132 128 126 125 bytes
n=>{var s="";for(int l,r;(l=s.Length)<n;)if((l<1&(r=new System.Random().Next(10))>0)|(l>0&!s.Contains(r+"")))s+=r;return s;};

Try It Online!
Borrowed the idea from @KevinCruijssen's answer to initialise the random, r, in the if statement to save 2 bytes.
Pretty sure this can be golfed further but I don't have time at the moment.

Old version using a while loop:
n=>{var s="";while(s.Length<n){int r=new System.Random().Next(10);if(s.Length<1&r>0)s+=r;else if(!s.Contains(r+""))s+=r;}return s;};

I don't think this is correct. Let's say the first random integer is 0, it would first try if(s.Length<1&r>0) which is false, but then it will do if(!s.Contains(r+"")) which is true and still append "0" to s as first digit.

@KevinCruijssen Fixed and golfed further

I was about to post a Java answer which is exactly the same as your new answer. :) The only difference (and you can also golf this), is int l=0,r; instead of int l=0,r=0;. So it becomes n=>{var s="";for(int l=0,r;l<n;l=s.Length){r=new System.Random().Next(10)if((l<1&r>0)|(l>0&!s.Contains(r+"")))s+=r;}return s;}; (127 bytes)

@KevinCruijssen I can only seem to get that at 128 bytes still, not sure why. And if you haven't already feel free to post your answer :)

@KevinCruijssen Ah I've worked it out, in your example you don't end the .Next(10)... with a ;. So no further improvements there, but good idea.

I have just posted it. And oops, you're right I missed that semi-colon.. You can still golf it like this though: n=>{var s="";for(int l=0,r;l<n;l=s.Length)if((l<1&(r=new System.Random().Next(10))>0)|(l>0&!s.Contains(r+"")))r+=x;return s;}; :)

@KevinCruijssen I just borrowed the idea from your answer as you was writing that comment! Nice improvement thanks

Let us continue this discussion in chat.

Batch, 156 bytes
@set/af=9,r=x=0
@for /l %%i in (1,1,%1)do @call:c
@echo %r%
@exit/b
:c
@set/a"d=9-%random%%%f,e=x>>d&1
@if %e%==1 goto c
@set/a"r=r*10+d,f=10,x|=1<<d

x maintains a bitmask of used digits. f indicates the number of available digits (counting down from 9). Random digits are generated until an unused digit is found. n=10 could be supported for 165 bytes:
@set/af=9,r=x=0
@for /l %%i in (1,1,%1)do @call:c
@echo %r:~1%
@exit/b
:c
@set/a"d=9-%random%%%f,e=x>>d&1
@if %e%==1 goto c
@set r=%r%%d%
@set/a"f=10,x|=1<<d

(r contains an extra leading zero because it's golfier that way.) Previous approach for 165 bytes special-cased the first digit, and also happened to work with n=10 (the numeric version actually took 166 bytes!):
@set/ar=%random%%%9+1,x=0
@for /l %%i in (2,1,%1)do @set/a"x|=1<<d"&call:c
@echo %r%
@exit/b
:c
@set/a"d=%random%%%10,e=x>>d&1
@if %e%==1 goto c
@set r=%r%%d%

Original approach for 170 bytes also worked for n=10:
@set/ar=%random%%%9+1
@for /l %%i in (2,1,%1)do @call:c
@echo %r%
@exit/b
:c
@set/ad=%random%%%10
@call set s=%%r:%d%=%%
@if not "%s%"=="%r%" goto c
@set r=%r%%d%

Uses string manipulation to detect duplicate digits.

Jellyfish, 17 bytes
p
d^u ?
 j?r10
10

Try it online!
Fork of Dennis' Jelly answer.

MathGolf, 10 11 bytes
úr╞gÆ░▀£k=w

Try it online!
Explanation
úr            push [0, ..., (10**input)-1]
  ╞           discard the first item of the list (0)
   gÆ         filter by block of 5 operators
     ░        convert to string (needed for "unique elements" operator
      ▀£      number of unique characters in string
        k=    is equal to input?
              end of block
          w   random item from the filtered list

Shouldn't the range be [1, ..., (10**input)-1]? 0 isn't a valid output for n=1.

@KevinCruijssen Good catch, added a byte.

@KevinCruijssen I thought I could get away with replacing r with ╒ (1-based range), but I noticed that input 2 could give output 100.

Mathematica 65 60 Bytes
0For[a=11,Max@DigitCount@a>1,a=RandomInteger[10^{#-1,#}]]+a&

Here is a faster version but adds 9 bytes:
FromDigits@Join[f=(s=RandomSample)[r=Range@9,1],s[r/.f[[1]]->0,#-1]]&

C, 96 93 bytes
f(n){char d[11],i=0,r;for(;i++^10;d[i-1]=d[r=rand()%i],d[r]=47+i);*d^48?d[n]=0,puts(d):f(n);}

Fisher-Yates shuffle initialization until the first digit isn't zero.
Is uniform, assuming rand()%i is uniform. (Since for most i RAND_MAX/i leaves a small remainder, there is a very small bias. This bias grows smaller as RAND_MAX grows larger.)
See it work online.
See it generate correct numbers for when n equals 2, as shown in the question.

Java 9 JShell, 86 bytes
n->new Random().longs(0,10).limit(n-1).reduce(new Random().nextInt(9)+1,(a,b)->a*10+b)

Try it online!
Note: I'm not counting the imports as those packages are imported by default in JShell, but there's no Try-it-online link that I know of for JShell, so I've provided one for Java 9 with header and footer code to make it work in that context. In JShell you can just do:
jshell> Function<Integer,Long> f =
   ...> n->new Random().longs(0,10).limit(n-1).reduce(new Random().nextInt(9)+1,(a,b)->a*10+b)
f ==> $Lambda$27/633070006@5702b3b1

And then:
jshell> f.apply(6)
$26 ==> 746202

How it works:
We define a function from Integer to Long and create an infinite stream of random longs in the range from 0-9, limit it to the first n-1 items, then reduce it with a random int from 1-9 as the initial value and a function that multiplies the value by 10 and adds the next value from the stream.
I used longs so this should work for up to about 18 digits (n = 18).

Ruby, 53 52 bytes
Shuffle until the first digit is not 0, then combine the digits and convert to an integer.
->n{a=*0..9;a.shuffle!while a[0]==0;eval a[0,n]*''}

Try it online!

Axiom, 191 bytes
g(a:NNI):Complex INT==(a<1 or a>9=>%i;r:List NNI:=[];b:=a;repeat(a=0=>break;d:=random()$INT rem 10;a=b and d=0=>0;~member?(d,r)=>(a:=a-1;r:=cons(d,r)));reduce(+,[r.i*10^(i-1)for i in 1..#r]))

ungolf it, test result
-- Return one number of 'a' different random digits if 0<a<10
f(a:NNI):Complex INT==
    a<1 or a>9=>%i
    r:List NNI:=[];b:=a
    repeat
       a=0=>break
       d:=random()$INT rem 10
       a=b and d=0  =>0
       ~member?(d,r)=>(a:=a-1;r:=cons(d,r))
    reduce(+,[r.i*10^(i-1)for i in 1..#r])

(4) -> [[i,g(i)] for i in 0..10]
   (4)
   [[0,%i], [1,9], [2,76], [3,135], [4,6810], [5,48675], [6,415768],
    [7,7461539], [8,98421537], [9,825046739], [10,%i]]
                                          Type: List List Complex Integer
(5) -> [[i,g(i)] for i in [3,3,3,3,3,3,3,3,3]]
   (5)
   [[3,653],[3,128],[3,254],[3,268],[3,914],[3,594],[3,276],[3,240],[3,398]]

C, 77 bytes
r;a;n;d(i){for(a=n=0;r=rand()%10,i-=n&1<<r?0:!!(a=a*10+r);n|=1<<r);return a;}

See it work online.
See it generate correct numbers for when n equals 2, as shown in the question.

Io, 108 bytes
With no RNG properly working (even time()!), I had to use a pseudo-random number generator with one more function operand taken.
method(X,Y,(Range 1 to(10**X-1)asList map(i,i asString asList unique join asNumber)select(>10**(X-1)))at(Y))

Try it online!

Perl 5 -pa, 45 bytes
1while($_=substr rand,2,"@F")&&/^0/+/(.).*\1/

Try it online!

Thunno 2, 7 bytes
eėæUl:ɼ

Try it online!
Explanation
eėæUl:ɼ  # Implicit input
e        # Push 10 ** input
 ė       # Then push the range [1..that)
  æ  :   # Filter this list by:
   U     #  Uniquify it
    l:   #  Does the length equal the input?
      ɼ  # Take a random item from this list
         # Implicit output

Vyxal m, 8 bytes
↵'UL?=;℅

Try it Online!
Port of my Thunno 2 answer.
Explanation
↵'UL?=;℅  '# Implicit input
↵          # Push 10 ** input
 '    ;   '# Filter [1..that) by:
  U        #  Uniquify it
   L?=     #  Does the length equal the input?
       ℅   # Take a random item from this list
           # Implicit output

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
Rewrite the Tiny BASIC IL program to support 7 changes to BASIC
Circa 1976. With the success of the Tiny BASIC Design Note, a variety of Tiny BASIC IL implementations now span a range of microcomputers. The time has come to expand the Tiny BASIC standard.
Grammar revisions:
(LET) var = expression
INPUT (string ,) var-list
PRINT expr-list (;)
IF expression relop expression (THEN) statement
DO
WHILE expression
UNTIL expression
REM any-text

Please rewrite the Tiny BASIC program in its IL to support the revised grammar above:

Make the “LET” keyword optional (prevent overbyte! e.g., X = X + 1 no longer has to be LET X = X +1).
Make the “THEN” keyword optional (e.g., IF X=21 PRINT “BLACKJACK!” becomes valid).
Support the “REM” remark statement for those people who upgraded their RAM and can waste memory with comments.
If an INPUT statement starts with a string, output that string as a prompt (e.g., INPUT “AGE?”, A).
If a PRINT statement ends with a semicolon (“;”) then suppress the carriage return.
Implement a DO-WHILE loop.
Implement a DO-UNTIL loop.

Sample loop:
10 X=10
20 DO
30 PRINT X
40 X=X-1
50 UNTIL X<0
60 REM "WHILE X>=0" WOULD ALSO HAVE WORKED
70 PRINT "BLASTOFF!"

I've lightly edited the Tiny BASIC IL Reference and program here to make both easier to follow.
This is atomic-code-golf so shortest code wins, but - since no one has an IL assembler handy and since encoding of op-codes varied anyway - in this case, the fewest lines of code wins (not counting blank lines or lines with only comments; no penalty here for readability).

Hi Jeffrey, welcome to PPCG. "no one has an IL assembler handy" I think we need an implementation of the IL to test our code on, otherwise its going to be very difficult to determine if an answer is valid. Languages are defined by implementation here. Also (before someone else says it) normally we score by bytes but in this case I understand a "line" of code means one of the 33 IL instructions. Close voting as I understand no IL assembler is available

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/


text:
Snooker scoring
I was watching the world snooker championship and it got me wondering..
Snooker scoring
In the game of snooker there are certain rules that you must adhere too:

When there are red balls on the table, during your turn you must first pot a red ball
After potting each red ball, you must pot a colored (not red) ball (the potted colored ball is then replaced onto the table)
After all the red balls are up (there are 15) you can first choose a colored ball and then you start with the lowest scoring ball and work your way up to the highest scoring ball (these are not replaced)
Not potting at any point ends your turn.
Points per ball

Red ball: 1 point
Yellow ball: 2 points
Green ball: 3 points
Brown ball: 4 points
Blue ball: 5 points
Pink ball: 6 points
Black ball: 7 points

The question
You start with a table with all the balls still on it - 15 red and one of each of the other coloured balls - and are given the score of a player in snooker after their first turn, what are the ways that they could have achieved this score?
Input will be a score going from 1 to 147. You can choose if it is an integer or a string. Output should be the different combinations of number of times you potted each ball.
Test cases:
Input: 4
Output:
1r 1g
2r 1y
Input: 25
Output:
4r 3b
5r 2b 1br 1y
5r 2b 2g
...
9r 8y

Rules:

You can choose whether you output the possibilities divided by a new line or a separator of some sort (/,;|\ or even others I'm missing)

This is codegolf, so the shortest code wins.

Can I output as list of arrays?

I'd recommend making the input score range between 1 and 147 (oh for the 155).

@LeakyNun The problem with that is that you are going to have R come back multiple times.. I think it will more clear if you just put out the number of times you use each ball. Also for most scores there are multiple combinations possible, how will you cope with that?

@JonathanAllan, I will edit that.

Regarding an array output: number of balls ordered by score is unambiguous, so maybe "5r 3b 2g" could be output as [5,0,2,0,3,0,0] (as long as this is consistent)?

What is a colored ball?

@Dennis a coloured ball is one that isn't red, probably not obvious to those who don't know the game.

Does input 2 need to be handled?

Is 2r 1y not a valid way of achieving a score of 4?

@w0lf, yes it should be there.

Btw a turn is called a break ;-) I guess we should state that we completly ignore free balls if we limit to 1 - 147?

You use b for brown and bl for blue; so bk for black? Could we use n, e and k (last letters) for these three? How about dleruna to identify all eight colours (3rd letter of each)?

@JonathanAllan, your way of output is also correct. For me it matters most that it is unambiguous. dleruna can be used, but then I would like that you also include the explanation in your answer for future viewers.

Does the order of colours in the output matter?

@Shaggy, If you use an indication of color like dleruna or another one, no. If you just use an array like [5 0 0 4 1 0 0], then they should be sorted from low to high.

Jelly,  65  25 bytes
7Ḋṗ15Ė€F;ɗ€ƊÄċƇ⁸f€RŻ€IṢ€Q

A monadic Link that accepts an integer, "score", from \$[1,147]\$ and yields a list of lists - each being a potential selection of ball scores used in reaching the given score disregarding the order in which they were actually potted.
Try it with only six reds (15 replaced with 6; again, fifteen reds would take an age).
How?
7Ḋṗ15Ė€F;ɗ€ƊÄċƇ⁸f€RŻ€IṢ€Q - Link integer, S
7                         - seven
 Ḋ                        - dequeue -> coloured ball scores, [2..7]
           Ɗ              - last three links as a monad - f([2..7]):
   15                     -   fifteen
  ṗ                       -   ([2..7]) Cartesian power (15) -> all length 15 words
                                using the coloured ball scores as letters
          €               -   for each (such Word):
         ɗ                -     last three links as a dyad - f(Word, [2..7])
                                              e.g. Word = [7,...,7]
     Ė€                   -       enumerate each          [[1,7],...,[1,7]]
       F                  -       flatten                 [1,7,...,1,7]
        ;                 -       concatenate ([2..7])    [1,7,...,1,7,2,3,4,5,6,7]
            Ä             - cumulative sums, i.e. convert each such legal way to
                              clear the table to a list of the running score
              Ƈ           - filter keep those for which this is truthy (non-zero):
               ⁸          -   chain's left argument (S)
             ċ            -   count - i.e. count of S in the running score
                  R       - range (input Score) -> [1..S]
                f€        - for each (running score list) filter keep ([1..S])
                   Ż€     - prefix each with a zero
                     I    - forward differences of each (back to ball scores)
                      Ṣ€  - sort each
                        Q - deduplicate

Original \$66\$ byte entry (\$65\$ really, since the trailing G is post-formatting):
L⁼30µÐfµ7Ḋ;\¤;€Ṣ€µ€;/
ċ1<⁴µÐfµ;Ç
7Ḋœċ⁴Ḷ¤;/L€;$€;@þ2B¤;/ḟ€0ÇS⁼¥Ðf⁸G

Well, it's too slow for TIO now!
...so here is a paste of the 2636 ways to make exactly 100 produced offline.
...and here is a version that will run there with just SIX reds (maximum break = 75)
Prints a grid of numbers each line being a space separated list of ball values (e.g. three red and two green would be on a line reading 1 1 1 3 3).

For a value-grouped version that prints lines of counts along with the full names of the balls, at 102 bytes:
ŒrÑ€
Ṫ;ị“¡^³ṗ⁼¬wḌ⁼ø÷OẏK¦ẆP»Ḳ¤$K
L⁼30µÐfµ7Ḋ;\¤;€Ṣ€µ€;/
ċ1<⁴µÐfµ;Ç
7Ḋœċ⁴Ḷ¤;/L€;$€;@þ2B¤;/ḟ€0ÇS⁼¥Ðf⁸Ñ€K€Y

How?
L⁼30µÐfµ7Ḋ;\¤;€Ṣ€µ€;/ - Link 1, create post-red-ball games: list of all pre-yellow-ball-games
    µÐf               - filter keep if:
L⁼30                  -   length equals 30 (games that get on to the yellow)
       µ         µ€   - for €ach sequence leading to the yellow:
            ¤         -   nilad followed by link(s) as a nilad:
        7Ḋ            -     7 dequeued  = [2,3,4,5,6,7]
          ;\          -     ;\ cumulative reduce with concatenation  = [[2],[2,3],[2,3,4],...]
             ;€       - concatenate the sequence with €ach of those
               Ṣ€     - sort each one
                   ;/ - reduce with concatenation (flatten by one)

ċ1<⁴µÐfµ;Ç - Link 2, filter bogus entries created and append post-yellow-ball games: list of pre-yellow-ball games (along with the bogus ones with 16 reds potted)
    µÐf    - filter keep if:
ċ1         -   count ones
   ⁴       -   literal 16
  <        -   less than?
       µ   - monadic chain separation
         Ç - call the last link (1) as a monad
        ;  - concatenate

7Ḋœċ⁴Ḷ¤;/L€;$€;@þ2B¤;/ḟ€0ÇS⁼¥Ðf⁸G - Main link: score
7Ḋ                                - 7 dequeued = [2,3,4,5,6,7]
      ¤                           - nilad followed by link(s) as a nilad:
     ⁴                            -   literal 16
    Ḷ                             -   lowered range = [0,1,2,...,15]
  œċ                              - combinations with replacement (every possible colour-ball selection that goes with the red pots)
       ;/                         - reduce with concatenation (flatten by one)
            $€                    - last two links as a monad for €ach:
         L€                       -   length of €ach (number of coloured balls potted)
           ;                      -   concatenate
                   ¤              - nilad followed by link(s) as a nilad:
                 2B               -   2 in binary = [1,0]
                þ                 - outer product with:
              ;@                  -   concatenation with reversed @rguments
                    ;/            - reduce with concatenation (flatten by one)
                      ḟ€0         - filter discard zeros from €ach
                         Ç        - call the last link (2) as a monad
                             Ðf   - filter keep:
                            ¥  ⁸  -   last two links as a dyad, with score on the right
                          S⁼      -     sum(ball values) is equal to score?
                                G - format as a grid
                                  - implicit print

It works well for all the cases I have tried. Only in some cases the last code gives leading zeros.

Ah yes they should have been filtered out... Fixed.

Your output for the 53 one is unambiguous as I said before, but I'm still doubting if it is readable for everyone..

It is much better in the grid way. If there aren't any shorter answers in the next few days, I am going to accept your answer!

Hmm. I get 2636 century break combinations. So either you or I are wrong...

@Arnauld I now have 2636 ways too! Editing in my fix.

Ah! Awesome! :-)

JavaScript (ES7), 188 180 178 bytes
Returns an array of arrays (sorted from red to black).
n=>[...Array(17**6)].map((_,x)=>[2,3,4,5,6,p=7].map(v=>(k=a[++j]=x%17|0,x/=17,t+=k,p+=!!(y=y&&k),s-=k*v),y=s=n,a=[j=t=0])&&(s==15|s>=t)&s<16&s<t+2&t<9+p&&(a[0]=s,a)).filter(a=>a)

Commented
Note: This version doesn't include the last optimization on p (now initialized to 7) which makes the logic harder to understand.
n =>                              // given a target score n:
  [...Array(17**6)].map((_, x) => // for each x in [0 .. 17^6 - 1]:
    [2, 3, 4, 5, 6, 7].map(v =>   //   for each v in [2 .. 7] (yellow to black):
      ( k = a[++j] = x % 17 | 0,  //     k = a[j] = number of colored balls of value v
        x /= 17,                  //     update x to extract the next value
        t += k,                   //     update t = total number of colored balls
        p += !!(                  //     update p = number of consecutive colors that were
          y = y && k              //     potted at least once, using y = flag that is zeroed
        ),                        //     as soon as a color is not potted at all
        s -= k * v ),             //     subtract k * v from the current score s
      y = s = n,                  //     initialize y and s
      a = [j = t = p = 0]         //     initialize a, j (pointer in a), t and p
    )                             //   at this point, s is the alleged number of red balls
    &&                            //   this combination is valid if we have:
      (s == 15 | s >= t) &        //     - 15 red balls or more red balls than colored ones
      s < 16 &                    //     - no more than 15 red balls
      s < t + 2 &                 //     - at most one more red ball than colored ones
      t < 16 + p                  //     - no more than 15 + p colored balls
    &&                            //   if valid:
      (a[0] = s, a)               //     update the combination with red balls and return it
  ).filter(a => a)                // end of outer map(): filter out invalid entries

Example output
Below is the output for n = 140:
//  R   Y  G  Br Bl P  Bk
[ [ 15, 1, 1, 1, 1, 8, 9  ],
  [ 15, 1, 1, 1, 2, 6, 10 ],
  [ 15, 1, 1, 1, 3, 4, 11 ],
  [ 15, 1, 1, 2, 1, 5, 11 ],
  [ 15, 1, 1, 1, 4, 2, 12 ],
  [ 15, 1, 1, 2, 2, 3, 12 ],
  [ 15, 1, 2, 1, 1, 4, 12 ],
  [ 15, 1, 1, 2, 3, 1, 13 ],
  [ 15, 1, 1, 3, 1, 2, 13 ],
  [ 15, 1, 2, 1, 2, 2, 13 ],
  [ 15, 2, 1, 1, 1, 3, 13 ],
  [ 15, 1, 2, 2, 1, 1, 14 ],
  [ 15, 2, 1, 1, 2, 1, 14 ],
  [ 15, 1, 1, 1, 1, 1, 15 ] ]

Demo
This is too slow for a snippet. You can try it here instead. (You may get one or two unresponsive script alerts, but it should eventually complete.)