Bricklayer provides a function, called generateRandomBrickFn, that can be used to generate random bricks. Before describing the details of the generateRandomBrickFn it is important to understand what generating a random brick means (what it should mean).

Slides covering this material can be found here.

## Generating Random Values

In this discussion we will ignore the idiosyncrasies surrounding how computers represent real numbers and issues surrounding equality comparisons.

Virtually all programming languages provide a variety of ways to generate a random (real) number that, mathematically speaking, is in the range 0.0 ≤ n < 1.0. Note that, in this range, n can never equal 1.0, but can equal 0.0. To get a random number, one typically calls a special function. The basic random number function is a nullary function. Its name can vary from language to language, but the function is typically called random or rand.

Let random denote a function that when called generates a random number in the range 0.0 ≤ n < 1.0. Let us assume that random is a nullary function which can therefore be called as follows:

random ()

### Simulating the Flip of a Coin

The following algorithm shows how the random function can be used to simulate a coin flip. In the algorithm below, H stands for “heads” and T stands for “tails”.

1. Let n = random ()
2. if n < 0.5 then print (“H”) else print (“T”)

This algorithm can be easily implemented in SML. An important question is: What kind of output could one expect from a program that flipped a coin, say, 10 times?

• Would you expect 5 heads and 5 tails?
• Would you expect 10 heads and 0 tails?

I conducted an experiment where I flipped an actual coin 10 times and got the following sequence of heads (H) and tails (T).

H T T T T T H H H H

One important thing to note about the sequence is that random does not mean “evenly distributed”. For example, after seeing a sequence of 3 tails, it is incorrect to assume that the next coin flip must yield heads.

What would happen if I ran the experiment again? What would be the chances (i.e., the odds) that same sequence of heads and tails would occur? Now let us consider writing a program that conducts the coin-flipping experiment on our behalf. What would you want to have happen if you ran such a program twice?

• Would you want the program to produce the same output every time it is executed?
• Would you want the program to produce the same output if it is executed on a different computer?
• Would you want the program to produce a (possibly) different output everytime it is executed? In this case, how might this impact your ability to test the program?

### Simulating the Roll of a Die

The following algorithm shows how the random function can be used to simulate the roll of a six-sided die. The basic idea here is to partition the  range 0.0 ≤ n < 1.0 into six equal sections and associate each section with (aka, map each section to) a side of the die.

1. Let n = random ()
2.          if 0.0/6.0 ≤ n < 1.0/6.0 then print (“1”)
3. else if 1.0/6.0 ≤ n < 2.0/6.0 then print (“2”)
4. else if 2.0/6.0 ≤ n < 3.0/6.0 then print (“3”)
5. else if 3.0/6.0 ≤ n < 4.0/6.0 then print (“4”)
6. else if 4.0/6.0 ≤ n < 5.0/6.0 then print (“5”)
7. else if 5.0/6.0 ≤ n < 6.0/6.0 then print (“6”)

This algorithm can also be easily implemented in SML.

I conducted an experiment where I rolled an actual die 10 times and got the following sequence of numbers.

3 5 1 2 1 5 2 2 5 2

Note that the numbers 4 and 6 never appeared. Does this imply that the die is “loaded”? No. If I roll the die five more times, will I be guaranteed that 4 and/or 6 will appear? No. It is important to appreciate that random number sequences have such properties.

## Bricklayer’s Random Brick Function

Bricklayer provides a function, called generateRandomBrickFn, that can be used to generate random bricks. This function implements an algorithm similar to the coin-flipping and die-rolling algorithms described previously.

Let brickList denote a list of bricks. The evaluation of the expression

generateRandomBrickFn brickList

will produce a nullary function value as its result. A val-declaration can be used to bind a variable (i.e., our desired function name) to this nullary function value as follows.

val myName = generateRandomBrickFn brickList;

The evaluation of the function call “myName ()” will return a brick, randomly selected from brickList.

## Predefined Brick Lists

Bricklayer provides a set of predefined brick lists that can be used to generate random brick functions. This set includes the following brick lists.

• grayScale
• greenScale
• blueScale
• purpleScale
• redScale
• warmScale
• brownScale
• clearScale
• allOneBitBricks

Consult the Bricklayer documentation on Pieces for a complete listing of all predefined brick lists as well as the bricks they contain.

