WAITS: Emulating the Xerox Graphics Printer

This time we'll look at the Xerox Graphics Printer, an ancestor of today's laser printers, and see how it was used at SAIL. I've created an new emulator which will produce PDF files from output intended for the XGP, so they can be seen again for the first time in 50 years. As an example, here is a montage of six files.

/images/waits/xgo-collage.png Montage of PDFs created from XGP files. Source: Rupert Lane. License: CC0.

Background

Xerox provided a XGP to Stanford, MIT and a number of other research institutes in around 1972. The printer was based on an earlier Xerox experiment, the LDX (Long Distance Xerography) which was a fax type system with a scanner and a printer. The XGP just had the printer part. It was similar to modern laser printers in that it used an electrostatic drum and ink powder to print an page, but it had a CRT rather than a laser as its light source.

It could print 192 dots to the inch on a roll of paper 8.5" wide; it had a knife under system control so pages could be cut or it could simply produce a long scroll. Output was black or white only with no greyscale.

Here's a picture taken by a DEC representative of the XGP at SAIL; not the console in the front, it's in the background at the centre of the picture. It seems most sites put a bin in front of it to catch its output. so it often looks quote humdrum.

/images/waits/xgp.jpg The XGP in the SAIL computer room. Source: CHM.

Each institute integrated this into their systems differently: MIT, for example, interfaced it to their PDP-10 via a PDP-11. Stanford chose to connect it directly to their PDP-10 and developer an interface in the WAITS monitor. This could print in either bitmap or text mode; in text mode it could

  • select different bitmap fonts stored on disk
  • write text, with support for kerning, overprinting and underlining
  • position items on the page with pixel accuracy
  • draw simple vector graphics

Many output files that were sent to the XGP have been preserved in the saildart.org archive - manuals, project proposals, letters - created by the users as part of their regular work.

You can also make new XGP files using the simh emulator by running the source processors like PUB on either contemporary input files or your own creations

Fonts

This was all taking place in the 1970s, well before Postscript or any of the font technologies we use today. Staff at SAIL created their own bitmap fonts, and there was lots of sharing with MIT, CMU and other XGP sites. As of 1974 the SAIL system had 71 fonts and by the time it was shut down in the 1990s there were over 500. These went beyond just English characters with different appearances, with fonts for Cyrillic, Hebrew and graphics.

/images/waits/fonts.png Sample XGP fonts. Source: scanned copy of Find-a-font

On WAITS there are utilities that use the DD terminal to display a font file (R DDFONT) and edit them (R EDFONT).

Document tools

Along with writing programs, creating documents was one of the key activities of the Stanford AI Lab: a study from 1970 reported that in 1969 the 64 staff produced 23 external documents, 28 AI memos and 15 SAILON operational notes during that year. (It then goes on to facetiously extrapolate from the rate of the growth in the 1960s to the year 2001 where it expected 158 million staff producing 29 billion documents).

To support this need, and to use the XGP, several document production tools were created at SAIL. These would all take a marked-up text file as input and produce a .XGP file as output, which could be sent to the printer via the XSPOOL command,

POX - Prototype Overlay Xewrographics - was written by Robert Maas and was a simple language specifically designed for the XGP. It has around 10 single letter commands introduced by a backslash: for example the below will define two fonts, set "Preface" in font 0 and use font 1 for the body, then starts a paragraph with justified text.

\M0BAXL30;\M1NGR25

\F0Preface\F1

\JThis document will introduce the POX language...

It also had a simple register based programming facility similar to TECO's called Q-registers, but no high level commands for producing structured text. It was generally used for smaller documents like letters. This can be run on WAITS via R POX which will prompt for an input file.

/images/waits/waits-pub-cover.png Cover of the PUB manual. Source: saildart.org

PUB was a scriptable markup language, implemented in 1971 by Larry Tesler from an idea by Les Earnest. This spread to other PDP-10 sites where it was extended (support for the XGP printer was added by CMU, for example). It had around 100 commands with an English like syntax together with a built in programming language similar to SAIL. An example from the manual to set up headers and footers with date and page number, and to indent paragraphs by six spaces:

.EVERY HEADING(DAN MATION,PARACYBERNETIC PHENOMENA,{DATE})
.EVERY FOOTING(,{PAGE},)
.INDENT 6

