Commits

Anonymous committed 1bb032f

Initial import of RUBE version 1.02 revision 1997.0715.

  • Participants
  • Tags rel_1_02_1997_0715

Comments (0)

Files changed (8)

File doc/rube.html

+<html><head>
+    <meta http-equiv="Content-Type" content="text/html;CHARSET=iso-8859-1">
+    <meta name="Description" content="Cat's Eye Technologies: The RUBE Language">
+    <title>Cat's Eye Technologies: The RUBE Language</title>
+</head>
+<body>
+<center>
+<A HREF="/esoteric/index.html">Esoteric Topics in Computer Programming</A> presents...
+<br><table border=0><tr>
+    <td nowrap align=center valign=center
+    bgcolor="#000000" background="/img/sineblack.gif">&nbsp;<a href="http://www.catseye.mb.ca/index.html"><img
+    align=absmiddle src="/img/3qtrsize.gif"
+    alt="Cat's Eye Technologies" border=0></a>&nbsp;</td>
+    <td nowrap align=center><font size=+3
+    face="century gothic,arial,times new roman" color="#800000">&nbsp;&nbsp;</font><FONT face="arial,monaco" color=#00007f SIZE=+4><B>R</B></FONT>
+<FONT face="arial,monaco" color=#007f00 SIZE=+4><B>U</B></FONT>
+<FONT face="arial,monaco" color=#007f7f SIZE=+4><B>B</B></FONT>
+<FONT face="arial,monaco" color=#7f0000 SIZE=+4><B>E</B></FONT><font></td>
+    </tr></table>
+
+<TABLE WIDTH="100%"><TR><TD WIDTH="50%" ALIGN=LEFT VALIGN=TOP>
+
+<p><font face="arial,monaco" size=+2><b>Language</b></font>
+
+<P>RUBE is a tribute to Rube Goldberg, creator of all those unique
+cartoon contrivances, showed the world that anything
+can be done in a more complicated fashion than necessary.
+
+<p>The language itself is a cellular "bully" automaton: certain state
+transitions force other, non-adjacent cells to assume certain state
+transitions.  Although this may sound like an interesting notion, the
+number of interactions climbs quickly as more objects are added, and
+things get much messier than they normally would in a regular
+cellular automaton, like John Conway's Game of Life.
+
+<p>Also unlike a real cellular automaton, RUBE supports rudimentary
+output functionality; input was planned, but has never been implemented.
+
+<p><a HREF="/esoteric/alpaca/redgreen/index.html">REDGREEN</A> is an
+updated version of the RUBE universe, one which is expressible as
+a proper cellular automaton.
+
+<p><img src="/img/new.gif" alt="[NEW]" width=26 height=16 border=0> John Colagioia has created a more consistent version of
+the RUBE language, <a href="klik.txt">RUBE II:  Das Klickenklacker</a>.
+
+</TD><TD WIDTH="50%" ALIGN=RIGHT VALIGN=BOTTOM>
+
+<p><font face="arial,monaco" size=+2><b>Implementation</b></font>
+
+<p>You can download the <a href="/esoteric/rube/rubev102.zip"><img src="/img/fileicon.gif" border=0 ALT="[D/L]" width=12 height=12>RUBE</a> distribution from
+this web server.
+It contains C source code, documentation, and a precompiled binary for MS-DOS.
+
+<p>You can also download John's <a href="/esoteric/rube/rube_ii.zip"><img src="/img/fileicon.gif" border=0 ALT="[D/L]" width=12 height=12>RUBE II</a>
+ distribution from this web server.
+Strangely enough it <i>also</i> contains C source code, documentation, and a precompiled binary for MS-DOS.
+
+<p><font face="arial,monaco" size=+2><b>Documentation</b></font>
+
+<p>See <a href="/esoteric/rube/rube.txt">rube.txt</a> for the original
+description of the interpreter, <a href="/esoteric/rube/klik.txt">klik.txt</a>
+for RUBE II.
+
+<p><font face="arial,monaco" size=+2><b>Programs</b></font>
+
+<p>Attempting to write anything even approaching a single
+"Turing-power" in this language is an utter nightmare.  Partly this
+is because the playfield in the available implementation is
+restricted to 80 columns by 25 rows.  But mostly it's just because
+programming anything non-trivial in RUBE is a clumsy job of
+co-oridnating concurrently operating sections of the playfield.
+
+</TD></TR></TABLE>
+
+</body></html>

