In Triveni, the class Expr captures the abstract notion of behavior. Expr enriches the structure of the encapsulated state in objects in two ways. (Figure 1 summarizes the following discussion.)
Battle is an n-player variation of the 2-player board game Battleship. New players cannot join the game once it has begun. A player loses by manually aborting the game or when all his/her ships are destroyed. Oceans. Each player has a collection of ships on an individual ocean grid. The n ocean grids are disjoint. Each player's screen displays all n oceans, but a player can see only his/her own ships. A player's ships are confined to the player's ocean. Ships. Each ship occupies a rectangular sub-grid of the player's ocean and sinks after each point in its grid area has been hit. There are two kinds of ships:
Moves. A player can move as fast as the user-interface/reflexes allow. Player i can make 4 kinds of moves:
|
The different kinds of state in Expr can interact. This discussion is best carried out in the context of a concrete example.
Consider the class of players in the Battle game. The user interface of the player is a reactive subcomponent of the player. The number of available shields can be modeled as an instance variable, say numshields. The timer that measures the duration of shielding evolves autonomously.
The activation of the shielding (i.e. the initiation of the autonomous state) is caused reactively by inputs from the user interface. This activation affects the variable numshields. The end of the period of shielding, as detected by the autonomously evolving clock object, causes a stimulus (in the form of brightening of this player's ocean) to the reactive subcomponents in other players.
The become method in Expr follows standard object-oriented techniques. It allows an Expr to assume the behavior of another Expr and is useful for refining the inherited behavior in subclasses of Expr.
In the design of Battle that follows, a class called Ship is used to factor out the common behavior of Battleship and Submarine, namely the handling of opponent fire. (See Figure 3.) A Battleship is constructed from a Ship by adding instance variables and behavior to handle movement in terms of direction and speed. A sketch is as follows (detailed design is in Section 3.5):
class Battleship extends Ship { Direction dir; int speed; Battleship(initial_status) { super(initial_status); // initialize receiver Expr e = // construction of new behavior // from inherited behavior become(e); // assume new behavior }}