# 10 Generate a maze in Minecraft

This example illustrates how to generate a perfect maze from R and the render in Minecraft.

## 10.1 Generate a random maze

First, we need to generate a maze, for which we will use the `Rmaze`

R package’s depth-first search algorithm. As the package is not on CRAN, you have to install from GitHub:

`devtools::install_github('Vessy/Rmaze')`

Then load the package and generate a maze with, for example, 10 x 10 tiles:

```
library(Rmaze)
n <- 10
maze <- makeGraph(n, n)
set.seed(42)
maze <- makeMaze_dfs(maze)
```

This is a graph representation of the maze, which can be rendered with `ggplot2`

very easily:

`plotMaze(maze, n, n)`

## 10.2 Transform maze graph into matrix

Now we have to transform this graph representation into a binary matrix, where we see in 2D which blocks need to be air or wall. Let’s start with a large empty `matrix`

allowing 4 block for every single cell, as in the matrix we will use blocks for the wall as well (unlike in the above plot):

`df <- matrix(NA, nrow = n*4, ncol = n*4)`

Then let’s mark the surrounding border with ones:

```
df[c(1, nrow(df)), ] <- 1
df[, c(1, nrow(df))] <- 1
```

Here is the top corner of the matrix now:

`df[1:4, 1:4]`

```
## [,1] [,2] [,3] [,4]
## [1,] 1 1 1 1
## [2,] 1 NA NA NA
## [3,] 1 NA NA NA
## [4,] 1 NA NA NA
```

But we should leave the entrance and exit open in the bottom left and top right corner:

```
df[1, ncol(df) - 1:2] <- NA
df[nrow(df), 2:3] <- NA
```

Here is the top right corner showing the maze exit we just made:

`df[1:4, ncol(df) - 3:0]`

```
## [,1] [,2] [,3] [,4]
## [1,] 1 NA NA 1
## [2,] NA NA NA 1
## [3,] NA NA NA 1
## [4,] NA NA NA 1
```

Now we need to convert the graph object into a `data.frame`

on which we can iterate later to render the actual wall blocks:

```
library(igraph)
mazedf <- as_data_frame(maze)
library(data.table)
setDT(mazedf)
```

Then let’s extract the `x`

and `y`

positions from the `A_x_y`

names:

```
for (v in c('from', 'to')) {
mazedf[, (paste0(v, 'x')) := as.numeric(sub('A_([0-9]*)_[0-9]*', '\\1', get(v)))]
mazedf[, (paste0(v, 'y')) := as.numeric(sub('A_[0-9]*_([0-9]*)', '\\1', get(v)))]
}
```

And let’s also record in which direction the edge points:

```
mazedf[fromx < tox, direction := 'top']
mazedf[fromy < toy, direction := 'right']
```

Now let’s map the `x`

and `y`

coordinates to the 2D matrix:

```
mazedf[, x := nrow(df) - fromx * 4 + 3 - as.numeric(direction == 'top') * 2]
mazedf[, y := fromy * 4 - 1 + as.numeric(direction == 'right') * 2]
```

And then let’s update the blank matrix `NA`

cells with 1, 2 or 3 to represent the actual walls:

```
for (i in seq_len(nrow(mazedf))) {
cell <- mazedf[i]
if (cell$wall == 'ON') {
df[cell$x + -1:0, cell$y + -1:0] <- 1
}
if (cell$direction == 'top' & cell$wall == 'ON') {
df[cell$x - 0:1, cell$y - 1:2] <- 2
}
if (cell$direction == 'right' & cell$wall == 'ON') {
df[cell$x - 2:3, cell$y - 0:1] <- 3
}
}
```

I know it was a bit tricky, and probably there’s a nicer and lot more elegant way to do all this :) But at least this works and results in something like:

## 10.3 Render the maze in Minecraft

Now that we have a binary matrix representation of the maze, it’s very easy to render the related blocks in Minecraft. First, we need to load the `miner`

package and establish a connection to a Minecraft server:

```
library(miner)
mc_connect()
```

Next, we will clean up some space, then generate the floor (diamond) and ceiling (glass), then the wall blocks(gold):

```
## create objects with number of columns and rows in the dataframe
nr <- nrow(df)
nc <- ncol(df)
## clean up some space
setBlocks(1, 50, 1, nr, 54, nc, 0)
## add floor
setBlocks(1, 50, 1, nr, 50, nc, 57)
## add torch
setBlocks(nr - 4, 51, 2, nr, 52, 4, 50)
## maze ceiling
setBlocks(1, 54, 1, nr, 54, nc, 95)
## 3 blocks tall maze walls
for (i in 1:nrow(df)) {
for (j in 1:ncol(df)) {
if (!is.na(df[i, j])) {
setBlock(i, 51, j, 41)
setBlock(i, 52, j, 41)
setBlock(i, 53, j, 41)
}
}
}
```

The result looks like this:

For a more complete solution, see the `mc_maze`

and `mc_mazer`

functions. The prior generates a maze with given dimensions right in front of a specified player id, while the latter does the same but triggered from the chat window by any player.