File doc/rube.txt

+RUBE
+====
+EXPERIMENTAL VERSION - IN DEVELOPMENT       June 15 1997
+
+implementation and grammar (c)1997, 2000 Cat's Eye Technologies.
+
+RUBE is a twisted programming language named after Rube Goldberg,
+creator of those convoluted cartoon machines.  It has some similarities
+to said machines.  Read on.
+
+Like Befunge, this is a 2-dimensional language where each instruction
+is an ASCII character meant to be seen in debugging mode to be
+appreciated.  Coincidentally (because I ripped off the Befunge-93
+routines) it's currently restricted to an 80x25 source file.
+
+There is no Program Counter as such - well there is, but it moves
+like a scan line on a TV or monitor: every command in the program
+is executed once every tick during a "sweep" of the program.  The
+program changes on every tick.  You could say RUBE is just a 30+
+state automaton with input and output functions, and you might be
+right.
+
+Anyone who's played The Incredible Machine (and to some extent,
+Donkey Kong) will understand RUBE almost immediately.  Instructions
+in the source file interact to execute the algorithm required.  A
+"warehouse" paradigm is used (this is what happens to your brain
+when you work at a lumberyard...)
+
+Integral are the crates, 0 to f.  These represent data.  They also
+represent movable boxes which are subject to gravity, being pushed
+around, and conveyor belts, among other things.
+
+Girders = are stationary parts of the program on which crates can
+be piled.  When there's no girder directly below a crate, that crate
+falls.
+
+Dozers ( and ) push crates around.  Dozers are subject to gravity,
+and must travel on girders.  Dozers turn around when there is a , in
+front and above them.  As an interesting side effect they also
+replicate themselves at ,'s.
+
+Ramps / and \ are used for dozers to move from girder to girder.
+
+Conveyor belts > and < carry crates along with no help needed from
+dozers.  Note that conveyor belots do not affect dozer motion.
+
+Winches up W and down M move crates from girder to girder.
+
+"Swinches" move crates up V or down A and then switch states.
+
+Gates K compare crates to a reference crate and move the crate
+depending on if it's less than, or more than/equal to the
+reference crate.
+
+     t   | t = target crate     l = lesser crates
+     K   | r = reference crate  g = greater than or equal to
+    lrg  |
+
+Packers + and Unpackers - perform 4-bit math on crates:
+
+     +      +     -      -
+    12  ->   3   ef  ->   1
+    ===    ===   ===    ===
+
+Furnaces F destroy everything one space left, right, below, and
+above them.
+
+Replicators : make a copy below them of whatever is above them,
+usually a crate or a dozer.  Special replicators ; only make
+copies of crates.  Upside-down special replicators . work like ;
+but make a copy above them of what's below them.
+
+Dozers turn around when they hit certain instructions.
+Crumble walls * disappear after being hit horizontally by a dozer.
+
+Program output provides a print mechanism.  If there is a c crate
+below the O, the ASCII value specified by the two crates above the O
+(if they exist) is output as an ASCII character.  If there is a b
+crate below the O they are output as a byte value.
+
+The following outputs a space:
+
+        2
+        0
+        O
+        c
+        =
+
+Symbol  Name                    Bump R  Bump L  Surface Gravity
+
+Implemented:
+        space                   pass    pass    no      no
+0..f    crate                   move r  move l  yes     yes
+(       dozer right             move r  move l  yes     yes
+)       dozer left              move r  move l  yes     yes
+=       girder                  rev     rev     yes     no
+F       furnace                 die     die     die     no
+\       ramp                    +1 elev +1 elev yes     no
+/       ramp                    +1 elev +1 elev yes     no
+>       conveyor belt right     rev     rev     yes     no
+<       conveyor belt left      rev     rev     yes     no
+:       replicator              rev     rev     yes     no
+;       special replicator      rev     rev     yes     no
+.       upside down replicator  rev     rev     yes     no
+,       turn signal                             no      no
+*       crumble-wall            break   break   yes     no
+O       output                  rev     rev     yes     no
+        b       byte<-crate crate
+        c       char<-crate crate
+K       gate                    rev     rev     yes     no
+W       winch up                rev     rev     yes     no
+M       winch down              rev     rev     yes     no
+V       swinch up               rev     rev     yes     no
+A       swinch down             rev     rev     yes     no
++       packer                  rev     rev     yes     no
+-       unpacker                rev     rev     yes     no
+C       crate killer            die cr  die cr  die cr  no
+D       dozer killer            die doz die doz die doz no
+
+
+Planned:
+I       input                   input   input   yes     no
+        b       byte->crate crate
+        c       char->crate crate
+T       scale                   rev     rev     yes     no
+|       door                    rev     rev     yes     no
+
+
+Kinda Silly (extraneous to real programming):
+km      monkey                  rev     rev     yes     yes
+wl      weasel                  rev     rev     yes     yes
+H       mulberry bush           rev     rev     yes     yes
+
+Q       supergoo                rev     rev     yes     kinda
+
+~       water                   wet     wet     wet     kinda
+u       pontoon                 rev     rev     yes     yes (floats)
+sz      electric eel            die     die     die     yes
+
+Sadly, the ubiquitous "Hello, world!" in RUBE is a very unfriendly
+
+
+4666622767662
+85ccfc07f2c41
+OOOOOOOOOOOOO
+ccccccccccccc
+=============
+
+
+Or an equally ugly
+
+
+(21646c726f77202c6f6c6c6548
+===========================
+
+                           O F
+                           c
+                           =
+

File eg/bottles.rub

+                   <<<<<<<<<W
+                               =
+                            ;-W
+                    <<W
+                      C    A>.>>
+,                l     ,W>=  1  F
+         (        36         =
+ =================;;===   <<<
+F             ,       ,  F
+               (
+               =======
+                      F
+              O
+            F b      73656c74746f62
+              =   ,  ;;;;;;;;;;;;;;            ,
+                   (
+                   ============================
+
+                  F                            O F
+                                               c
+                                               =
+
+abcdef                                  0123456789
+
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>K<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+                                     8
+                      +         <<<<<=>>>>>        -
+
+                 <<<<<=<<<<<<<<<           >>>>>>>>=>>>>
+
+                O                                       O
+                c                                       c
+                =                                       =
+               F F                                     F F

File eg/hello.rub

+  0a21646c726f77202c6f6c6c6548
+, :::::::::::::::::::::::::::: ,
+ )
+ ==============================
+F
+                               O F
+                               c
+                               =

File eg/special.rub

+
+
+=(  71f543
+==========;;==;;==;=;=;=;;==;;===;;;;;==;;=;;;=====;;========
+                                                             F
+
+
+
+>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+
+
+                  O
+                  b
+                  =
+

File eg/waterw.rub

+       ~
+
+
+    =     =
+    =======
+
+                 =~
+                 ===
+
+
+
+=                              =
+=                              =
+=                              =
+================================
+/*
+
+   rube.c - RUBE language
+   Interpreter/Debugger Implementation
+     v1.02, Jul 1997, Chris Pressey
+
+   (c)1997, 2000 Cat's Eye Technologies.
+   http://www.catseye.mb.ca/
+
+   Usage :
+
+   rube [-d] [-q] [-r input-file] [-w output-file]
+	[-y delay] [-f frame-skip] [-o offset] <rube-source>
+
+      -d: disable debugging output
+      -q: produce no output but program output
+      -r: redirect input from a specified file instead of stdin
+      -w: redirect output to a specified file instead of stdout
+      -y: specify debugging delay in milliseconds (default 0)
+      -f: specify debugging frame skip in frames (default 1)
+
+   Compilation :
+
+   MS-DOS: used Borland C++ v3.1 to compile RUBE.EXE
+
+   Notes for the DOS version:
+     Load ANSI.SYS or compatible ANSI driver before using.
+
+   v1.00: May/Jun 97 original, minimal implementation
+   v1.01: Jun 97 added K gate, AV swinches, + packer, - unpacker
+   v1.02: Jul 97 fixed bug in WM winches, - unpacker, added . and C
+	  doubled height of playfield and improved debugger.
+	  added Ben Olmstead's cursor-turner-offer-thingy.
+	  added -q option.
+
+ */
+
+/********************************************************* #INCLUDE'S */
+
+#define CURSORON
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <time.h>
+#if __BORLANDC__
+  #include <dos.h>
+#endif
+
+/********************************************************** #DEFINE'S */
+
+#define LINEWIDTH    80
+#define PAGEHEIGHT   50
+
+#define SCREENWIDTH  79
+#define SCREENHEIGHT 22
+
+#define cur          pg[y * LINEWIDTH + x].c
+#define curv         pg[y * LINEWIDTH + x].v
+#define curd(dx,dy)  pg[(y+dy) * LINEWIDTH + (x+dx)].c
+#define nex          pg2[y * LINEWIDTH + x].c
+#define nexv         pg2[y * LINEWIDTH + x].v
+#define nexd(dx,dy)  pg2[(y+dy) * LINEWIDTH + (x+dx)].c
+
+#define shrink(s) s[strlen(s)-1]=0
+
+typedef struct cellstruct
+{
+  char c;
+  signed long int v;
+} cell;
+
+/*************************************************** GLOBAL VARIABLES */
+
+cell pg[LINEWIDTH * PAGEHEIGHT]; /* playfield */
+cell pg2[LINEWIDTH * PAGEHEIGHT];/* playfield' */
+
+cell *head = NULL;
+
+int x = 0, y = 0;                /* x and y looping */
+int dx = 1, dy = 0;              /* direction of looping */
+int debug = 1;                   /* flag : display ANSI debugging? */
+int infile = 0, ia;              /* flag : use input file, and assoc arg? */
+int outfile = 0, oa;             /* flag : use output file, and assoc arg? */
+int deldur = 0;                  /* debugging delay in milliseconds */
+int debskip = 1;		 /* frame skip in debug view */
+int debopos = 1;       		 /* output column in debugger */
+int frame = 1;
+int quiet = 0;
+
+/********************************************************* PROTOTYPES */
+
+int isramp(char c);
+int isblock(char c);
+int issupport(char c);
+int iscrate(char c);
+int ctoh(char c);
+char htoc(int i);
+
+/******************************************************* MAIN PROGRAM */
+
+void main (argc, argv)
+     int argc;
+     char **argv;
+{
+  FILE *f;
+  FILE *fi;
+  FILE *fo;
+  FILE *fs;
+  int i;
+  int done=0;
+  int maxy=0; int maxx=0;
+  short signed oldcursor;
+
+#ifdef CURSOROFF
+__asm
+{
+  mov al,0x03
+  mov bl,0x00
+  int 0x10
+  mov oldcursor,cx
+  mov al,0x01
+  mov cx,0x0001
+  int 0x10
+}
+#endif
+
+  srand (time (0));
+
+  if (argc < 2)
+  {
+    printf ("USAGE: rube [-d] [-q] [-r input] [-w output] [-y delay] [-f skip] foo.rub\n");
+    exit (0);
+  }
+  for (i = 1; i < argc; i++)
+  {
+    if (!stricmp(argv[i], "-d")) { debug = 0; }
+    if (!stricmp(argv[i], "-q")) { quiet = 1; debug = 0; }
+    if (!stricmp(argv[i], "-r")) { infile = 1; ia = i + 1; }
+    if (!stricmp(argv[i], "-w")) { outfile = 1; oa = i + 1; }
+    if (!stricmp(argv[i], "-y")) { deldur = atoi(argv[i + 1]); }
+    if (!stricmp(argv[i], "-f")) { debskip = atoi(argv[i + 1]); }
+  }
+  if (!quiet) printf ("Cat's Eye Technologies RUBE Interpreter v1.02\n");
+  if ((f = fopen (argv[argc - 1], "r")) != NULL)             /*** Input Phase */
+  {
+    int x = 0, y = 0;
+    while (!feof (f))
+    {
+      cur = fgetc (f);
+      if (cur == '\n')
+      {
+	cur = ' ';
+	x = 0;
+	y++;
+	if (y >= PAGEHEIGHT) break;
+      } else
+      {
+	x++;
+	if (x > maxx) maxx = x;
+	if (x >= LINEWIDTH)
+	{
+	  x = 0;
+	  y++;
+	  if (y >= PAGEHEIGHT) break;
+	}
+      }
+    }
+    fclose (f);
+    maxy = y;
+  } else
+  {
+    printf ("Error : couldn't open '%s' for input.\n", argv[argc - 1]);
+    exit (0);
+  }
+
+  if (infile)
+  {
+    if (!(fi = fopen (argv[ia], "r")))
+    {
+      printf ("Error : couldn't open '%s' for input.\n", argv[ia]);
+      exit (0);
+    }
+  }
+
+  if (outfile)
+  {
+    if (!(fo = fopen (argv[oa], "w")))
+    {
+      printf ("Error : couldn't open '%s' for output.\n", argv[oa]);
+      exit (0);
+    }
+  }
+
+#if __BORLANDC__
+  setcbrk(1);
+#endif
+
+  while (!done)          /*** Intepreting Phase */
+  {
+    if ((debug) && (!(frame++ % debskip) || (!frame)))
+    {
+      printf ("%c[1;1H", 27);
+      for(y = 0; (y <= maxy) && (y <= SCREENHEIGHT); y++)
+      {
+	for(x = 0; (x <= maxx) && (x <= SCREENWIDTH); x++)
+	{
+	  putc(isprint(cur) ? cur : ' ', stdout);
+	}
+	printf("\n");
+      }
+    } else
+    {
+      // putc('.', stdout);
+    }
+    fflush (stdout);
+    fflush (stdin);
+    for (x=0; x<=(maxx); x++)
+    {
+      for (y=0; y<=(maxy); y++)
+      {
+	switch (cur)
+	{
+	  case 0: case 1: case 2: case 3: case 4:
+	  case 5: case 6: case 7: case 8: case 9:
+	  case 10: case 11: case 12: case 13: case 14:
+	  case 15: case 16: case 17: case 18: case 19:
+	  case 20: case 21: case 22: case 23: case 24:
+	  case 25: case 26: case 27: case 28: case 29:
+	  case 30: case 31: case 32:
+	    if (iscrate(curd(0,-1))) nex = curd(0,-1);    // falling in from above
+	    if (curd(0,-1) == '(') nex = '(';
+	    if (curd(0,-1) == ')') nex = ')';
+
+	    if (curd(1,1) == 'W') nex = curd(2,2);
+	    if (curd(-1,1) == 'W') nex = curd(-2,2);
+
+	    if ((curd(1,1) == 'V') && iscrate(curd(2,1))) nex = curd(2,1);
+	    if ((curd(-1,1) == 'V') && iscrate(curd(-2,1))) nex = curd(-2,1);
+
+	    if (curd(1,-1) == 'M') nex = curd(2,-2);
+	    if (curd(-1,-1) == 'M') nex = curd(-2,-2);
+
+	    if ((curd(1,-1) == 'A') && iscrate(curd(2,-1))) nex = curd(2,-1);
+	    if ((curd(-1,-1) == 'A') && iscrate(curd(-2,-1))) nex = curd(-2,-1);
+
+	    if (curd(0,-1) == '~') nex = '~';
+	    if ((curd(-1,0) == '~') && (issupport(curd(-1,1)))) nex = '~';
+	    if ((curd(1,0) == '~') && (issupport(curd(1,1)))) nex = '~';
+
+	    if (curd(1,-1) == '+')
+	    {
+	      if (iscrate(curd(1,0)) && iscrate(curd(2,0)))
+	      {
+		nex = htoc((ctoh(curd(1,0))+ctoh(curd(2,0))) % 16);
+	      }
+	    }
+
+	    if (curd(-1,-1) == '+')
+	    {
+	      if (iscrate(curd(-1,0)) && iscrate(curd(-2,0)))
+	      {
+		nex = htoc((ctoh(curd(-1,0))+ctoh(curd(-2,0))) % 16);
+	      }
+	    }
+
+	    if (curd(1,-1) == '-')
+	    {
+	      if (iscrate(curd(1,0)) && iscrate(curd(2,0)))
+	      {
+		int i;
+		i = ctoh(curd(2,0)) - ctoh(curd(1,0));
+		while (i < 0) i += 16;
+		nex = htoc(i);
+	      }
+	    }
+
+	    if (curd(-1,-1) == '-')
+	    {
+	      if (iscrate(curd(-1,0)) && iscrate(curd(-2,0)))
+	      {
+		int i;
+		i = ctoh(curd(-2,0)) - ctoh(curd(-1,0));
+		while (i < 0) i += 16;
+		nex = htoc(i);
+	      }
+	    }
+
+	    if ((curd(1,-1) == 'K') && (iscrate(curd(1,-2))))
+	    {
+	      if(ctoh(curd(1,-2)) < ctoh(curd(1,0))) nex = curd(1,-2);
+	    }
+
+	    if ((curd(-1,-1) == 'K') && (iscrate(curd(-1,-2))))
+	    {
+	      if(ctoh(curd(-1,-2)) >= ctoh(curd(-1,0))) nex = curd(-1,-2);
+	    }
+
+	    if ((iscrate(curd(-1,0))) && (curd(-1,1) == '>')) nex = curd(-1,0);
+	    if ((iscrate(curd(1,0))) && (curd(1,1) == '<')) nex = curd(1,0);
+	    if (curd(0,-1) == ':') nex = curd(0,-2);
+	    if ((curd(0,-1) == ';') && (iscrate(curd(0,-2)))) nex = curd(0,-2);
+	    if ((curd(0,1) == '.') && (iscrate(curd(0,2)))) nex = curd(0,2);
+	    if ((curd(-1,0) == '(') && (curd(1,0) == ')')) // collision
+	    {
+	      nex = ' ';
+	    } else
+	    {
+	      if ((curd(-1,0) == '(') && (issupport(curd(-1,1)))) nex = '(';
+	      if ((curd(1,0) == ')') && (issupport(curd(1,1)))) nex = ')';
+	      if ((curd(0,1) == '/') || (curd(0,1) == '\\'))
+	      {
+		if ((curd(-1,1) == '(') && (issupport(curd(-1,2)))) nex = '(';
+		if ((curd(1,1) == ')') && (issupport(curd(1,2)))) nex = ')';
+	      }
+	    }
+	    if (iscrate(curd(-1,0)))
+	    { // shift crates
+	      int bx=-1;
+	      while ((iscrate(curd(bx,0))) && (issupport(curd(bx,1))))
+	      {
+		if (curd(bx-1,0) == '(')
+		{
+		  nex = curd(-1,0);
+		}
+		bx--;
+	      }
+	    }
+	    if (iscrate(curd(1,0)))
+	    {
+	      int bx=1;
+	      while ((iscrate(curd(bx,0))) && (issupport(curd(bx,1))))
+	      {
+		if (curd(bx+1,0) == ')')
+		{
+		  nex = curd(1,0);
+		}
+		bx++;
+	      }
+	    }
+	    break;
+	  case '(':
+	    if (((curd(1,0) == '(') ||
+		 (curd(1,0) <= ' ') ||
+		 (curd(0,1) <= ' ') ||
+		 (curd(0,1) == '('))) nex = ' ';
+	    if (isramp(curd(0,1))) nex = ' ';
+	    if (isramp(curd(1,0))) nex = ' ';
+	    if (isramp(curd(-1,0))) nex = ' ';
+	    if ((isblock(curd(1,0))) ||
+		(curd(1,-1) == ',') ||
+		(curd(1,0) == '*')) nex = ')';
+	    if (iscrate(curd(1,0)))
+	    {
+	      int bx=1;
+	      while ((iscrate(curd(bx,0))) && (issupport(curd(bx,1))))
+	      {
+		if (isblock(curd(bx+1,0)))
+		{
+		  nex = ')';
+		}
+		bx++;
+	      }
+	    }
+	    break;
+	  case ')':
+	    if (((curd(-1,0) == ')') ||
+		 (curd(-1,0) <= ' ') ||
+		 (curd(0,1) <= ' ') ||
+		 (curd(0,1) == ')'))) nex = ' ';
+	    if (isramp(curd(0,1))) nex = ' ';
+	    if (isramp(curd(1,0))) nex = ' ';
+	    if (isramp(curd(-1,0))) nex = ' ';
+	    if ((isblock(curd(-1,0))) ||
+		(curd(-1,-1) == ',') ||
+		(curd(-1,0) == '*')) nex = '(';
+	    if (iscrate(curd(-1,0)))
+	    {
+	      int bx=-1;
+	      while ((iscrate(curd(bx,0))) && (issupport(curd(bx,1))))
+	      {
+		if (isblock(curd(bx-1,0)))
+		{
+		  nex = '(';
+		}
+		bx--;
+	      }
+	    }
+	    break;
+	  case 'O':
+	    if ((iscrate(curd(0,-1))) && (iscrate(curd(0,-2))))
+	    {
+	      int d;
+
+	      d = ctoh(curd(0,-1)) + ctoh(curd(0,-2)) * 16;
+	      if (curd(0, 1) == 'b')
+	      {
+		if (debug)
+		{
+		  char s[80];
+		  printf ("%c[%d;%dH", 27, 25, debopos);
+		  sprintf(s, "%d ", (int)d);
+		  debopos += strlen(s);
+		  if (debopos > SCREENWIDTH)
+		  {
+		    debopos = 1;
+		    printf ("%c[%d;%dH%c[K", 27, 25, 1, 27);
+		    debopos += strlen(s);
+		  }
+		  printf(s);
+		} else
+		{
+		  printf("%d ", (int)d);
+		}
+	      }
+	      if (curd(0, 1) == 'c')
+	      {
+		if (debug)
+		{
+		  printf ("%c[%d;%dH", 27, 25, debopos++);
+		  if (debopos > SCREENWIDTH)
+		  {
+		    debopos = 1;
+		    printf ("%c[%d;%dH%c[K", 27, 25, 1, 27);
+		    debopos++;
+		  }
+		  printf ("%c", (char)d);
+		} else
+		{
+		  putc((char)d, stdout);
+		}
+	      }
+	    }
+	  case 'A':
+	    if (iscrate(curd(-1,0))  || iscrate(curd(1,0))) nex = 'V'; else nex = cur;
+	    break;
+	  case 'V':
+	    if (iscrate(curd(-1,0))  || iscrate(curd(1,0))) nex = 'A'; else nex = cur;
+	    break;
+	  default: nex = cur;
+	}
+	if (iscrate(cur))
+	{
+	  if (issupport(curd(0,1))) nex = cur; else nex = ' ';
+	  if ((curd(1,0) <= ' ') && (curd(0,1) == '>')) nex = ' ';
+	  if ((curd(-1,0) <= ' ') && (curd(0,1) == '<')) nex = ' ';
+	  if ((curd(1,-1) == 'W') && (curd(2,-2) == cur)) nex = ' ';
+          if ((curd(-1,-1) == 'W') && (curd(2,-2) == cur)) nex = ' ';
+          if ((curd(1,1) == 'M') && (curd(2,2) == cur)) nex = ' ';
+	  if ((curd(-1,1) == 'M') && (curd(-2,2) == cur)) nex = ' ';
+	  if (curd(1,0) == 'V') nex = ' ';
+	  if (curd(-1,0) == 'V') nex = ' ';
+	  if (curd(1,0) == 'A') nex = ' ';
+	  if (curd(-1,0) == 'A') nex = ' ';
+	  if (iscrate(curd(-1,0)) && ((curd(-1,-1) == '+')
+	      || (curd(-1,-1) == '-'))) nex = ' ';
+	  if (iscrate(curd(1,0)) && ((curd(1,-1) == '+')
+	      || (curd(1,-1) == '-'))) nex = ' ';
+	  if ((iscrate(curd(-1,0)) || iscrate(curd(1,0))) && ((curd(0,-1) == '+')
+	      || (curd(0,-1) == '-'))) nex = ' ';
+	}
+      }
+    }
+    // fix nex array
+    for (x=0; x<=(maxx); x++)
+    {
+      for (y=0; y<=(maxy); y++)
+      {
+	switch (cur)
+	{
+	  case '*':
+	    if (curd(-1,0) == ')') nex = ' ';
+	    if (curd(1,0) == '(') nex = ' ';
+	    break;
+	  case 'O':
+	    if ((iscrate(curd(0,-1))) && (iscrate(curd(0,-2))))
+	    {
+	      nexd(0,-1)=' ';
+	      nexd(0,-2)=' ';
+	    }
+	    break;
+	}
+	if (iscrate(cur))
+	{
+	  if (curd(1,0) == ')')
+	  {
+	    int bx=0; int flag=0;
+	    while ((iscrate(curd(bx,0))) && (issupport(curd(bx,1))))
+	    {
+	      if (curd(bx-1,0) <= ' ')
+	      {
+		flag = 1;
+	      }
+	      bx--;
+	    }
+	    if (flag)
+	    {
+	      bx=0;
+	      while ((iscrate(curd(bx,0))) && (issupport(curd(bx,1))))
+	      {
+		nexd(bx-1,0) = curd(bx,0);
+		bx--;
+	      }
+	      nex = ')'; nexd(1,0) = ' ';
+	    }
+	  }
+	  if (curd(-1,0) == '(')
+	  {
+	    int bx=0; int flag=0;
+	    while (iscrate(curd(bx,0)) && (issupport(curd(bx,1))))
+	    {
+	      if (curd(bx+1,0) <= ' ')
+	      {
+		flag=1;
+	      }
+	      bx++;
+	    }
+	    if (flag)
+	    {
+	      bx=0;
+	      while ((iscrate(curd(bx,0))) && (issupport(curd(bx,1))))
+	      {
+		nexd(bx+1,0) = curd(bx,0);
+		bx++;
+	      }
+	      nex = '('; nexd(-1,0)= ' ';
+	    }
+	  }
+	  if ((curd(-1,0)=='C') ||
+	      (curd(1,0)=='C') ||
+	      (curd(0,-1)=='C') ||
+	      (curd(0,1)=='C')) nex = ' ';
+	}
+	if ((curd(-1,0)=='F') ||
+	    (curd(1,0)=='F') ||
+	    (curd(0,-1)=='F') ||
+	    (curd(0,1)=='F')) nex = ' ';
+      }
+    }
+#if __BORLANDC__
+    delay (deldur);
+#endif
+    memcpy(pg, pg2, LINEWIDTH * PAGEHEIGHT * sizeof(cell));
+  }
+  if (fi) fclose (fi);
+  if (fo) fclose (fo);
+  if (fs) fclose (fs);
+  if (debug) printf ("%c[22;1H", 27);
+#if CURSOROFF
+__asm
+{
+  mov al,0x01
+  mov cx,oldcursor
+  int 0x10
+}
+#endif
+  exit (0);
+}
+
+int isramp(c)
+  char c;
+{
+  return ((c=='/')||(c=='\\'));
+}
+
+int isblock(c)
+  char c;
+{
+  return ((c=='='));
+}
+
+int issupport(c)
+  char c;
+{
+  return ((c=='=')||iscrate(c)||(c=='(')||(c==')')||(c==';')||
+	  (c=='/')||(c=='\\')||(c==':')||(c=='*')||(c==',')||
+	  (c=='>')||(c=='<')||(c=='O')||(c=='W')||(c=='M')||
+	  (c=='A')||(c=='V')||(c=='~')||(c=='.'));
+}
+
+int iscrate(c)
+  char c;
+{
+  return ((c=='0')||(c=='1')||(c=='2')||(c=='3')||
+	  (c=='4')||(c=='5')||(c=='6')||(c=='7')||
+	  (c=='8')||(c=='9')||(c=='a')||(c=='b')||
+	  (c=='c')||(c=='d')||(c=='e')||(c=='f'));
+}
+
+int ctoh(c)
+  char c;
+{
+  if((c>='0') && (c<='9')) return (c-'0'); else return ((c-'a')+10);
+}
+
+char htoc(i)
+  int i;
+{
+  if((i>=0) && (i<=9)) return ((char)(i+'0')); else return ((char)(i+'a')-10);
+}