IntroductionThis page discusses what the original syntax of the SCI language may have looked like. CluesThere are not very many clues available regarding the original syntax of the SCI language. Those that are available are discussed below. The Official Book of King's QuestThis is a book written by Donald B. Trivette, in which there are a couple of clues related to the original syntax of the SCI language: Description of the LanguageOn page 16 (chapter 2) of the first edition, it has this to say about the Script Interpreter: "T he programmer is the one who puts all the rooms and animated characters together to make the game run. He does this using a special computer language called SCI (SCript Interpreter) developed by Sierra. SCI is an object-oriented language similar to LISP; it's written in Assembler, C, and itself." Note: Although this book contains sample code snippets, these are unfortunately from the older AGI language and not SCI. What does this the above description tell us?
SCI ClassesOn page 17 the book mentions the Actor class, the View class and the Prop class. On page 18 it mentions Wander, Chase and MoveTo. Ex-Sierra Employee CommentsThese are few and far between. However there are a couple: Mark Wilden's Smalltalk PageAt the time of writing, you can find this page at the following address: http://web.archive.org/web/20101219175024/http://www.mwilden.com/smalltalk/index.htm. Mark has this to say about the SCI langauge: "SCI was a combination of Lisp, C and Smalltalk, but the message-passing was very much Smalltalkesque. I loved the language." And strangely he has this to say about LISP: "So what did the Unix haters like? Well, Lisp. I'm sorry, but I cannot get into Lisp (I tried hard during my six-month Linux-Java-Emacs phase)." And on his blog he says this about SCI: "They had actually created their own language, SCI, that was a very pure implementation of OOP. I'll never forget that first night reading the documentation on my bed and just being consumed with this language that did things I wanted to do and even things I didn't know I wanted it to do. Ever since then, I've run into lots of people who talked about the difficulties of making the paradigm shift to OOP. But not me. It was love at first sight." Here is another comment from Mark, this time from a Smalltalk forum: "Sierra On-Line used a proprietary language for their adventure games which had many similarities to Smalltalk. There weren't blocks, but you could override methods in instances." What does this tell us?
J. Mark Hood InterviewAn interview with J. Mark Hood (http://www.gamasutra.com/view/feature/4130/from_sierra_to_korea_j_mark_.php?page=3) has the following to say: "I was doing language design, and they happened to be doing a new language to create computer games with -- adventure games -- called SCI. And they were developing this new object-oriented development language, and there were very few people actually back then that were doing object-oriented [programming]... Well, it turned out that SCI was very good at making games really fast, and so I started becoming just in charge of running the object-oriented toolset and building up the class library." What does this tell us?
Standard SCI0 Debug ModeEveryone knows about the standard debug mode that all SCI0 games had built in. It was activated with SHIFT-SHIFT-MINUS (the minus on the keypad). So what exactly can the debug mode tell us about the syntax of the original language? If you type in "s" when in the debug mode, it shows you something called the Send Stack. If you then step through the SCI instructions using the debugger, you will see the send stack get more and more items added to it, for example: (sounds eachElementDo:) (Game doit:) (KQ4 doit:) (KQ4 play:) What does this tell us?
Selector NamesAs mentioned elsewhere on this site, the file VOCAB.997 contains the selector names for the game. If you skip ahead and read the section below entitled "Smalltalk Message Passing" then you'll get an idea of what a selector is. The reason that this file is interesting in relation to the original SCI syntax is because it helps us to see similarities to other programming languages. All classes in the SCI programming language extend from the Object class. This class is in contained in the file SCRIPT.999 along with all the other non-adventure classes, such as Collection, Set, List, Code, Script and Event. The Object class is very interesting as regards the investigation into the original SCI language syntax. These are a few of the method names on that class (you can see these in VOCAB.997 and track them back to the Obj class in SCRIPT.999, or for the easier approach you can load up VOCAB.997 in SCI Companion to see these): isKindOf isMemberOf respondsTo yourself perform If we type this into Google and hit search, the results are mostly for Smalltalk, Squeak or Objective-C. Squeak is a Smalltalk implementation. Objective-C is a language that adds Smalltalk-style messaging to the C programming language. There is a common theme here. If you examine the results a bit closer, you'll notice that the results that actually have the unbroken strings above in them are almost all Smalltalk results. Here are a couple of examples: What does this tell us?
PMachine Instruction Set CluesSCI programs execute on a virtual CPU or what is known as a PMachine (which stands for p-code machine or pseudo code machine). A PMachine has a pseudo machine language, which is a set of machine instructions for a machine that doesn't really exist. It exists solely in software. The most common examples of this these days are the Java virtual machine and the .NET virtual machine but the idea has been around for a long time, since around 1966. Here are a few links to information about the SCI PMachine (these actually are all to the same page of the SCI specifications but I've added all three just in case one or more of these links change over time): The instruction set of the SCI PMachine can tell us a few things about the original SCI syntax. Arithmetic OperatorsThe SCI PMachine instruction set contains a full set of arithmetic instructions. Each of these instructions will map 1-to-1 with an arithmetic operator in the SCI language. For example: add maps to (+ arg1 arg2) sub maps to (- arg1 arg2) mul maps to (* arg1 arg2) div maps to (/ arg1 arg2) Relational OperatorsThere is likewise a 1-to-1 mapping between the relational instructions in the instruction set and the equivalent operators in the SCI language. For example: eq? maps to (== arg1 arg2) ne? maps to (!= arg1 arg2) gt? maps to (> arg1 arg2) ge? maps to (>= arg1 arg2) A more detailed analysis of the arithmetic (and logical and relational and bitwise) operators will be covered in the Operators page. Send InstructionWhere things get interesting is with the send instruction. Let's reproduce the description of this instruction from the SCI specifications:
Something that immediately strikes me about this is that it is sending multiple messages using what is effectively keyword syntax. The example above is essentially a keyword message (see the Smalltalk Message Passing section below for a description of this). There is a single "send" instruction being invoked but there are three different messages. This is something that doesn't happen in VMs such as the Java VM. In the Java VM the stack frame contains data for invoking a single method. The Java invoke VM instructions invoke a single method and there are separate instructions for changing and getting fields (AKA properties). In SCI, however, we can see that all of these things can be done with "send". This says something about the higher level language and what it can do. It suggests keyword messages as used by Smalltalk. Fan-made SCI IDEsThere are two fan-made SCI IDEs at the time of writing. These are SCI Studio and SCI Companion. The fan-made IDEs have embraced the idea of the original syntax being LISP-like. The authors of these tools had very few clues to go on when they implemented the language syntax. It has been known since 1988 when The Official Book of King's Quest came out that the syntax was LISP-like. So this has been embraced by the IDEs. It wasn't known until fairly recently that SCI syntax was also strongly influenced by Smalltalk. For this reason the syntax used in the IDEs has no similarity to Smalltalk. Instead it uses a C like syntax for invoking procedures and methods. The reason I have listed the fan-made IDEs as a "clue" is not because of the syntax that they use but because of the keywords that they use (note that in LISP these are referred to as "special forms" and not keywords - see LISP section below). The template game source code that comes with these IDEs was reverse engineered from the original games data files. It therefore gives us a clue about the "types" of keyword/statement that the original SCI language must have supported but perhaps not necessarily the actual names of those keywords. If we look through the source code of the template game, we can see the following keywords: if, for, while, switch. It is highly likely that the original language supported structures of these types. The reason for this is that when the template game source was reverse engineered, it would have been fairly obvious to the person doing that manual decompilation from the patterns of byte code within the compiled scripts that these language structures must have existed in the original language. For example, repeated testing of a single variable against multiple values suggests a "switch". If the testing of a variable's value is only against a single value then it suggests an "if". If, however, the testing of a variable's value is within a loop where a branching instruction jumps back above the test then perhaps it is the condition test for a "for" loop or a "while" loop. Recognising the difference between these would be a matter of what it does at the top and bottom of those loops. What does this tell us?
Smalltalk Message PassingMore than one clue above has suggested a Smalltalk syntax to the SCI message passing. This has been confirmed by ex-Sierra employees. So let's do a bit of research about what Smalltalk message passing is like. In "An Introduction to Object Oriented Programming" by Timothy Budd, he has this to say about Smalltalk's message passing: "Smalltalk and Objective-C use a slightly different syntax. In these languages a space is used as a separator. Unary messages (messages that take no argument) are simply written following the receiver. Messages that take arguments are written using keyword notation. The message selector is split into parts, one part before each argument. A colon follows each part of the key."Here is another description of the Smalltalk messaging passing style in this article entitled "Simplicity Makes the Difference that Makes the Difference" by Peter William Lount: "Smalltalk's language syntax is in part based upon "keyword" and "parameter" pairs delimited by a colon character, ":", for "setting" or "passing" a paramter to an object one writes the keyword as "x: 100" or "name: 'tom'" for keywords with single parameters, and "x: 100 y: 699" for multiple keywords and multiple parameters. When "getting" a parameter value from an object one simply uses a keyword without the parameter (and colon)." And this six page PDF has a nice visual explanation of the Smalltalk message passing syntax on page 3: The Smalltalk message passing syntax is sometimes referred to as "keyword notation" or "keyword syntax" but appears to be more commonly called "keyword message". What it all boils down to is this, using the standard terminology, is this: receiver selector: argument where the receiver is an object. If we wrap this in LISP-like parentheses we get this: (receiver selector: argument) And for multiple messages we get this: ( receiver selector1: argument selector2: argument1 argument2) The following example shows how this would be used in a SCI game: (ego x: 100 y: 150) LISP-like SyntaxOne thing that has been known about the original SCI syntax for a long time is its LISP-like syntax. Characteristics of LISPSo what is it that makes something LISP-like? What are the characteristics of LISP that make it recognisable as LISP? "Lisp uses the distinct S-expressions or prefix notation. This notation can be summarized as (function arguments...). You always start with the name of a function, and list zero or more arguments to pass in to that function. The function and its arguments are organized together by surrounding them with parentheses. This leads to one of the trademarks of Lisp: a lot of parentheses." "S-expressions are probably best known for their use in the Lisp family of programming languages. They are typically represented in text by parenthesized, whitespace-separated sequences of character strings, as in (= 4 (+ 2 2)), which represents the Boolean expression commonly written as 4==2+2 in C and its related programming languages. In Lisp, the first element of every S-expression is an operator and any remaining elements are treated as data. This is called "prefix notation" or "Cambridge Polish notation"." "Polish notation, also known as prefix notation, is a form of notation for logic, arithmetic, and algebra. Its distinguishing feature is that it places operators to the left of their operands." The above quotes are all telling us essentially the same thing. It all boils down to this: (function arguments...) which is equivalent to this: (function [argument1 argument2 ...]) A function might be an arithmetic operator, e.g.: (+ 3 5 6) ...or a relational operator: (> y 5) ...or a logical operator "special form": (and (< x 5) (> y 6)) ...or perhaps a flow control "special form": (if (< x 4) ...) ...or even a user defined function. Everything follows the same general pattern. The last two examples, however, are not standard LISP expressions. They are what LISP calls "special forms". They are primitives defined by the language that are necessary for things such as flow control. In other languages we might call them keywords but in LISP "keyword" has a very different meaning so I'll attempt to avoid using that term from now on. "Special Forms" are expressions that appear to look like standard LISP expressions but that do not follow the normal rules of evaluation. For a normal expression in LISP, all arguments are evaluated in the order from left to right. For example: (+ (- 5 3) (* 2 2) (+ 2 4)) It makes sense to us just by looking at the above expression that all of the arguments to + will get evaluated and the end result will be 12. In the case of a "special form", this does not happen. For example: (if (< x 4) (print "Hello")) Clearly we don't want the second argument to be evaluated if x is greater than or equal to 4. The "if" special form has semantics that says only evaluate the second parameter if the first parameter equates to true. This type of behaviour does not conform to the normal rules of evaluation in LISP. For some more information of LISP special forms, see the following: The following page is a quite interesting comparison of the most common LISP dialects. It gives us a feel for the types of operation that is common to LISP. Note that Scheme is the oldest of the four common dialects. Scheme and Common LISP are the most common these days but Common LISP was fairly new when the SCI language was invented, so Scheme would probably have had the most influence if any. How LISP-like was it?In the last section we explored some of the characteristics of LISP, the things that make it visually recognisable as LISP. But since SCI was supposedly a combination of LISP, C, and Smalltalk, exactly how LISP-like was it? Which parts of the SCI language were LISP-like, which were Smalltalk-like and which were C-like? I think it is very interesting that Mark Wilden says on his Smalltalk web page that "I'm sorry, but I cannot get into LISP". This is a comment from someone who tried hard to give LISP a chance but in the end he just couldn't like LISP. On the other hand Mark describes SCI as a language that he fell in love with at first sight and that one of the highlights of his programming career was reading the SCI documentation for the first time. So how can SCI be LISP-like and yet not remind Mark Wilden strongly enough of what he dislikes about LISP? I think we have to conclude that SCI is not a LISP. It might look like LISP visually but perhaps that is where it stops. I think in order to be LISP-like, it must have had at least these features:
And that is perhaps where the likeness stops. Putting It All TogetherAs was mentioned above, the syntax used by SCI Studio and SCI Companion was in part based on a small snippet of SCI code that was floating around the SCI community in the late 90s. This code snippet was short and perhaps only showed a small part of the syntax. For this reason some parts of the SCI Studio syntax are bang on the mark and others parts are very different. Ex-Sierra employees having seen the syntax used by SCI Studio have confirmed that it is definitely not the original SCI syntax. The message passing is one area that is very different. In this section we will show a code snippet from the SCI Studio template game and then apply all of the various clues that we have discussed above to the code snippet to reach something that is closer to the original SCI syntax.
In-Game Code GenerationQuest for Glory IIFeature WriterQFG2 has a debug command called Feature Writer. This is accessed within QFG2 by firstly typing "suck blue frog" to activate the debug mode, and then typing "ALT-W". It then takes the user through a sequence of dialogs that allows the user to define one of a Feature, a Prop, a PicView, a View or an Actor. After entering all the details, it will then display the SCI source code to the screen and also write the code into a file on the disk drive. For example, the following SCI source code was generated by QFG2 using the Feature Writer: (instance Harry of Actor (properties x 187 y 136 z -17 heading 0 noun 'harry' view 0 loop 0 cel 0 description "Harry" sightAngle 90 closeRangeDist 50 longRangeDist 100 shiftClick verbLook contClick verbGet ) ) What does this tell us?
Write Cast To FileThere is another debug option to Write Cast to a file. This produces a file with code like the following, for each Actor in the room:
What does this tell us? Polygon Editor
What does this tell us? Path Maker
What does this tell us? SQ5, LSL6, Freddy Pharkas and Similar Later GamesFeature WriterSome of these later games have a Feature Writer tool within the game, similar to what was discussed above for QFG2, but in addition to generating a "properties" section for the instance, it also generates the shell of a method within the instance, e.g. as follows:
(instance Bob of Actor (properties x 273 y 169 z 56 heading 0 view 220 loop 0 cel 0 sightAngle 40 approachX 273 approachY 113 approachDist 0 _approachVerbs $0 noun Bob ) (method (doVerb theVerb) (switch theVerb (LOOK ) (DO ) (else (super doVerb: theVerb) ) ) ) ) And others like this:
(instance monitor of Feature (properties x 295 y 27 sightAngle 40 noun ) (method (init) (self setPolygon: ((Polygon new:) type: PTotalAccess, init: 274 45 301 55 314 52 316 46 315 7 297 0 293 0 274 12, yourself: ) ) (super init: &rest) ) );monitor
Polygon EditorThese later games also often have a Polygon Editor. The following are some examples of the output that this editor can produce:
; Polygon Editor 1.11 ; Dynamic Obstacles : Picture 230 (curRoom addObstacle: ((Polygon new:) type: PBarredAccess, init: 0 0 319 0 319 124 281 124 281 110 205 110 168 113 151 74 147 74 147 114 134 114 129 105 51 105 51 78 37 78 37 105 0 105, yourself: ) ((Polygon new:) type: PBarredAccess, init: 0 174 319 174 319 189 0 189, yourself: ) ) (altPolyList add:
What does this tell us?
Dialog EditorThe third of the in-game source code generation tools is the Dialog Editor. The following is an example generated by Freddy Pharkas:
The following is the genuine SCI source code that was in general circulation before the turn of the century. I had originally thought that this had been lost a long time ago. It appeared on some SCI related web sites from 1999 but most of the SCI related web sites from back then no longer exist. However, thanks to the Wayback Machine and Wikipedia, it has been found again. If we glance over the syntax, it appears to validate most of the conclusions made above about what the syntax must have looked like.
There are several inconsistencies and mistakes in this code, but it is repeated above in its original form. It is thought that the errors in the code might provide clues as to the original of the code. Was it typed in by hand, perhaps out of a book or magazine? The missing : and ) at the end of "(theGame handsOff" is suggestive of this, as is the inconsistent "newstate" vs "newState", and the "qualProd" vs "qualprod". It is also clear from other clues (such as the selector names in the games themselves) that the method name should be "changeState" and that "newroom" should be "newRoom". The "curroom" should likewise be "curRoom", since we've seen from in-game code generation tools that this should be curRoom. And there's a couple of others like that as well. All in all, it seems quite clear that this was not simply a copy and paste from working game source code. It has all the marks of an inaccurate copying process, be it by human hand, or perhaps by OCR. What does it tell us though?
|