## Example 1 – A one dimensional sequence of RED and BLACK bricks.

This first example represents Bricklayer’s version of a sequence of coin flips. A brickList is defined that contains two bricks, a BLACK brick and a RED brick. We can think of one of these bricks as denoting “heads” and the other as denoting “tails”. Using this brickList, a random nullary funtion is declared called randomBrick. When called, the function randomBrick will return a randomly selected brick from the brickList. Specifically, the randomBrick function will randomly select either a BLACK brick or a RED brick and return this brick as its result.

The function sequence0 creates a sequence, running along the x-axis, consisting of 2 bricks randomly selected from brickList. Val-declarations are used to bind the variables brick1 and brick2 to random bricks obtained by evaluating the function call randomBrick ().

A geometric algorithm is used to create longer and longer sequences along the x-axis. The function sequence1 creates an artifact consisting of two sequence0 artifacts placed side-by-side. The remaining sequence functions construct their artifacts in a similar fashion.

```open Level_3;

val brickList = [BLACK,RED];

val randomBrick = generateRandomBrickFn brickList;

fun sequence0 (x,z) =
let
val delta = 1;

val brick1 = randomBrick ();
val brick2 = randomBrick ();
in
put2D (1,1) brick1 (x + 0 * delta, z);
put2D (1,1) brick2 (x + 1 * delta, z)
end;

fun sequence1 (x,z) =
let
val delta = 2*1;
in
sequence0 (x + 0 * delta, z );
sequence0 (x + 1 * delta, z )
end;

fun sequence2 (x,z) =
let
val delta = 2*2*1;
in
sequence1 (x + 0 * delta, z );
sequence1 (x + 1 * delta, z )
end;

fun sequence3 (x,z) =
let
val delta = 2*2*2*1;
in
sequence2 (x + 0 * delta, z );
sequence2 (x + 1 * delta, z )
end;

fun sequence4 (x,z) =
let
val delta = 2*2*2*2*1;
in
sequence3 (x + 0 * delta, z );
sequence3 (x + 1 * delta, z )
end;

build2D (32,32);

sequence4 (0,0);

show2D "random in 1D";
```

## Example 2 – A four-colored two dimensional random brick sequence.

The code in this example creates a chessboard-like artifact in which unit bricks (i.e., bit-bricks) are randomly selected from the brick list

[RED, GREEN, YELLOW, BLUE]

Note that bricks are only created in the body of the function board0. More specifically, the put2D function is used to create four unit bricks in a square configuration. Each brick in this configuration is randomly selected from brickList via the function call randomBrick ().

A standard geometric algorithm is then used to create a 16×16 chessboard-like artifact.

It is worth mentioning that the distribtion of brick colors can be changed by creating a brickList in which desired bricks occur more frequently. For example, the following brick list

[RED, GREEN, YELLOW, BLUE, BLUE]

will randomly select BLUE bricks more frequently than other colored bricks. While this technique offers some control over brick distribution it is not meant to be used as a mechanism to create complex distributions.

```open Level_3;

val brickList = [RED, GREEN, YELLOW, BLUE];

val randomBrick = generateRandomBrickFn brickList;

fun board0 (x,z) =
let
val delta = 1;

val brick1 = randomBrick ();
val brick2 = randomBrick ();
val brick3 = randomBrick ();
val brick4 = randomBrick ();
in
put2D (1,1) brick1 (x        , z        );
put2D (1,1) brick2 (x + delta, z        );
put2D (1,1) brick3 (x + delta, z + delta);
put2D (1,1) brick4 (x        , z + delta)
end;

fun board1 (x,z) =
let
val delta = 2*1;
in
board0 (x        , z        );
board0 (x + delta, z        );
board0 (x + delta, z + delta);
board0 (x        , z + delta)
end;

fun board2 (x,z) =
let
val delta = 2*2*1;
in
board1 (x        , z        );
board1 (x + delta, z        );
board1 (x + delta, z + delta);
board1 (x        , z + delta)
end;

fun board3 (x,z) =
let
val delta = 2*2*2*1;
in
board2 (x        , z        );
board2 (x + delta, z        );
board2 (x + delta, z + delta);
board2 (x        , z + delta)
end;

build2D (32,32);

board3 (0,0);

show2D "random 2D";
``` A 2D artifact created using randomly selected RED, GREEN, BLUE, and YELLOW bricks.