C SYNMCH-- SYNTAX MATCHER C C COPYRIGHT 1980, INFOCOM COMPUTERS AND COMMUNICATIONS, CAMBRIDGE MA. 02142 C ALL RIGHTS RESERVED, COMMERCIAL USAGE STRICTLY PROHIBITED C WRITTEN BY R. M. SUPNIK C C DECLARATIONS C C THIS ROUTINE DETAILS ON BIT 4 OF PRSFLG C LOGICAL FUNCTION SYNMCH IMPLICIT INTEGER(A-Z) LOGICAL SYNEQL,TAKEIT,DFLAG C C PARSER OUTPUT C LOGICAL PRSWON COMMON /PRSVEC/ PRSA,PRSI,PRSO,PRSWON,PRSCON C COMMON /DEBUG/ DBGFLG,PRSFLG C COMMON /ORPHS/ OFLAG,OACT,OSLOT,OPREP,ONAME COMMON /PV/ ACT,O1,O2,P1,P2 COMMON /SYNTAX/VFLAG,DOBJ,DFL1,DFL2,DFW1,DFW2, 1 IOBJ,IFL1,IFL2,IFW1,IFW2 COMMON /VRBVOC/ VVOC(950) COMMON /SYNFLG/ SDIR,SIND,SSTD,SFLIP,SDRIV,SVMASK COMMON /OBJFLG/ VABIT,VRBIT,VTBIT,VCBIT,VEBIT,VFBIT,VPMASK DATA R50MIN/1RA/ C SYNMCH=.FALSE. D DFLAG=(PRSFLG.AND."20).NE.0 J=ACT !SET UP PTR TO SYNTAX. DRIVE=0 !NO DEFAULT. DFORCE=0 !NO FORCED DEFAULT. QPREP=OFLAG.AND.OPREP !VALID ORPHAN PREP FLAG. 100 J=J+2 !FIND START OF SYNTAX. IF((VVOC(J).LE.0).OR.(VVOC(J).GE.R50MIN)) GO TO 100 LIMIT=J+VVOC(J)+1 !COMPUTE LIMIT. J=J+1 !ADVANCE TO NEXT. C 200 CALL UNPACK(J,NEWJ) !UNPACK SYNTAX. D IF(DFLAG) TYPE 60,O1,P1,DOBJ,DFL1,DFL2 D60 FORMAT(' SYNMCH INPUTS TO SYNEQL- ',5I7) SPREP=DOBJ.AND.VPMASK !SAVE EXPECTED PREP. IF(.NOT.SYNEQL(P1,O1,DOBJ,DFL1,DFL2)) GO TO 1000 D IF(DFLAG) TYPE 60,O2,P2,IOBJ,IFL1,IFL2 SPREP=IOBJ.AND.VPMASK !SAVE EXPECTED PREP. IF(SYNEQL(P2,O2,IOBJ,IFL1,IFL2)) GO TO 6000 C C SYNTAX MATCH FAILS, TRY NEXT ONE. C IF(O2) 3000,500,3000 !IF O2=0, SET DFLT. 1000 IF(O1) 3000,500,3000 !IF O1=0, SET DFLT. 500 IF((QPREP.EQ.0).OR.(QPREP.EQ.SPREP)) DFORCE=J !IF PREP MCH. IF((VFLAG.AND.SDRIV).NE.0) DRIVE=J !IF DRIVER, RECORD. 3000 J=NEWJ IF(J.LT.LIMIT) GO TO 200 !MORE TO DO? C SYNMCH, PAGE 2 C C MATCH HAS FAILED. IF DEFAULT SYNTAX EXISTS, TRY TO SNARF C ORPHANS OR GWIMS, OR MAKE NEW ORPHANS. C D IF(DFLAG) TYPE 20,DRIVE,DFORCE D20 FORMAT(' SYNMCH, DRIVE=',2I6) IF(DRIVE.EQ.0) DRIVE=DFORCE !NO DRIVER? USE FORCE. IF(DRIVE.EQ.0) GO TO 10000 !ANY DRIVER? CALL UNPACK(DRIVE,DFORCE) !UNPACK DFLT SYNTAX. C C TRY TO FILL DIRECT OBJECT SLOT IF THAT WAS THE PROBLEM. C IF(((VFLAG.AND.SDIR).EQ.0).OR.(O1.NE.0)) GO TO 4000 C C FIRST TRY TO SNARF ORPHAN OBJECT. C O1=OFLAG.AND.OSLOT IF(O1.EQ.0) GO TO 3500 !ANY ORPHAN? IF(SYNEQL(P1,O1,DOBJ,DFL1,DFL2)) GO TO 4000 C C ORPHAN FAILS, TRY GWIM. C 3500 O1=GWIM(DOBJ,DFW1,DFW2) !GET GWIM. D IF(DFLAG) TYPE 30,O1 D30 FORMAT(' SYNMCH- DO GWIM= ',I6) IF(O1.GT.0) GO TO 4000 !TEST RESULT. CALL ORPHAN(-1,ACT,0,DOBJ.AND.VPMASK,0) !FAILS, ORPHAN. CALL RSPEAK(623) RETURN C C TRY TO FILL INDIRECT OBJECT SLOT IF THAT WAS THE PROBLEM. C 4000 IF(((VFLAG.AND.SIND).EQ.0).OR.(O2.NE.0)) GO TO 6000 O2=GWIM(IOBJ,IFW1,IFW2) !GWIM. D IF(DFLAG) TYPE 40,O2 D40 FORMAT(' SYNMCH- IO GWIM= ',I6) IF(O2.GT.0) GO TO 6000 IF(O1.EQ.0) O1=OFLAG.AND.OSLOT CALL ORPHAN(-1,ACT,O1,DOBJ.AND.VPMASK,0) CALL RSPEAK(624) RETURN C C TOTAL CHOMP C 10000 CALL RSPEAK(601) !CANT DO ANYTHING. RETURN C SYNMCH, PAGE 3 C C NOW TRY TO TAKE INDIVIDUAL OBJECTS AND C IN GENERAL CLEAN UP THE PARSE VECTOR. C 6000 IF((VFLAG.AND.SFLIP).EQ.0) GO TO 5000 !FLIP? J=O1 !YES. O1=O2 O2=J C 5000 PRSA=VFLAG.AND.SVMASK !GET VERB. PRSO=O1 !GET DIR OBJ. PRSI=O2 !GET IND OBJ. IF(.NOT.TAKEIT(PRSO,DOBJ)) RETURN !TRY TAKE. IF(.NOT.TAKEIT(PRSI,IOBJ)) RETURN !TRY TAKE. SYNMCH=.TRUE. D IF(DFLAG) TYPE 50,SYNMCH,PRSA,PRSO,PRSI,ACT,O1,O2 D50 FORMAT(' SYNMCH- RESULTS ',L1,6I7) RETURN C END C UNPACK- UNPACK SYNTAX SPECIFICATION, ADV POINTER C C DECLARATIONS C SUBROUTINE UNPACK(OLDJ,J) IMPLICIT INTEGER(A-Z) C COMMON /VRBVOC/ VVOC(950) C COMMON /SYNFLG/ SDIR,SIND,SSTD,SFLIP,SDRIV,SVMASK COMMON /OBJFLG/ VABIT,VRBIT,VTBIT,VCBIT,VEBIT,VFBIT,VPMASK COMMON /SYNTAX/ VFLAG,DOBJ,DFL1,DFL2,DFW1,DFW2, 1 IOBJ,IFL1,IFL2,IFW1,IFW2 INTEGER SYN(11) EQUIVALENCE (SYN(1),VFLAG) C DO 10 I=1,11 !CLEAR SYNTAX. SYN(I)=0 10 CONTINUE C VFLAG=VVOC(OLDJ) J=OLDJ+1 IF((VFLAG.AND.SDIR).EQ.0) RETURN !DIR OBJECT? DFL1=-1 !ASSUME STD. DFL2=-1 IF((VFLAG.AND.SSTD).EQ.0) GO TO 100 !STD OBJECT? DFW1=-1 !YES. DFW2=-1 DOBJ=VABIT+VRBIT+VFBIT GO TO 200 C 100 DOBJ=VVOC(J) !NOT STD. DFW1=VVOC(J+1) DFW2=VVOC(J+2) J=J+3 IF((DOBJ.AND.VEBIT).EQ.0) GO TO 200 !VBIT = VFWIM? DFL1=DFW1 !YES. DFL2=DFW2 C 200 IF((VFLAG.AND.SIND).EQ.0) RETURN !IND OBJECT? IFL1=-1 !ASSUME STD. IFL2=-1 IOBJ=VVOC(J) IFW1=VVOC(J+1) IFW2=VVOC(J+2) J=J+3 IF((IOBJ.AND.VEBIT).EQ.0) RETURN !VBIT = VFWIM? IFL1=IFW1 !YES. IFL2=IFW2 RETURN C END C SYNEQL- TEST FOR SYNTAX EQUALITY C C DECLARATIONS C LOGICAL FUNCTION SYNEQL(PREP,OBJ,SPREP,SFL1,SFL2) IMPLICIT INTEGER(A-Z) C C OBJECTS C COMMON /OBJCTS/ OLNT,ODESC1(220),ODESC2(220),ODESCO(220), 1 OACTIO(220),OFLAG1(220),OFLAG2(220),OFVAL(220), 2 OTVAL(220),OSIZE(220),OCAPAC(220),OROOM(220), 3 OADV(220),OCAN(220),OREAD(220) C COMMON /OBJFLG/ VABIT,VRBIT,VTBIT,VCBIT,VEBIT,VFBIT,VPMASK C IF(OBJ.EQ.0) GO TO 100 !ANY OBJECT? SYNEQL=(PREP.EQ.(SPREP.AND.VPMASK)).AND. 1 (((SFL1.AND.OFLAG1(OBJ)).OR. 2 (SFL2.AND.OFLAG2(OBJ))).NE.0) RETURN C 100 SYNEQL=(PREP.EQ.0).AND.(SFL1.EQ.0).AND.(SFL2.EQ.0) RETURN C END C TAKEIT- PARSER BASED TAKE OF OBJECT C C DECLARATIONS C LOGICAL FUNCTION TAKEIT(OBJ,SFLAG) IMPLICIT INTEGER(A-Z) C COMMON /OBJFLG/ VABIT,VRBIT,VTBIT,VCBIT,VEBIT,VFBIT,VPMASK COMMON /STAR/ MBASE,STRBIT C C GAME STATE C LOGICAL TELFLG COMMON /PLAY/ WINNER,HERE,TELFLG COMMON /STATE/ MOVES,DEATHS,RWSCOR,MXSCOR,MXLOAD, 1 LTSHFT,BLOC,MUNGRM,HS,EGSCOR,EGMXSC C C OBJECTS C COMMON /OBJCTS/ OLNT,ODESC1(220),ODESC2(220),ODESCO(220), 1 OACTIO(220),OFLAG1(220),OFLAG2(220),OFVAL(220), 2 OTVAL(220),OSIZE(220),OCAPAC(220),OROOM(220), 3 OADV(220),OCAN(220),OREAD(220) C COMMON /OFLAGS/ VISIBT,READBT,TAKEBT,DOORBT,TRANBT,FOODBT, 1 NDSCBT,DRNKBT,CONTBT,LITEBT,VICTBT,BURNBT,FLAMBT, 2 TOOLBT,TURNBT,ONBT COMMON /OFLAGS/ FINDBT,SLEPBT,SCRDBT,TIEBT,CLMBBT,ACTRBT, 1 WEAPBT,FITEBT,VILLBT,STAGBT,TRYBT,NOCHBT,OPENBT, 2 TCHBT,VEHBT,SCHBT C C ADVENTURERS C COMMON /ADVS/ ALNT,AROOM(4),ASCORE(4),AVEHIC(4), 1 AOBJ(4),AACTIO(4),ASTREN(4),AFLAG(4) C TAKEIT, PAGE 2 C TAKEIT=.FALSE. !ASSUME LOSES. IF((OBJ.EQ.0).OR.(OBJ.GT.STRBIT)) GO TO 4000 !NULL/STARS WIN. ODO2=ODESC2(OBJ) !GET DESC. X=OCAN(OBJ) !GET CONTAINER. IF((X.EQ.0).OR.((SFLAG.AND.VFBIT).EQ.0)) GO TO 500 IF((OFLAG2(X).AND.OPENBT).NE.0) GO TO 500 CALL RSPSUB(566,ODO2) !CANT REACH. RETURN C 500 IF((SFLAG.AND.VRBIT).EQ.0) GO TO 1000 !SHLD BE IN ROOM? IF((SFLAG.AND.VTBIT).EQ.0) GO TO 2000 !CAN BE TAKEN? C C SHOULD BE IN ROOM (VRBIT NE 0) AND CAN BE TAKEN (VTBIT NE 0) C IF(SCHLST(0,0,HERE,0,0,OBJ).LE.0) GO TO 4000 !IF NOT, OK. C C ITS IN THE ROOM AND CAN BE TAKEN. C IF(((OFLAG1(OBJ).AND.TAKEBT).NE.0).AND. 1 ((OFLAG2(OBJ).AND.TRYBT).EQ.0)) GO TO 3000 C C NOT TAKEABLE. IF WE CARE, FAIL. C IF((SFLAG.AND.VCBIT).EQ.0) GO TO 4000 !IF NO CARE, RETURN. CALL RSPSUB(445,ODO2) RETURN C C 1000-- IT SHOULD NOT BE IN THE ROOM. C 2000-- IT CANT BE TAKEN. C 2000 IF((SFLAG.AND.VCBIT).EQ.0) GO TO 4000 !IF NO CARE, RETURN 1000 IF(SCHLST(0,0,HERE,0,0,OBJ).LE.0) GO TO 4000 CALL RSPSUB(665,ODO2) RETURN C TAKEIT, PAGE 3 C C OBJECT IS IN THE ROOM, CAN BE TAKEN BY THE PARSER, C AND IS TAKEABLE IN GENERAL. IT IS NOT A STAR. C TAKING IT SHOULD NOT HAVE SIDE AFFECTS. C IF IT IS INSIDE SOMETHING, THE CONTAINER IS OPEN. C THE FOLLOWING CODE IS LIFTED FROM SUBROUTINE TAKE. C 3000 IF(OBJ.NE.AVEHIC(WINNER)) GO TO 3500 !TAKE VEHICLE? CALL RSPEAK(672) RETURN C 3500 IF(((X.NE.0).AND.(OADV(X).EQ.WINNER)).OR. 1 ((WEIGHT(0,OBJ,WINNER)+OSIZE(OBJ)).LE.MXLOAD)) 2 GO TO 3700 CALL RSPEAK(558) !TOO BIG. RETURN C 3700 CALL NEWSTA(OBJ,559,0,0,WINNER) !DO TAKE. OFLAG2(OBJ)=OFLAG2(OBJ).OR.TCHBT !TOUCHED. CALL SCRUPD(OFVAL(OBJ)) OFVAL(OBJ)=0 C 4000 TAKEIT=.TRUE. !SUCCESS. RETURN C END C GWIM- GET WHAT I MEAN IN AMBIGOUS SITUATIONS C C DECLARATIONS C INTEGER FUNCTION GWIM(SFLAG,SFW1,SFW2) IMPLICIT INTEGER(A-Z) LOGICAL TAKEIT,NOCARE C COMMON /OBJFLG/ VABIT,VRBIT,VTBIT,VCBIT,VEBIT,VFBIT,VPMASK COMMON /STAR/ MBASE,STRBIT C C GAME STATE C LOGICAL TELFLG COMMON /PLAY/ WINNER,HERE,TELFLG C C OBJECTS C COMMON /OBJCTS/ OLNT,ODESC1(220),ODESC2(220),ODESCO(220), 1 OACTIO(220),OFLAG1(220),OFLAG2(220),OFVAL(220), 2 OTVAL(220),OSIZE(220),OCAPAC(220),OROOM(220), 3 OADV(220),OCAN(220),OREAD(220) C COMMON /OFLAGS/ VISIBT,READBT,TAKEBT,DOORBT,TRANBT,FOODBT, 1 NDSCBT,DRNKBT,CONTBT,LITEBT,VICTBT,BURNBT,FLAMBT, 2 TOOLBT,TURNBT,ONBT COMMON /OFLAGS/ FINDBT,SLEPBT,SCRDBT,TIEBT,CLMBBT,ACTRBT, 1 WEAPBT,FITEBT,VILLBT,STAGBT,TRYBT,NOCHBT,OPENBT, 2 TCHBT,VEHBT,SCHBT C C ADVENTURERS C COMMON /ADVS/ ALNT,AROOM(4),ASCORE(4),AVEHIC(4), 1 AOBJ(4),AACTIO(4),ASTREN(4),AFLAG(4) C GWIM, PAGE 2 C GWIM=-1 !ASSUME LOSE. AV=AVEHIC(WINNER) NOBJ=0 NOCARE=(SFLAG.AND.VCBIT).EQ.0 C C FIRST SEARCH ADVENTURER C IF((SFLAG.AND.VABIT).NE.0) 1 NOBJ=FWIM(SFW1,SFW2,0,0,WINNER,NOCARE) IF((SFLAG.AND.VRBIT).NE.0) GO TO 100 50 GWIM=NOBJ RETURN C C ALSO SEARCH ROOM C 100 ROBJ=FWIM(SFW1,SFW2,HERE,0,0,NOCARE) IF(ROBJ) 500,50,200 !TEST RESULT. C C ROBJ > 0 C 200 IF((AV.EQ.0).OR.(ROBJ.EQ.AV).OR. 1 ((OFLAG2(ROBJ).AND.FINDBT).NE.0)) GO TO 300 IF(OCAN(ROBJ).NE.AV) GO TO 50 !UNREACHABLE? TRY NOBJ 300 IF(NOBJ.NE.0) RETURN !IF AMBIGUOUS, RETURN. IF(.NOT.TAKEIT(ROBJ,SFLAG)) RETURN !IF UNTAKEABLE, RETURN GWIM=ROBJ 500 RETURN C END