Although it was powerful, it was quite slow, processing around 15 pages per minute. Many of the SAIL manuals, such as those for FAIL, were produced using PUB. PUB is integrated into the RPG system so you can type PUB filename.pub to start the program.

/images/waits/tex.png A section from the TeX manual about running it at SAIL. Source: saildart.org

The most famous text processing language to come out of Stanford was TeX, by Donald Knuth. The first full version was written in the SAIL language and made available in 1978. This produced output to an XGP file rather than the DVI files used today. This was pre-METAFONT, so Knuth created XGP font files to integrate with the SAIL printing system.

As the disk images we have running today are from 1974, that means that TeX is not available to run under simh at present. However, the XGP emulator can render to PDF existing XGP files produced by TeX.

The emulator

The new emulator, xgptopdf, is a Python program that is independent from the WAITS simh emulator. It takes a XGP file produced by PUB, POX or TeX as input and produces a PDF file as output. You can directly reference a saildart.org file by giving its WAITS filename; the tool will download the file and produce output in one step.

For example, International Yum Yum was the lab's guide to restaurants around the world, the cover of which you can see in the bottom right of the montage at the top of this article. The first version of this file from 1978 is preserved at saildart.org as YUMMY.XGP[P,DOC]`, so you can type

    xgptopdf YUMMY.XGP[P,DOC]1

and it will make a file YUMMY.XGP[P,DOC]1.pdf in your current directory that can be viewed or printed.

For new XGP files generated by PUB or POX using the WAITS simh emulator, use the techniques described in an earlier post to extract the files to your own computer via a virtual tape file. When unpacking the DART archive you need the -Woct switch to extract in octal format. So say you had a tape file extract.tap that contained an XGP file MY.XGP[1,REL] run

$ dart -Woct -xf extract.tap
$ xgptopdf rel/1/my.xgp

and it will produce my.pdf in your current directory.

The XGP spool file does not embed the font, rather it references which fonts it wants to use via a file name. Therefore the emulator contains a collection of font files from the SAIL backup and a facility to switch font assignments if needed.

The Github repo contains a few examples of PDFs created by this tool. There are several hundred original XGP files on the saildart.org archive - and many more that can be created from their PUB or POX source - so it's well worth exploring to see what you can find.

Further information

The computer history wiki gunkies.org has a page about the XGP. There's information on how it was used at MIT, plus some pictures, at the PDP-10 Github organisation.

Find-a-font - SAILON 74 - contains a guide to the fonts available on WAITS and the font format.

saildart.org has the original PUB manual in text form, along with a version with additional notes from Larry Tesler.

Questions, corrections, comments

I welcome any questions or comments, and also especially any corrections if I have got something wrong. Please email me at rupert@timereshared.com and I will add it here and update the main text.


WAITS: Programming in Lisp

Continuing our series about programming on WAITS, this week we'll look at Lisp.

History

Stanford had a version of Lisp on the IBM 7090 and PDP-1 machines used in the first few years of the lab's existence. When they got their PDP-6 they took an early version of Maclisp from MIT, made changes to get it to work with the WAITS system and released it in 1966 in Lisp 1.6. The authors were John Allen, Lynn Quam and Whitfield Diffie (who after leaving SAIL became famous for his work on cryptography).

Lisp 1.6 gained some additional features: as of 1974, the date of the disk image we are using, it had:

  • An arbitrary precision fixed point number system.
  • An interactive s-expression editor called ALVINE.
  • Flexible I/O, including to the teletype and to files.
  • A compiler, which reportedly produced code that ran twenty times faster than interpreted code.
  • A library to control the III display terminal.
  • Debugging and tracing features.

Using interactive Lisp

Start the interpreter with R LISP. By default this will give you 12k of core which is only enough for trivial programs, to give more core space add a number representing the core size in kilowords, eg R LISP 48.

It will ask you ALLOC? which if you type Y will allow you to change sizes of memory buffers; normally just press Enter here. It will then put you at the * prompt where you can type s-expressions. Use upper case.

.r lisp

ALLOC? 


*(PLUS 2 2)

4

Note that integers are in octal, so use real numbers for calculations.

*(TIMES 8 3)

30 
*(TIMES 8.0 3)

24.0

Typing altmode (the Escape key) will close all open parens, for example after entering 5 below I pressed Escape, the interpreter printed $ and the two close parens were supplied automatically.

