XML

kent logo

CO631 Anonymous Questions and Answers Keyword Index

This page provides a keyword index to questions and answers. Clicking on a keyword will take you to a page containing all questions and answers for that keyword, grouped by year.

To submit a question, use the anonymous questions page. You may find the keyword index and/or top-level index useful for locating past questions and answers.

Keyword reference for animation

2004

Question 104 (2004):

I have a quick question relating to my 'animation' - could you give any tips/ideas for nice(r) way of making the philosophers move about the screen without hard coding in the locations of every movement?

In my more 'advanced' animation (which has been a challenge to say the least) I have had a lot of hassle using a hard coded method. The code just to move a philosopher to the table (and it's currently not very smooth) is around 300 lines. Ouch.

I am sure there is a better way of doing things but I have racked my brains and I can't think of anything :(. The only other idea was to create a "large" VAL [][5][2]BYTE array that stored all the locations, and for each movement the required value is pulled out the array. That doesn't seem much nicer though; occam doesn't seem to allow you to span this sort of thing over multiple lines either.

Any sort of help would be greatly appreciated, however small!

Answer 104:

If ever you find yourself writing long sequences of repetitive code, where the differences are primarily in number values, you are doing something wrong, ugly and inefficient! So, your 300 lines of code is not a good idea.

Your 'better way' is much better, although it can be improved (see towards the end of this answer). Your VAL [][5][2]BYTE is, presumably, a 2-dimensional array of coordinates (i.e. [2]BYTEs), with the [5] index being for the philosophers and the unsized outermost dimension (i.e. []) being for the number of coordinates (i.e. the length of the path). That might make slightly more sense (and convenience for programming) with the two outer dimensions swapped around -- i.e. VAL [5][][2]BYTE.

occam does allow long lines to be broken across multiple lines ... but maybe I never told you! You can break a long line after commas, operators and the keyword IS. For example, the very long one-line declaration:

  VAL [n.phils][][2]BYTE path IS [[[13, 12], [14, 12], [14, 13], [14, 14], [14, 15]], [[23, 12], [24, 12], [24, 13], [24, 14], [24, 15]], [[33, 22], [34, 22], [34, 23], [34, 24], [34, 25]], [[83, 82], [84, 82], [84, 83], [84, 84], [84, 85]], [[93, 92], [94, 92], [94, 93], [94, 94], [94, 95]]]:

can be much more readibly laid out:

  VAL [n.phils][][2]BYTE path IS
    [[[13, 12], [14, 12], [14, 13], [14, 14], [14, 15]],
     [[23, 12], [24, 12], [24, 13], [24, 14], [24, 15]],
     [[33, 22], [34, 22], [34, 23], [34, 24], [34, 25]],
     [[83, 82], [84, 82], [84, 83], [84, 84], [84, 85]],
     [[93, 92], [94, 92], [94, 93], [94, 94], [94, 95]]]:

The rule about indentation for continuation lines is that any indentation at least as great as the initial line is allowed. So, the following, rather stupid, layout is also possible:

  VAL [n.phils][][2]BYTE path IS
    [[[13, 12], [14, 12], [14, 13], [14, 14], [14, 15]],
           [[23, 12], [24, 12], [24, 13], [24, 14], [24, 15]],
  [[33, 22], [34, 22], [34, 23], [34, 24], [34, 25]],
   [[83, 82], [84, 82], [84, 83], [84, 84], [84, 85]],
         [[93, 92], [94, 92], [94, 93], [94, 94], [94, 95]]]:

but we wouldn't, of course, ever do that! Another use of breaking lines after commas we have seen lots of times -- in PROC headers with long parameter lists:

  PROC thing (CHAN OF INT in0, in1,
	      CHAN OF BYTE keyboard, screen, error,
	      VAL INT id, interval,
	      [][]REAL64 data)

instead of:

  PROC thing (CHAN OF INT in0, in1, CHAN OF BYTE keyboard, screen, error, VAL INT id, interval, [][]REAL64 data)

Breaking lines after operators helps keep large expressions neat -- for example:

    first := (first - second) + ( ((-first) + (third - second)) * (rotational.torque - (ratio/2)) )

could be written:

    first := (first - second) +
	       ( ((-first) + (third - second)) *
		 (rotational.torque - (ratio/2)) )

which might help a little.

Getting back to improving your path description for a wandering philosopher ... rather than declare a table of absolute coordinates for each path position, consider a table of relative movements. For example:

  VAL [n.phils][][2]BYTE path IS
    [[[left, 3], [up, 5], [right, 2], [up, 4], [left, 1], [down, 2]],
     [[down, 8], [up, 3], [left, 6], [down, 1], [left, 6], [down, 3]],
     [[right, 3], [down, 2], [right, 8], [down, 9], [right, 1], [down, 5]],
     [[up, 5], [left, 5], [down, 2], [up, 2], [down, 1], [up, 3]],
     [[up, 9], [right, 9], [up, 2], [left, 2], [up, 3], [left, 6]]]:

where your movement code interprets [left, 3] as "move left 3 places" etc. Predeclared, of course, would need to be something like:

  VAL BYTE left IS 0:
  VAL BYTE right IS 1:
  VAL BYTE up IS 2:
  VAL BYTE down IS 3:

Elsewhere would be needed a table of absolute start coordinates for each path movement.

That just leaves the problem that all the above path lengths have to be the same length? With the modern occam-pi language, that's not a problem ... we can use dynamically sized mobile arrays. For classical occam, you could pad out short paths with some dummy movement elements - e.g. STAY where:

  VAL BYTE stay IS 255:

  VAL [2]BYTE STAY IS [stay, 0]:

  VAL [n.phils][][2]BYTE path IS
    [[[left, 3], [up, 5], [right, 2], [up, 4], STAY, STAY],
     [[down, 8], [up, 3], [left, 6], [down, 1], [left, 6], STAY],
     [[right, 3], [down, 2], [right, 8], [down, 9], [right, 1], [down, 5]],
     [[up, 5], [left, 5], STAY, STAY, STAY, STAY],
     [[up, 9], [right, 9], [up, 2], [left, 2], [up, 3], STAY]]:

Keywords: q7 , animation , long-lines

2003

Question 113 (2003):

Hi,

Until recently I had my dining philosophers program running fine with scrolling text output, now I have added the table style animation it runs very slowly and sometimes there is a visible pause as it outputs a word. Are there any obvious things that could be causing this?

I an doing the animations like this:

    SEQ
      clear.states (4 + (4 * n), out)
      cursor.x.y (32, BYTE (4 + (4 * n)), out)
      out.string ("Sitting", 0, out) 
      flush (out)

Thank you.

Answer 113:

Nothing looks wrong with the code you posted. If you're running it over a network (e.g. on raptor logged in from home), that could be the reason. It might also be raptor being slow (with everyone else doing their dining philosophers on it).

Keywords: q7 , animation


Question 109 (2003):

I lost my notes from the seminar where we did arranging stuff on the screen, could you tell me the commands for relocating the cursor, blanking the screen and changing text colour.

Answer 109:

The other answers under the animation keyword should be useful. In summary, though:

    PROC cursor.x.y (VAL BYTE x, y, CHAN BYTE out!)
    PROC erase.screen (CHAN BYTE out!)

... and many others. Changing the text colour isn't entirely trivial -- there are no pre-defined PROCs to do it for you. However, here's a simple example that prints some text in bold red (before restoring the default colour/attributes):

    SEQ
      out.string ("*#1B[1;31m", 0, screen!)
      out.string ("Hello, bold red world!", 0, screen!)
      out.string ("*#1B[0m", 0, screen!)
      screen ! FLUSH

The various ANSI/VT100 escape codes and suchlike can be found via google. A basic, but useful, reference can be found here.

Keywords: animation

Referrers: Question 113 (2004) , Question 113 (2004)


Question 92 (2003):

Are there any example source files of animation; I attended the seminar, but am having problems with even starting to animate.

Answer 92:

There were four seminars you should have attended ...

You could look at `test_utils.occ' in:

    /usr/local/courses/co516/examples

on Raptor. Or `examples/sort_pump.occ', but that uses `goto.x.y', which is now deprecated, rather than `cursor.x.y' (the two are essentially similar, however).

Essentially, text-animation is a repeating process of: move cursor, then output something. This can be seen most obviously in the `a7' model answer.

Source code for other animations can be found on Fred's occam page. These range from trivial to rather complex.

Keywords: animation , q7


Question 88 (2003):

I have some mystery regarding Q7 I'd like to clear up. As I understand it the college must communicate its status to the display process via a number of channels. I think the only thing the display process needs to know is the status of each philosopher; the status of security and the forks can be deduced if we know what the philosophers are doing.

As it stands the college is self contained and there is no obvious way to report, at any given time, its status to another process. One solution I can see is to replicate all communications between the processes in college, and route them to the display process. The display process would maintain its own picture of the college, which it updates according to the inputs on its channels. This seems rather complicated.

Alternately the display process could again recieve a copy of all internal college communications, but conforming to a protocol such that it can update its picture of the college without other information about its status. For example, when a philosopher wishes to sit down, instead of outputting a boolean he outputs a specific message the display process knows to mean "waiting to sit down" and can update its picture accordingly. This is assuming that the animation is not drawn frame at a time, but continuously updated as information comes in.

In these cases what does display need to communicate with in order to get a complete picture ? Security can tell it who is wanting to sit down and stand up, but it also needs to know the fork status. Presumably this will be the job of either forks or philosopher.

I have trawled the anonymous questions of old, none of the answers to which have baffled me, but I still cannot get this fundamental.

Answer 88:

All the questions you have asked have been discussed in your seminar groups for the last 4 weeks. These Q&A pages are in no way a substitute for attending those seminars. Your question suggests ideas that are either illegal (with respect to occam semantics) or far too complex. Simple solutions have been presented in the seminars.

Having said this, I will attempt to answer your questions. However, those who know how to do this problem should skip these answers, as correcting the confusion in your questions may confuse others unnecessarily.

In response to your first paragraph, yes, the state of the forks can be deduced from the philosopher, but it's easier to have the forks report their state. It also makes more sense; the state of a fork should be reported by the fork, not by something else.

You are sort of correct in your second paragraph, although I'm not sure what you mean by `replicate all communications'. Thankfully, setting up this extra `wiring' is not complicated in occam. However, the `display' process does not need to maintain the `state' of the college (see the next paragraph). The extra wiring can be handled using an array of channels; the `display' process gets the inputting ends as a `bundle' (array), whilst the outputting ends are distributed amongst the other processes. This will require some modifications to the `secure.college' process.

The third paragraph is essentially what we're expecting you to do for this assignment. The `philosopher', `fork' and `security' processes report their actions to the display as they happen. The display process just inputs these messages and draws on the screen accordingly. The animation should indeed be updated on-the-fly; it should not be done frame-by-frame. The only disadvantage is that the display cannot be completely redrawn (i.e. if it got corrupted, somehow). This isn't a problem for this assignment, however.

The various messages are best handled using a tagged protocol. The previous assignment, q6.occ, used a tagged protocol. The various `messages' have been discussed in the seminar groups. The q7.occ file gives some indication of what is required:

    Your task is to animate this demonstration.  Links will need to
    be made from the college to its external environment, through
    which the philsophers (and, maybe, the forks and the security guard)
    report their state.  These links are gathered by a fair-ALTing server
    that drives a screen display in response to incoming information
    from the college.  Thinking and eating by the philosphers should
    be modelled by random (but finite!) delays.  The animated display
    should reflect the round table in the dining room ...

Running the example solutions (on raptor, see Question 80 (2003)) should give you an indication of what is required -- i.e. what is being displayed (and therefore reported) there ? (`a7' is the example minimum-but-full-marks solution; the other example solutions are more animated).

Reporting by each process should be restricted to its own `state'. I.e., the security process should not report that philosophers are trying to stand up or sit down. This is actually very hard.. The only state the security process maintains is how many philosophers are actually sat down -- it should report this. When a philosopher stands up or sits down, that should be reported by the philosopher -- not anything else. It is both more logical and simpler to have things this way, since it keeps the logic of each process `intact'. E.g. I might take your philosopher, fork, security and display processes, completely re-wire the nextwork (within reason), and still expect it to work. Having the correct functioning of processes depend on their external wiring is not really a good idea.. (such processes must conform to the protocol that they conceputally agreed on, however).

I hope this clears things up a bit. If you still have queries, or want some points explained in more detail, I'd suggest emailing or visiting your seminar-leader or other member of the course team (we all have a desk somewhere on campus).

Keywords: q7 , animation

2002

Question 31 (2002):

I would like to use colour in my solution to Q7. The PROC fg.col in shared_screen.occ looks useful ... however, I am unable to use the shared_screen.occ code. I have the following lines at the top of my source code:

  #INCLUDE "shared_screen.occ"
  #USE "shared_screen.inc"

Many errors are generated relating to this, such as:

  Error-oc-shared_screen.occ(337)- pc subscripted too many times
  Serious-oc- Too many errors, maximum is 100.

What am I doing wrong?

Answer 31:

Sorry - we hadn't told you how to use this package. It's not part of the basic "course" library! Before explaining how to access, let me stress that noone needs to find out about and use this stuff - it's only there to provide a rich set of drawing mechanisms for those who want to do some really fancy animation. Even then, you don't have to use it ... but you will end up inventing something similar.

Something anyone could have done is simply copy those two files:

  libsrc/shared_screen.inc
  libsrc/shared_screen.occ

into the start of your own q7.occ file. Then, your own code could simply use anything defined in them. Note that the order is important - the shared_screen.inc must go before the shared_screen.occ file (which uses protocols and data types defined in shared_screen.inc).

Better would be to copy those files into the same directory as your q7.occ file and start your file with:

  #INCLUDE "shared_screen.inc"
  #INCLUDE "shared_screen.occ"

Again, note the ordering! These directives simply tell the compiler to pull in those files at the point of those #INCLUDEs.

Best is not to copy those files at all and use the library. All you haven't been told is the name of the library - which is "ss". Currently, only PROCs and FUNCTIONS are saveable in kroc libraries, which means that constants, data types, prototcols (etc.) have to be pulled in as #INCLUDEs. Anyway, to do this, your file needs to start with:

  #INCLUDE "ss.inc"
  #USE "ss.lib"

These can be followed, or preceeded, by other library accesses - e.g.

  #INCLUDE "consts.inc"       -- standard course library constants
  #USE "course.lib"           -- standard course library

We're not quite done. When compiling, the occam compiler (invoked by the kroc shell script) will find the relevant files. [Note: those working with the Linux kroc need to ensure their OCSEARCH environment variable is set up correctly.] When doing final linking (also invoked by the kroc shell script), we have to tell the linker where to find the library code. In fact, the kroc script uses the standard gcc (Gnu C Compiler) to do this linking - i.e. something different from OCSEARCH happens. Anyway, the compile command needed is:

  kroc q7.occ -lss

Linux users have always had to do something like this to link in the course library (which the kroc script on Solaris machines has been set up to do automatically). So, on Linux, if you want both libraries linked in to your executable, the command is:

  kroc q7.occ -lss -lcourse

Enjoy!

Keywords: q7 , colour , animation

2000

Question 91 (2000):

A friend told me that I should be using:

    out ! FLUSH

after every single output. My program works perfectly well without them. Do I need to include them for safety?

Answer 91:

Not for safety reasons. Unix flushes characters written to its standard output whenever the associated memory buffer gets full or when it gets a new line character. In addition, KRoC forces Unix to flush its buffer when the FLUSH character is sent.

You should flush your animation output after each completed update of the screen (but not, of course, after each character). If you did not and action was progressing slowly in your animation, you would not see anything until the Unix buffer became full when, suddenly, you would see everything that had happened since the last time the buffer was flushed. This is because individual animation updates would not usually include a new line character. If your animation is very active, you will be continually filling the Unix buffer and, so, would see things happening all the time.

However, if your animation is very active but includes a user freeze command and you haven't sent a FLUSH, the animation would freeze but you would not see the latest updates. Of course, you could respond to a freeze by sending a FLUSH ...

But if there are other ways of interacting with the animation (see a7-1997 and a7-1998 in the answers directory on raptor), you will need those FLUSHes. Otherwise you may run into latency problems: what you see on the screen might be the state of the animation a while back - the latest updates are buffered up somewhere and have not been sent to your screen yet!

Keywords: flush , animation

Referrers: Question 51 (2004) , Question 114 (2003)


Question 90 (2000):

Just a small point - I have tried to remove the cursor from the screen using cursor.invisible (out). However, this would apear to do nothing and my dislplay still has a big black cursor jumping all over the place?

Answer 90:

I'm afraid we are at the mercy of the completeness of the VT100 terminal emulation provided by the system we are using to get a text window. Most do not implement this make cursor invisible function and there's nothing we can do about it (apart from hacking the source code of the terminal emulator if we can get hold of it). In the good old days, we used to have real VT220 (which superceded VT100) terminals and this cursor.invisible procedure worked just fine!

Keywords: animation , cursor.invisible


Question 68 (2000):

I've forgotten how to implement the lookup table for the screen positions for the dining philosophers. Any help would be appreciated.

Answer 68:

Your animation code should not be highly repetitive with the same logic repeated with different magic numbers - e.g. for displaying new positions of the different philosophers. Having a table of anchor coordinates for each philosopher may help. A table is simply an array of VALues (i.e. constants). For example:

  VAL [][2]BYTE phil.anchor IS [[40, 5], [70, 10], [55, 15],
                                [35, 15], [10, 10]]:

where the [][2]BYTE could have just been [][]BYTE, but being specific about the dimension of the coordinates (rather than the number of them) seems right. We could have been even more explicit and written [5][2]BYTE, but that seems too much. Any way, the compiler will fill in the sizes of any blanks in what we write after the IS.

With the above, it's nice to give names to the two indices of the [2]BYTE array coordinates - e.g.

  VAL INT X IS 0:
  VAL INT Y IS 1:

Then, if we want to move the screen cursor to the anchor point for philosopher i - and we know that that i is a valid philosopher number (i.e. 0 through 4):

    cursor.x.y (phil.anchor[i][X], phil.anchor[i][Y], screen)

or, more efficiently:

    VAL [2]BYTE phil.i IS phil.anchor[i]:
    cursor.x.y (phil.i[X], phil.i[Y], screen)

since it only checks the array index (for out-of-bounds error) and calculates the address of phil.anchor[i] once.

Keywords: q7 , cursor , table , animation

Referrers: Question 84 (2003) , Question 29 (2002)

Valid CSS!

Valid XHTML 1.0!

Last modified Mon May 15 17:39:44 2006
This document is maintained by Fred Barnes, to whom any comments and corrections should be addressed.