The universe.rkt teachpack implements and provides the functionality for creating interactive, graphical programs that consist of plain mathematical functions. We refer to such programs as world programs. In addition, world programs can also become a part of a universe, a collection of worlds that can exchange messages.
The purpose of this documentation is to give experienced Racketeers and HtDP teachers a concise overview for using the library. The first part of the documentation focuses on world programs. Section A First Sample World presents an illustration of how to design such programs for a simple domain; it is suited for a novice who knows how to design conditional functions for enumerations, intervals, and unions. The second half of the documentation focuses on "universe" programs: how it is managed via a server, how world programs register with the server, etc. The last two sections show how to design a simple universe of two communicating worlds.
Note: For a quick and educational introduction to just worlds, see Howto Design Programs, Second Edition: Prologue. As of August 2008, we also have a series of projects available as a small booklet on How to Design Worlds.
The universe teachpack assumes working knowledge of the basic imagemanipulation operations, either htdp/image or2htdp/image. As far as this extended reference isconcerned, the major difference between the two image teachpacks isthe assumption thathtdp/image programs render their state as scenes,i.e., images that satisfy the scene? predicate.
The step from simulations to interactive programs is relatively small. Roughly speaking, a simulation designates one function, create-image, as a handler for one kind of event: clock ticks. In addition to clock ticks, world programs can also deal with two other kinds of events: keyboard events and mouse events. A keyboard event is triggered when a computer user presses a key on the keyboard. Similarly, a mouse event is the movement of the mouse, a click on a mouse button, the crossing of a boundary by a mouse movement, etc.
Your program may deal with such events via the designation of handler functions. Specifically, the teachpack provides for the installation of four event handlers: on-tick, on-key, on-mouse, and on-pad. In addition, a world program must specify a render function, which is called every time your program should visualize the current world, and a done predicate, which is used to determine when the world program should shut down.
The big-bang form installs World_0 as the initial WorldState. The handlers tock, react, and click transform one world into another one; each time an event is handled, done is used to check whether the world is final, in which case the program is shut down; and finally, render renders each world as an image, which is then displayed on an external canvas.
For simplicity, we represent key events with strings, but not all strings are key events. The representation of key events comes in distinct classes. First, a single-character string is used to signal that the user has hit a "regular" key, such as
Second, some keys have multiple-character string representations. Strings with more than one character denote arrow keys or other special events, starting with the four most important ones:
Here is a typical key-event handler:(define (change w a-key) (cond [(key=? a-key "left") (world-go w -DELTA)] [(key=? a-key "right") (world-go w +DELTA)] [(= (string-length a-key) 1) w] ; order-free checking [(key=? a-key "up") (world-go w -DELTA)] [(key=? a-key "down") (world-go w +DELTA)] [else w]))The omitted, auxiliary function world-go is supposed to consume a world and a number and produces a world.
When a big-bang expression specifies an on-pad clause,all PadEvents are sent to the on-pad handler. All otherkey events are discarded, unless an on-key and/or anon-release clause are specified, in which case all remainingKeyEvents are sent there.
For "leave" and "enter" events, the coordinates of themouse click may be outside of the (implicit) rectangle. That is, thecoordinates may be negative or larger than the (implicitly) specifiedwidth and height.
The optional resize-expr is applied to the current world and thesizes (width and height) of the display once, when the world is initialized. This givesthe program a chance to draw shapes of a size relative to the display sizein a portable manner.
This section uses a simple example to explain the design of worlds. The first subsection introduces the sample domain, a door that closes automatically. The second subsection is about the design of world programs in general, the remaining subsections implement a simulation of the door.
Simulating any dynamic behavior via a world program demands two different activities. First, we must tease out those portions of our domain that change over time or in reaction to actions, and we must develop a data representation for this information. This is what we call WorldState. Keep in mind that a good data definition makes it easy for readers to map data to information in the real world and vice versa. For all others aspects of the world, we use global constants, including graphical or visual constants that are used in conjunction with the rendering operations.
A typical program does not use all three of these functions. Furthermore, the design of these functions provides only the top-level, initial design goal. It often demands the design of many auxiliary functions. The collection of all these functions is your world program.
The library facilities covered so far are about designing individual programs with interactive graphical user interfaces (simulations, animations, games, etc.). In this section, we introduce capabilities for designing a distributed program, which is really a number of programs that coordinate their actions in some fashion. Each of the individual programs may run on any computer in the world (as in our planet and the spacecrafts that we sent out), as long as it is on the internet and as long as the computer allows the program to send and receive messages (via TCP). We call this arrangement a universe and the program that coordinates it all a universe server or just server.
Recall that event handlers return a HandlerResult, and we have just refined this data definition. Hence, each handler may return either a WorldState or a Package. If an event handler produces a Package, the content of the world field becomes the next world and the message field specifies what the world sends to the universe. This distinction also explains why the data definition for WorldState may not include a Package.
Messages are sent to the universe program, which runs on some computer in the world. The next section is about constructs for creating such a universe server. For now, we just need to know that it exists and that it is the recipient of messages.
Before a world program can send messages, it must register with the server. Registration must specify the internet address of the computer on which the server runs, also known as an IP address or a host. Here a IP address is a string of the right shape, e.g., "192.168.1.1" or "www.google.com".
Finally, the receipt of a message from the server is an event, just like tick events, keyboard events, and mouse events. Dealing with the receipt of a message works exactly like dealing with any other event. DrRacket applies the event handler that the world program specifies; if there is no clause, the message is discarded.
A registered world program may send a message to the universe server at any time by returning a Package from an event handler. The message is transmitted to the server, which may forward it to some other world program as given or in some massaged form. The arrival of a message is just another event that a world program must deal with. Like all other event handlers receive accepts a WorldState and some auxiliary arguments (a message in this case) and produces a WorldState or a Package.
When messages are sent from any of the worlds to the universe or vice versa, there is no need for the sender and receiver to synchronize. Indeed, a sender may dispatch as many messages as needed without regard to whether the receiver has processed them yet. The messages simply wait in queue until the receiving server or world program takes care of them.
A server is the central control program of a universe and deals with receiving and sending of messages between the world programs that participate in the universe. Like a world program, a server is a program that reacts to events, though to different events than worlds. The two primary kinds of events are the appearance of a new world program in the universe and the receipt of a message from a world program.
The teachpack provides a mechanism for designating event handlers for servers that is quite similar to the mechanism for describing world programs. Depending on the designated event handlers, the server takes on distinct roles:
A server keeps track of information about the universe that it manages. One kind of tracked information is obviously the collection of participating world programs, but in general the kind of information that a server tracks and how the information is represented depends on the situation and the programmer, just as with world programs.
The design of a universe server demands that you come up with a datadefinition for all possible server states. For runninguniverses, the teachpack demands that you come up with a datadefinition for (your state of the) server. Any piece of data canrepresent the state. We just assume that you introduce a data definitionfor the possible states and that your event handlers are designedaccording to the design recipe for this data definition.
Evaluating a universe expression starts a server. Visually it opens a console window on which you can see that worlds join, which messages are received from which world, and which messages are sent to which world. Messages that are too long are truncated before they are displayed.
c80f0f1006