Randomized Drawing
Summary:
Up to this point, all of the programs we have written are, in some
sense, predictable. That is, the output depends only on the input.
However, we want some programs, such as games and simulations,
to be less predictable. We may also want to have make drawings
using unpredictable procedures, so that we can derive inspiration
from unexpected results. In this reading, we consider Scheme's
tools for supporting such unpredictability, particularly the
random procedure.
Introduction: Simulation
Many computing applications involve the simulation of games or events,
with the hope of gaining insights and identifying underlying principles.
In some cases, simulations can apply definite, well-known formulae.
For example, in studying the effect of a pollution source in a lake or
stream, one can keep track of pollutant concentrations in various places.
Then, since the flow of water and the interactions of pollutants is
reasonably well understood, one can follow the flow of the pollutants
over a period of time, according to known equations.
In other cases, specific outcomes involve some chance. For example, when an
automobile begins a trip and encounters a traffic light, it may be a matter of
chance whether the light is green, yellow, or red. Similar uncertainties
arise when considering genetic mutations or when tabulating outcomes
involving flipping a coin, tossing a die, or dealing cards. In these
cases, one may know about the probability of an event occurring (a head
occurs about half the time), but the outcome of any one event depends on
chance.
In studying events that involve some chance, one approach is to model the
event or game, using a random-number generator as the basis for decisions.
If such a model is simulated many times on a computer, the results may give
some statistical information about what outcomes are likely and how often
each type of outcome might be expected to occur. This approach to problem
solving is called the Monte Carlo Method.
Randomness is also useful in image generation. A number of artists,
from the founders of the Dada movement to Jackson Pollock and beyond,
have reveled in the images that can be created by random or unpredictable
processes. The Dadaists employed random selection to write poetry and
subconscious drawing to create images. Pollock threw paint with an
expectation that interesting patterns would result. (And yes, those
are incredible simplifications of the philosophies and techniques of
these artists.) By combining a random-number generator with some drawing
techniques, we can produce some potentially interesting images.
The random Procedure
A random number generator for a typical computer language is a procedure
that produces an unpredictable value each time it is called. Such
procedures simulate a random selection process. Scheme provides the
procedure random for this purpose. This procedure
returns integer values that depend on its parameter. In particular,
random returns an unpredictable integer value
between 0 and one less than its parameter, inclusive. By
unpredictable
we mean that we are unlikely to be
able to predict the number that random will
return.
> (random 10)
1
> (random 10)
9
> (random 10)
7
> (random 10)
0
> (random 10)
5
> (random 10)
1
> (random 10)
0
Simulating a Die
We can use random to write a program to simulate
the rolling of a die. The simulation generates integers from 1 to
6, to correspond to the faces on the die cube. The details of this
simulation are shown in the following procedure:
We can use that procedure to simulate the roll of multiple dice.
Procedures for Randomized Drawing
We can use a number of simple techniques to generate such randomized
art. What can we randomize? One thing to start with is colors. Given
a list of colors, it is easy to select one of those colors.
It's also possible to be a bit more open in our random selection.
For example, we can choose a random color simply by choosing random red,
green, and blue components.
Similarly, we can choose a random brush. The easiest way to choose
a random brush is to select a random element of the brushes list.
However, that procedure can choose from perhaps too many brushes. We
might create a similar procedure that selects from a particular list
of brushes.
If we wanted to select one of the circle brushes, we might use
> (randomly-select-brush! (list "Circle (01)" "Circle (03)" "Circle (05)"
"Circle (07)" "Circle (09)" "Circle (11)"
"Circle (13)" "Circle (15)" "Circle (17)"
"Circle (19)"))
or
> (randomly-select-brush! (context-list-brushes "Circle"))
although the latter command will also select the fuzzy circle brushes.
In fact, we can rewrite select-random-brush!
using this procedure.
It is, of course, also possible that we'll want to randomly select from
other lists (not just lists of brushes). For example, we might want
randomly select a shade of blue by selecting an element of the list
of all colors with blue
in their names.
Hence, we'll define a generalized procedure for randomly selecting
elements of lists.
We can now select a random shade of blue with the following procedure.
We can also rewrite randomly-select-brush! to use
list-random-element. (The process of identifying common
procedures and then rewriting code to use these common procedures is
called refactoring, and it's a good practice.)
Combining Procedures
Let's step back and remember what we're doing. We're trying to build
a procedure (or set of procedures) that make unpredictable images.
What have we figured out so far? We have a way to randomly select
colors and to randomly select brushes. What next? Now we need ways
to randomly draw things. For lines, circles, and rectangles, we can
simply randomly select all of the parameters (perhaps within certain
limits, such as the width and height of the image). For example,
here is a procedure to draw a line between two randomly selected points.
There are many interesting variants, such as ones that use a fixed
starting point, a fixed line length, and so on and so forth.
Now that we know how to select colors unpredictably, how to select brushes
unpredictably, and how to draw lines unpredictably. We can write a
procedure that puts all of these techniques together.