*(PLUS 10.0 2 (TIMES 6 5$
42.0

Variables can be set with SETQ and functions defined with DE.

*(SETQ Y 3)

3 
*(DE DOUBLE (X) (TIMES X 2))

DOUBLE 
*(DOUBLE Y)

6

The I/O system can handle multiple channels, but for simple reading from the terminal you can use READ which will accept a s-expression as input. PRINT will type out its argument, but you can also just evaluate a form to display its value.

Programs - collections of functions and other declarations can be created by editors outside of Lisp and read in to the environment using DSKIN. For example, (DSKIN (FOO . LSP)) will read in the file FOO.LSP in your current file area.

TPK in Lisp

Let's demonstrate Lisp by implementing the TPK algorithm in Lisp 1.6. We can use the Lisp 1.5 code for CTSS as a base. In the Lisp 1.5 version, the key function to calculate TPK, √|x| + 5x³, is expressed as

(F (LAMBDA (X) (PLUS (SQRT (ABS X)) (TIMES 5 (EXPT X 3)))))

so in Stanford Lisp 1.6 this would be:

(DE F (X)
    (PLUS (SQRT (ABS X)) (TIMES 5 (EXPT X 3))))

However, whereas Lisp 1.5 had EXPT but no SQRT or ABS, here we have ABS but not EXPT or SQRT. We can implement (EXPT X 3) as a cube function (TIMES X X X) but for SQRT we will need to resort to the Babylon algorithm we last used in the Essex BCPL program.

(DE CLOSE (X GUESS)
    (LESSP (ABS (DIFFERENCE (TIMES GUESS GUESS) X)) 0.000001))

(DE IMPROVE (X GUESS)
    (QUOTIENT (PLUS GUESS (QUOTIENT X GUESS)) 2.0))

(DE BABYLON (X GUESS)
    (COND ((CLOSE X GUESS) GUESS)
          (T (BABYLON X (IMPROVE X GUESS)))))

(DE SQRT (X)
    (BABYLON X (QUOTIENT X 2.0)))

This is recursive, so may run out of space for large numbers.

The heart of the program is then:

(DE F (X)
    (PLUS (SQRT (ABS X)) (TIMES 5 (CUBE X))))

(DE LIMIT-F (X)
    (PROG (RESULT)
          (SETQ RESULT (F X))
          (RETURN (COND
                   ((GREATERP RESULT 400.0) (QUOTE TOO-LARGE))
                   (T RESULT)))))

(DE TPK (NUMS)
    (MAPCAR (FUNCTION LIMIT-F) (REVERSE NUMS)))

MAPCAR is available so this was slightly simpler to write compared to Lisp 1.5.

Finally, a driver program doing the I/O:

(DE MAIN ()
    (PROG (NUMS)
          (PRINT (QUOTE "Please enter 11 numbers in a list"))
          (SETQ NUMS (READ))
          (PRINT (QUOTE "Results are"))
          (RETURN (TPK NUMS))))

To run, we load the file onto the file system using the techniques discussed in a previous post. When we run Lisp we need to give it some more core - here 32k just to be sure. We load in the file with DSKIN and execute the main function.

.r lisp 32

ALLOC? 

*(DSKIN (TPK.LSP))

CLOSE 
IMPROVE 
BABYLON 
SQRT 
CUBE 
F 
LIMIT-F 
TPK 
MAIN 
FINISHED-LOADING 
*(MAIN)

"Please enter 11 numbers in a list" *(10.0 -1.0 1.0 2.0 3.0 4.0 4.3 4.305 4.303 4.302 4.301)

"Results are" 
(399.88630 TOO-LARGE TOO-LARGE TOO-LARGE 399.60864 322.0 136.73204 41
.414213 6.0000000 -3.9999999 TOO-LARGE)

Further information

The primary manual for Stanford Lisp 1.6 can be found in LISP.WD[S,DOC].

The Computer History Museum Software Preservation Group has a detailed history of Lisp, including a page on Lisp 1.6 with several versions of the above manual in PDF format, and information on versions derived from this.

A simpler introduction to Lisp of this area can be found in Clark Weissman's LISP 1.5 Primer, which is also available at the Lisp history page above.

Questions, corrections, comments

I welcome any questions or comments, and also especially any corrections if I have got something wrong. Please email me at rupert@timereshared.com and I will add it here and update the main text.


WAITS: Programming in SAIL

Today we'll look at SAIL, which was derived from Algol 60 and was developed and used on WAITS for both system programs and research projects.

There was a compiler named SAIL,

Assembled and coded in FAIL.

Its authors, they say

(one glorious day)

Were run out of town on a rail.

Comment in the source code for the SAIL compiler, SAIL[S,AIL]

History

SAIL was a combination of work done on two languages. The first was Gogol, which was a simplified version of Algol 60 for the PDP-1. Not much information on this remains apart from a list of its error messages.

The other source - primarily for its associative arrays - was the LEAP language, which was written by Jerome Feldman and Paul Rovner for the Lincoln Labs Tx-2 machine; there's a paper describing this at the ACM.

The compiler was written by SAIL members Don Swinehart and R. Sproull, with the first version being available in November 1969. As the manual puts it

SAIL in a sense has something for everyone. For those who think in ALGOL, SAIL has ALGOL. For those who want the most from the PDP-10 and the time-sharing system, SAIL allows flexible linking to hand-coded machine language programs. For those who have complex input/output requirements, the language provides complete access to the I/O facilities of the PDP-10 system. For those who aspire to speed, SAIL generates fairly good code.

It achieved its goal, with wide use at Stanford and it spread to other PDP-10 sites.

In 1980, there was a commercial spin off of SAIL called MAINSAIL. This was cross-platform, with initial versions on other PDP-10 and -11 operating systems, and possibly VAX and System/360 also. The language had some success (one user was VLSI Technologies for electronic design tools) and was available for at least HP-UX, AIX and IRIX up to the early 2000s. Bitsavers has some documentation.

SAIL features

Like every other Algol 60 implementation, program format and I/O is slightly different, so to set the scene, here's a simple hello world program.

BEGIN
    INTEGER I;
    COMMENT Print Hello World 5 times;
    FOR I ← 1 STEP 1 UNTIL 5 DO
        OUTSTR("HELLO, WORLD" & '15 & '12)
END PROGRAM

This follows the typical Algol 60 block structure, using BEGINEND and having statements separated rather than terminated by semicolons, so the last statement in a block should not have a semicolon at the end. Comments are statements as well so need to be terminated depending on their position.

The assignment operator is an arrow, which was typeable using the Stanford keyboard; on a teletype you could use _ instead. A ↔ B would swap the values of A and B.

For I/O there is an extensive set of routines that can handles files and different devices, but for console I/O you can use OUTSTR to print strings (adding a CR/LF line terminator in the above example) and read a line of input to a string with INCHWL.

Real, integer and boolean types are provided, along with arrays. Strings are internally represented as a two word value, the first being a character count and the second a pointer to an array of 7 bit characters. The body of the OUTSTR shows concatenation of a string literal with two characters, CR/LF, to produce a new string.

Procedures take value or reference parameters, can be called recursively (with the keyword RECURSIVE PROCEDURE). Procedures can also be passed into other procedures.

The LEAP facilities allow sets (PUT item IN set) and associative arrays (MAKE key ⊗ object ≡ value). You can then do search operations on these using FOREACH. An example adapted from the manual:

FOREACH x,y,z SUCH THAT father ⊗ x ≡ y AND father ⊗ y ≡ z DO
    PUT z IN grandfathers

Macros are similar to C's macro processor: you can define constants and then they get expanded in the program when used:

    DEFINE ARRAY_SIZE="11";
    ...
    INTEGER ARRAY DATA[1:ARRAY_SIZE];

or to take parameters.

    DEFINE APPEND(x, y)="x ← x & y";

TPK in SAIL

Let's use the compiler to run the TPK algorithm. The source code can be found here. This can be loaded onto the disk using the techniques described in this post.

The full program looks like this:

BEGIN
    COMMENT TPK algorithm in SAIL for WAITS;

    REQUIRE "{}{}" DELIMITERS;
    COMMENT Size of array to use for TPK;
    DEFINE N = {11};
    COMMENT Macro definitions to print a string with CR/LF at the end;
    DEFINE CRLF={('15 & '12)};
    DEFINE TYPE(MSG)={OUTSTR(MSG & CRLF)};

    REAL PROCEDURE FN(REAL X);
    BEGIN
        RETURN(SQRT(ABS X) + 5*X↑3)
    END;

    COMMENT Main program;
    INTEGER J;
    REAL ARRAY A[1:N];
    TYPE("Please enter 11 numbers");
    FOR J ← 1 STEP 1 UNTIL N DO
    BEGIN
        STRING REPLY;
        BOOLEAN BRCHAR;
        REPLY ← INCHWL;
        A[J] ← REALSCAN(REPLY, BRCHAR)
    END;
    TYPE("Results are");
    FOR J ← N STEP -1 UNTIL 1 DO
    BEGIN
        REAL RESULT;
        RESULT ← FN(A[J]);
        IF RESULT > 400.0 THEN
            TYPE("Too large")
        ELSE
            TYPE(CVF(RESULT))
    END;
END

One additional trick is used for macros:

    REQUIRE "{}{}" DELIMITERS;
    DEFINE TYPE(MSG)={OUTSTR(MSG & CRLF)};

The first line redefines the start and end delimiters for macros to be curly brackets rather than double quotes; if this is not done, any double quotes in the text being expanded, for example a string constant TYPE("Hello") would not work.

The procedure FN shows use of ABS as a unary function, and as the exponentiation operator.

We use several type conversion functions here. REALSCAN takes a string and a boolean and returns a real value if found, otherwise it will set the boolean to true (we ignore this in the program). CVF conversed a real to a string.

To compile and run, assuming the program is stored in a file tpk.sai, use exec:

.exec tpk

SAIL: TPK    1
LOADING

LOADER 2K CORE
EXECUTION
Please enter 11 numbers

Errors found in compilation are handled interactively. If for some reason I had put UNREAL PROCEDURE it would halt with

.comp tpk

SAIL: TPK    1
UNDECLARED IDENTIFIER: UNREAL
TPK, PAGE 1
01100           UNREAL
                       PROCEDURE FN(REAL X);
^

At this prompt, you can press Enter to continue: in some cases it may be able to correct the situation but here it would ignore the statement. You could press E and it would open the file at that line in the SOS editor; T would do the same in TV. X would exit. Pressing ? shows a full list of what options are available

Further information

The main manual for SAIL can be found in SAIL.DCS[S,DOC] or on Bitsavers as a PDF.

Dan Swinehart gave a talk on the history of SAIL (and some background on its name) at a 2009 reunion - the video is at the Stanford Archives.

Questions, corrections, comments

I welcome any questions or comments, and also especially any corrections if I have got something wrong. Please email me at rupert@timereshared.com and I will add it here and update the main text.


WAITS: Programming

As an operating system for a research lab, WAITS was used extensively to write programs. In this post we'll look at which languages were used, the software development environment - and investigate an early implementation of Donald Knuth's MIX system.

/images/waits/fail-manual-cover.png Cover of the FAIL manual.. Source: Bitsavers

Lisp, FAIL and SAIL

The three main programming environments used by the lab were all maintained in house.

Lisp was the main language for AI research at that time, and as the original author of Lisp, John McCarthy, was the head of SAIL it was natural it would be used here. The main version used was Lisp 1.6, an evolution of Lisp 1.5 from MIT, but there were also other dialects - MLISP, which understands m-expressions like 2+2 instead of the more traditional Lisp s-expressions (PLUS 2 2), and UCI Lisp from the University of California in Irvine, which extended Lisp 1.6 and added tools from BBN Lisp.

Although DEC's MACRO assembler for the PDP-10 was available, the main assembler used was developed at SAIL by Phil Petit and was called FAIL. This was a single pass assembler, which ran five times as fast as DEC's version, and also had more powerful macro capabilities. This was used by system programmers and researchers who needed the extra speed and flexibility of machine language.

SAIL was the lab's version of Algol 60. It added support for linking to PDP-10 assembly language, I/O facilities, extra data structures like associative arrays and a macro package. This made it a good choice for writing system utilities and general algorithmic programs. The first version of Knuth's TeX was written in SAIL.

We'll look at Lisp and SAIL further in future posts.

Other languages

The standard set of languages from DEC - AID, BASIC and Fortran - are also available on WAITS. These work much the same as on TOPS-10, so see the linked articles above for more details. Note that the Fortran version is F40 rather than the newer Fortran-10.

There are a couple of programming languages that came from other sources. A version of SNOBOL called Fasbol which originated from the PDP-10 at Berkeley can be executed with R FASBOL. Micro-planner, based on the PLANNER language, came from MIT and can be run via R PLNR.

This is as of July 1974, the date of the system image we are running. Looking at saildart.org other languages were added later on, including Pascal, Simula and C.

The development environment

Similar to the concept of 'compile class' commands in TOPS-10 is RPG, or Rapid Program Generation, on WAITS. This can save on typing - as an example, if you just created and compiled a file with

. CREATE hworld.f4
. EXEC hworld.f4

for the rest of the login session you can type commands without parameters, so EDIT would edit the file and EXEC would compile and run it. This works across the different editors and languages supported at SAIL.

As well as the DEC-supplied CREF cross-reference listing tool and DDT debugger, SAIL created a more powerful debugger called RAID.

MIX

MIX was a hypothetical machine Donald Knuth designed and used in his book The Art of Computer Programming to illustrate how an algorithm could be implemented in code without depending on a specific computer or high level language. The book defines the MIX machine and an assembly language that can target it.

An implementation of MIX for a real machine is a handy way to experiment with these algorithms, and one was developed on the SAIL machine in around 1970. The assembler is run via R MIXAL and the virtual machine via R MIX. The latter also includes facilities for debugging, such as examining the memory or tracing through instructions.

Documentation is in MIX.RES[UP,DOC] and the source code, in FAIL, is in [MIX,SYS].

I'm not completely sure who wrote this: the source code does not state an author, and the way it describes the program ("MIX is a simulator for the MIX machine described in Knuth, vol. 1.") leads me to believe it was not Donald Knuth himself. There's a comment in MIX1[MIX,SYS]

(CS236B–June 5, 1970)

which makes me think it was done as part of a course, and looking at the Stanford publication Courses and degrees. 1969-1970 page 240 indicates CS236-B was a system programming course taught by Knuth:

The first instance of the documentation MIX.RES[UP,DOC] is from 1972, and the SAIL convention of using the programmer ID who wrote the doc as its extension, so RES. This ID was used by Richard Smith, who may have been involved in the original work or took over maintenance of it later.

Further information

My posts on TOPS-10 programming are useful to compare the languages and tools between the two systems.

Questions, corrections, comments

I welcome any questions or comments, and also especially any corrections if I have got something wrong. Please email me at rupert@timereshared.com and I will add it here and update the main text.


WAITS: Arthur Samuel's Checkers

Although chess was a popular target, one of the earliest examples of using classical pre-LLM artificial intelligence to play games was checkers/draughts. Arthur Samuel wrote one of the first such programs in the early 1950s, ported this to the PDP-10 when he moved to SAIL and even created a version for a home computer in the late 1970s.

In this post we'll look at Samuel's work on checkers and run the 1972 version he created on WAITS.

History

/images/waits/samuel-vs-the-ibm-7090.png Samuel playing against the IBM 7090. Source: IBM

Arthur Samuel started out working on vacuum tubes at Bell Labs in the 1930s. In 1946 he became a professor at the University of Illinois. Wanting to get a computer for the university, he came up with a proposal to build one, and for it to run a program that could play checkers. He started planning for it on paper, but both it and the computer were not finished when he left in 1949 to work at IBM.

There his main role was on vacuum tubes and later transistors, but the problem of checkers still intrigued him. He worked on it using the IBM 70x series of machines - according to a letter to a computer magazine journalist in 1979, it was written initially in raw machine code as even an assembler was not available for the IBM machine yet. A first version was ready in 1952, but

It was not until 1954, with the advent of the IBM 704 that my program was able to play an interesting game. My contribution was to add learning to the program, and I believe that I can claim a first for this.

In 1956 the program was demonstrated on TV and caught the imagination of the public. Eventually it was able to play games at a level that could sometimes challenge a master player.

Using techniques such as minimax, alpha-beta pruning and rote learning, his work was influential in the early years of AI; Samuel was present at John McCarthy's 1956 Dartmouth workshop and his work was included in Feigenbaum and Feldman's seminal 1960s overview of AI, Computers and Thought.

He retired from IBM in 1966 and came to SAIL as a senior member of staff. Here he helped with many of the lab's projects, and also ported his IBM 7090 assembly program to PDP-10 assembly language. The version we have running today is from 1972.

/images/waits/waits-checkers-running.png Checkers running on WAITS. Source: Rupert Lane. License: CC0.

He picked it up again in 1976 due to interest from other researchers, and played against a team at Duke University who had a new program running on an IBM System/360. Two games were played, but not to completion due to the amount of CPU time needed. According to an account by Samuel:

it was believed that the Duke program had a possible win in both games. Subsequent analysis reveals that one of these games might still lead to a draw.

Also in 1977, he worked with the makers of the VideoBrain Family Console to develop a version of checkers for this early home computer. This was a cut-down version, as the system only had 1KB of RAM, but offered four different levels of difficulty. He also helped on the AI for the VideoBrain version of Reversi/Othello, Vice Versa.

/images/waits/videobrain-chekers.jpg VideoBrain checkers program and manual. Source (l) atariprotos.com (r) archive.org

Playing checkers on WAITS

The program can be run on any terminal type by typing R CHECKE. Type HELP (must be in upper case) to see a list of commands: you can enter initial board settings, adjust playing parameters and even have the computer play itself with the PS command.

By default, you are playing first (as black/red) and the computer second (as white/blue). You enter moves by typing the source and destination squares, using the standard notation where 1 is the bottom right position and 32 the top left.

Here I start the program and move from square 9 to square 13.

.R CHECKE

        26 JUL 74


1*      9 13

The program will then try to find the best move and print it, along with some statistics on the number of positions it searched, the best value of its evaluation function, and the time taken in milliseconds (so about 13s here, would have been much slower on real hardware)

        MOVE   # OF BDS    PIECE   EVAL   TIME

2       23-19    219956.       0     35  13567

so it has moved 23-19. You can type the instruction BD to display the board in ASCII:

3*     BD

* * * * * * * * * *
* + W + W + W + W *
* W + W + W + W + *
* + W +   + W + W *
*   + W +   +   + *
* +   +   +   + B *
* B + B + B +   + *
* + B + B + B + B *
* B + B + B + B + *
* * * * * * * * * *

But to make life easier, you can also use something like gametable in two player mode to record the moves; here's how the board would look like:

/images/waits/waits-running-checke.png Playing checkers against CHECKE. Source: Rupert Lane. License: CC0.

If you type a nonsensical move it will print:

3*    99 66
SORRY CHARLIE!

I won't give a full account of the game, but by move 44 the program announced:

THE PDP-10 EXPECTS TO WIN IN 11 MOVES.
44      26-22     15171.   11 MOVE WIN.   1017
/images/waits/waits-checkers-board-4.png

but my downfall occurred just three moves later. Here, FORCED is printed because by the game's rules if it can take an opposing piece it must.

45*    10 15
46      17-1          3.       FORCED        0
47*    15 18


        26 JUL 74


1*

The source code

The original IBM 7090 code is not publicly available as far as I am aware.

Samuel's directories on the WAITS system can be found on saildart.org. It's hard to tell what code matching the CHECKE binary from 1972, but CKP2.MAC[2,ALS] is the oldest file, dating back to 1971. Further enhancements - up to 1977 - can be found in [CH2,ALS] and sample game data in [CH3,ALS], [CH4,ALS] and [3,ALS].

The code shows evidence of it being a port of the IBM 7090 version, with translations into subroutines of some instruction where there was not an equivalent on the PDP-10 , eg CAQ.

The VideoBrain development directory is called F8. This includes several versions of the checkers source code along with a cross-assembler in Fortran, presumably written by Fairchild (who made the CPU in the VideoBrain). It's not clear how much was written by Samuel, and how much by his collaborators at VideoBrain. There is also some correspondence between Samuel and the makers of the Videobrain, with Samuel suggesting other games that could be produced and complaints about the unreliability pf the development hardware.

Further information

IBM's article The games that helped AI evolve is a first introduction to Samuel's work at the company on checkers and also discusses Tesauro's TD-Gammon program.

Samuel's original July 1959 paper, "Some Studies in Machine Learning Using the Game of Checkers", in IBM Journal of Research and Development, vol. 3, no. 3, pp. 210-229 is available for download at IEEExplore. The IEEE also has a memorial on Samuel's work.

Richard Sutton and Andrew Barto's book Reinforcement Learning: An Introduction is available in full online and has a case study on Samuel's checkers.

MAME has an emulator for the VideoBrain and copies of the game's cartridge ROM can be found online.

Another early checkers program was written by Christopher Strachey for the Ferranti Mark 1 in the early 1950s; there is an emulator that can run this.

Questions, corrections, comments

I welcome any questions or comments, and also especially any corrections if I have got something wrong. Please email me at rupert@timereshared.com and I will add it here and update the main text.


Next →