Skip to main content Skip to navigation

Lab 3 - Exercises

This week we are going to look in a little more detail at the semantics of DOSTE. What are definitions? How do they work? What does it all mean? The idea is that you experiment with the kinds of definitions you can write. Towards the end we introduce a 3D version of the lift model which you can connect with the work you did last week. Don't forget to keep a record of what you do in a text editor so that you have a complete model to save at the end of the session. If you could keep this record and somehow send it to me (n.w.pope@warwick.ac.uk) it would help with my PhD work, thanks.


DOSTE can be run directly without tkeden. By default this becomes more like a program environment because the input window is removed. It is useful to run DOSTE without tkeden because this is available for your home machines and also runs in Windows. Not only that but you don't always want the input window. In DCS type ~empublic/doste32/bin/doste-dcs in a directory containing a config.dasm file (this automatically runs the doste binary with the correct settings and the -i option).

To start the tool:

~empublic/teaching/cs405/run lab3


Semantics of Definitions

An 'is' definition means that the observable will become the result of that definition in the very next instant. This can be highlighted with the following example. Try it out and see what values you get when you query (or %list).

.a is {0};
.a = 1;

Temporarily 'a' becomes 1 but in the next instant it reverts back to 0 so by the time you type in the query it will already be 0 again. There is an observable '@root red'  which can be set to 0 or 1. Try connecting 'a' to '@root red' which should make the screen go red when 'a' goes to 1. Nothing happens - why is this? Now try connecting  'a' to '@root cout' and check the console output.

By default you can think of observables as having the following definition:

.a is {.a};

If you were to now use '=' to change 'a' it would stay as that value forever or until some other agent changes it. This is what you might do to effectively remove a definition. (Why is this different from making the definition .a is {null};?) It should also be obvious now that if you use the following definition you will end up with a counter that adds 1 every instant (or as fast as the DOSTE machine can):

.a is {.a + 1};

Another fun example is alternating values between two observables. This alternation is only possible because these definitions are 'will be' so they look at the current (present) values of 'a' and 'b' to determine the next. They say nothing about what the values of 'a' and 'b' are right now. Try the next example and,  using '=', change the value of one of them. Each time you query or list them they should have switched (probably).

.a is {.b};
.b is {.a};


Chess Clock

Putting the above styles of definition together allows us to very simply build a model of a chess clock. Below is my script for that clock. Your first objective is to gain a clear understanding of how this chess clock behaves.   It is missing the flag or alarm to indicate the end of the game. There is no associated visualisation so one thing to do would be create this visualisation in the form of two buttons and two digital clock outputs, however, this is an exercise for your own time.

@chessclock = (new);
@chessclock
    A = (new
        time is {
            if (@chessclock reset) {
                @chessclock start_time
            } else if (@chessclock active == A) {
                .time - (@root itime)
            } else {
                .time
            }
        }
        button is { false }    #Change this to true using '='
    )

    B = (new
        time is {
            if (@chessclock reset) {
                @chessclock start_time
            } else if (@chessclock active == B) {
                .time - (@root itime)
            } else {
                .time
            }
        }
        button is { false }    #Change this to true using '='
    )

  active = A
  active is {
    if (.active == A and (.A button)) B
    else if (.active == B and (.B button)) A
    else { .active }
  }

  reset is { false }    #Reset the clock, set to true using '=' before you use the chessclock.
  start_time = (30 * 60)
;


If you are satisfied with how the chess clock works then attempt to construct an alarm clock or digital watch in a similar manner. You are welcome to make a visualisation. Something worth doing is splitting the time up into hours, minutes and seconds instead of a single floating point number. A useful construct for timing and counting is given below where a 'tick' observable becomes true once every second.

.ticktime is { if (.tick) { @root time } else { .ticktime } };
.tick is { if (.time - (.ticktime) > 1.0) true else false };


3D Lift Model

For a bit of fun and because we can we have made a 3D model of a lift and thought it would be good to try combining this with the work you did last week. All the logic behind moving the lift should be the same (except not in pixels any more) and can easily be added to the 3D model. Cloning floors or lifts is still possible but this time we have doors that move as well. A demo is included showing how to move doors. It is also possible to still have 2D components such as buttons on the screen (a bit like a Heads-Up-Display in a game) so that the user (you) can control the lift.

To run the model:

~empublic/teaching/cs405/run lift3d