-- CreateBeads5.mesa
-- put in long pointers

-- dd etc
-- two backfacing transistors!

DIRECTORY IODefs:FROM"IODefs",
BeadsDefs:FROM"BeadsDefs",
InlineDefs:FROM"InlineDefs",
SystemDefs:FROM"SystemDefs",
StringDefs:FROM"StringDefs",
StreamDefs:FROM"StreamDefs";
CreateBeads:PROGRAM
IMPORTS InlineDefs,SystemDefs,StringDefs,StreamDefs,IODefs,BeadsDefs
EXPORTS BeadsDefs =
BEGIN OPEN BeadsDefs;

Error:SIGNAL=CODE;
IllegalInput:SIGNAL=CODE;

someBead:CARDINAL=noBead+1;

PackedInput:TYPE=RECORD[a:[0..17B],b:[0..7777B]];
PackedBytes:TYPE=RECORD[a,b:Byte];
Byte:TYPE=[0..256);
pieces:PackedBytes;
right:BOOLEAN;
altoYMax:CARDINAL=1000;
inputStream:StreamDefs.DiskHandle;

allSticks:POINTER TO StickStuff;
topStick:CARDINAL;
xLo,yLo,xHi,yHi:[0..10000];
stickScaling:CARDINAL=20;

--allContacts:ConStuff;
--topContact:CARDINAL←0;

getWhatYouSee:PUBLIC BOOLEAN;

--BeadType:TYPE={none,all,rg,rb,bg,tt,dd,ttV,ddV,endG,endR,endB,stub,
-- jctn,jctnR,jctnB,bf,wireG,wireR,wireB,wireO,of};

typeFromColor:ARRAY Color OF ARRAY Color OF BeadType←[
[none,endR,endB,endG,endR,endO],
[none,jctnR,rb,rg,jctnR,endO],
[none,rb,jctnB,bg,rb,endO],
[none,rg,bg,jctnG,rg,endO],
[none,jctnR,rb,rg,jctnR,endO],
[none,endO,endO,endO,endO,endO]];

ColorToLevel:ARRAY Color OF CARDINAL←[0,1,2,1,1,3];
--none,red,blue,green,yellow,orange
ColorToType:ARRAY Color OF ARRAY Color OF BeadType←--1st guy horizontal
[[none ,none ,none ,none ,none ,none],
[none ,jctnR,none , ttV ,jctnR, endO ],
[none ,none ,jctnB,none ,none , endO ],
[none , tt ,none ,jctnG, dd , endO ],
[none ,jctnR,none , ddV ,jctnR, endO ],
[none, endO , endO , endO , endO , endO ]];

-- Code: jctn,jctnR,jctnB,rb,bg,rg,all,other
TwoCodes:ARRAY [0..5] OF ARRAY [0..5] OF BeadType←[
[jctnG, rg , bg , all , bg , rg ],
[ rg ,jctnR, rb , rb , all , rg ],
[ bg , rb ,jctnB, rb , bg , all ],
[ all , rb , rb , rb , all , all ],
[ bg , all , bg , all , bg , all ],
[ rg , rg , all , all , all , rg ]];
inTry:CARDINAL;


FromInputToBeads:PUBLIC PROCEDURE[fileName:STRING,pr:BOOLEAN]=BEGIN
i:CARDINAL;
allSticks←SystemDefs.AllocateSegment[SIZE[StickStuff]];
StringDefs.AppendString[fileName,".stick"];
FromSilFileToSticks[fileName];
fileName.length←fileName.length-6;
IF pr THEN PrintAllSticks[allSticks,topStick];
FindBoundsOfStickDiagram[];
IF getWhatYouSee THEN BEGIN
FOR i IN [0..topStick] DO WhatYouSeeIsWhatYouGet[i]; ENDLOOP;
EliminateNulls[];
END;
IF pr THEN PrintAllSticks[allSticks,topStick];
FOR i IN [0..topStick] DO MakeCloseTeeJctnsTouch[i]; ENDLOOP;
IF pr THEN PrintAllSticks[allSticks,topStick];
CompressStickCoordinates[];
IF pr THEN PrintAllSticks[allSticks,topStick];
FOR i IN [0..topStick] DO PutTeeJctnsInBeadTable[i]; ENDLOOP;
IF pr THEN PrintBeads[];
FOR i IN [0..topStick] DO PutCrossingsInBeadTable[i]; ENDLOOP;
IF pr THEN PrintBeads[];
FOR i IN [0..topStick] DO IF allSticks[i].color=y THEN allSticks[i].color←r; ENDLOOP;
FOR i IN [0..topBead] DO Get[i].beadT←noBead; ENDLOOP;
FOR i IN [0..topBead] DO ConvertMultipleLevelsToTiedBeads[i]; ENDLOOP;
IF pr THEN PrintBeads[];
FOR i IN [0..topBead] DO DoesBeadHaveNeighbors[i]; ENDLOOP;
FOR i IN [0..topBead] DO RecordBeadsNeighbors[i]; ENDLOOP;
IF pr THEN PrintBeads[];
FOR i IN [0..topBead] DO StickToBeadCoordinates[i]; ENDLOOP;
IF pr THEN PrintBeads[];
FOR i IN [0..topBead] DO WiggleTiedBeadsUpAndDown[i]; ENDLOOP;
IF pr THEN PrintBeads[];
FOR i IN [0..topBead] DO Get[i].wire←FALSE; ENDLOOP;
FOR i IN [0..topBead] DO AddWires[i]; ENDLOOP;
IF pr THEN PrintBeads[];
FOR i IN [0..topBead] DO SetHeightAndWidth[i]; ENDLOOP;
FOR i IN [0..topBead] DO CorrectWireLength[i]; ENDLOOP;
IF pr THEN PrintBeads[];
MakeCircuits[];
FOR i IN [0..topBead] DO SetTypeConstants[i]; ENDLOOP;
SystemDefs.FreeSegment[allSticks];
WriteOneNumber["size of stick table= ",topStick];
END;

FromSilFileToSticks:PROCEDURE[inName:STRING]=BEGIN
a,i:CARDINAL; m:PackedInput;
s,x,y,xMax,yMax,f:CARDINAL; string:STRING←[100]; c:Color;
inTry←0;
inputStream←StreamDefs.NewWordStream[inName,StreamDefs.Read];
a←RW[]; SELECT a FROM 34562B,34563B=>NULL; ENDCASE=>Error;
topStick←0;
UNTIL inputStream.endof[inputStream] DO
IF (a←RW[])#177777B THEN Error; -- type non-macro
m←LOOPHOLE[RW[]]; x←m.b;
yMax←altoYMax-RW[]; IF yMax>altoYMax THEN Error;
m←LOOPHOLE[RW[]]; xMax←m.b;
c←SELECT m.a FROM 1=>r, 2=>y, 3=>g, 4=>b, 9=>o, ENDCASE=>none;
--black,red,yellow,green,cyan,violet,magenta,white,
--brown,orange,lime,turquoise,aqua,ultraviolet,pink,smoke
m←LOOPHOLE[RW[]]; f←m.a; y←altoYMax-m.b; IF y>3777B THEN Error;
IF f<=13 THEN BEGIN
s←RB[];
FOR i IN [0..s) DO string[i]←LOOPHOLE[RB[],CHARACTER]; ENDLOOP;
END;
IF c#none AND f=14 THEN BEGIN
w:CARDINAL←xMax-x;
h:CARDINAL←yMax-y;
allSticks[topStick]←IF h>w THEN [v,c,x+w/2,y,yMax]
ELSE [h,c,x,y+h/2,xMax];
topStick←topStick+1;
IF topStick>maxStick THEN Error;
END;

--process exception stuff

ENDLOOP;
topStick←topStick-1;
inputStream.destroy[inputStream];
END;
-- ///////////////
FindBoundsOfStickDiagram:PROCEDURE=BEGIN i:CARDINAL;
xLo←yLo←10000;
xHi←yHi←0;
FOR i IN [0..topStick] DO IF allSticks[i].color#none THEN BEGIN
is:Stick←allSticks[i];
IF is.dir=h THEN SetLoHi[is.x,is.y-4,is.end,is.y+4]
ELSE SetLoHi[is.x-4,is.y,is.x+4,is.end];
END; ENDLOOP;
END;

SetLoHi:PROCEDURE[a,b,c,d:INTEGER]=BEGIN
IF a<xLo THEN xLo←a;
IF b<yLo THEN yLo←b;
IF c>xHi THEN xHi←c;
IF d>yHi THEN yHi←d;
END;
-- ///////////////
WhatYouSeeIsWhatYouGet:PROCEDURE[i:CARDINAL]=BEGIN
is:Stick←allSticks[i];
j:CARDINAL; js:Stick;
IF is.dir=h THEN FOR j IN (i..topStick] DO
js←allSticks[j];
IF js.dir=h AND is.color=js.color AND is.y=js.y AND js.x<=is.end
AND js.end>=is.x THEN BEGIN
js.x←MIN[is.x,js.x];
js.end←MAX[is.end,js.end];
allSticks[i].color←none;
EXIT;
END;
IF js.dir=h AND (is.color=r AND js.color=g OR is.color=g AND js.color=r)
AND is.y=js.y AND js.x<is.end
AND js.end>is.x THEN BEGIN--should complain if vert wire nearby
SELECT TRUE FROM
is.x>=js.x AND is.end<=js.end => allSticks[i].color←none;
js.x>=is.x AND js.end<=is.end => allSticks[j].color←none;
is.x>js.x => js.end←is.x;
ENDCASE=>is.end←js.x;
EXIT;
END;
ENDLOOP
ELSE FOR j IN (i..topStick] DO
js←allSticks[j];
IF js.dir=v AND is.color=js.color AND is.x=js.x AND js.y<=is.end
AND js.end>=is.y THEN BEGIN
js.y←MIN[is.y,js.y];
js.end←MAX[is.end,js.end];
allSticks[i].color←none;
EXIT;
END;
IF js.dir=v AND (is.color=r AND js.color=g OR is.color=g AND js.color=r)
AND is.x=js.x AND js.y<is.end
AND js.end>is.y THEN BEGIN--should complain if vert wire nearby
SELECT TRUE FROM
is.y>=js.y AND is.end<=js.end => allSticks[i].color←none;
js.y>=is.y AND js.end<=is.end => allSticks[j].color←none;
is.y>js.y => js.end←is.y;
ENDCASE=>is.end←js.y;
EXIT;
END;
ENDLOOP;
END;

EliminateNulls:PROCEDURE=BEGIN
i:CARDINAL←0;
UNTIL i=topStick DO
IF allSticks[i].color=none
THEN allSticks[i]←allSticks[(topStick←topStick-1)+1]
ELSE i←i+1;
ENDLOOP;
END;
-- ///////////////
MakeCloseTeeJctnsTouch:PROCEDURE[i:CARDINAL]=BEGIN j:CARDINAL;
is:Stick←allSticks[i];
IF is.color=none THEN RETURN;
IF Close[is.x,xLo] THEN is.x←xLo;
IF Close[is.y,yLo] THEN is.y←yLo;
IF is.dir=h THEN IF CloseS[is.end,xHi] THEN is.end←xHi ELSE NULL
ELSE IF CloseS[is.end,yHi] THEN is.end←yHi ELSE NULL;
FOR j IN [0..topStick] DO IF i#j THEN BEGIN
js:Stick←allSticks[j];
IF is.dir=js.dir THEN BEGIN
IF is.dir=h AND CloseS[is.y,js.y] AND is.y#js.y
AND (WithinS[is.end,js.x,js.end] OR WithinS[is.x,js.x,js.end])
THEN Error;
IF is.dir=v AND CloseS[is.x,js.x] AND is.x#js.x
AND (WithinS[is.end,js.y,js.end] OR WithinS[is.y,js.y,js.end])
THEN Error;
END
ELSE BEGIN
IF is.dir=h AND WithinS[is.y,js.y,js.end] THEN BEGIN
IF CloseS[is.x,js.x] THEN is.x←js.x;
IF CloseS[is.end,js.x] THEN is.end←js.x;
END;
IF is.dir=v AND WithinS[is.x,js.x,js.end] THEN BEGIN
IF CloseS[is.y,js.y] THEN is.y←js.y;
IF CloseS[is.end,js.y] THEN is.end←js.y;
END;
END;
END; ENDLOOP;
allSticks[i]←is;
END;
-- ///////////////
CompressStickCoordinates:PROCEDURE=BEGIN i:CARDINAL;
s,ad,c:INTEGER;
s←0;
FOR c IN [xLo..xHi] DO
ad←IF c=xLo OR c=xHi THEN 1 ELSE 0;
FOR i IN [0..topStick] DO
IF allSticks[i].x=c THEN BEGIN allSticks[i].x←s; ad←1; END;
IF allSticks[i].end=c AND allSticks[i].dir=h
THEN BEGIN allSticks[i].end←s; ad←1; END;
ENDLOOP;
s←s+ad;
ENDLOOP;
xLo←0; xHi←s-1;
s←0;
FOR c IN [yLo..yHi] DO
ad←IF c=xLo OR c=xHi THEN 1 ELSE 0;
FOR i IN [0..topStick] DO
IF allSticks[i].y=c THEN BEGIN allSticks[i].y←s; ad←1; END;
IF allSticks[i].end=c AND allSticks[i].dir=v
THEN BEGIN allSticks[i].end←s; ad←1; END;
ENDLOOP;
s←s+ad;
ENDLOOP;
yLo←0; yHi←s-1;
END;

-- ///////////////
PutTeeJctnsInBeadTable:PROCEDURE[i:CARDINAL]=BEGIN is:Stick←allSticks[i];
IF is.color=none THEN RETURN;
SeeIfButts[is.x,is.y,i];
IF is.dir=h THEN SeeIfButts[is.end,is.y,i] ELSE SeeIfButts[is.x,is.end,i];
END;

SeeIfButts:PROCEDURE[x,y:INTEGER,i:CARDINAL]=BEGIN j:CARDINAL;
ic:Color←allSticks[i].color;
IF Close[x,xHi] OR Close[x,xLo] OR Close[y,yHi] OR Close[y,yLo]
THEN Cc[x,y,none,ic]
ELSE FOR j IN [0..topStick] DO IF i#j THEN BEGIN
js:Stick←allSticks[j];
IF js.dir=h AND Close[y,js.y] AND Within[x,js.x,js.end]
OR js.dir=v AND Close[x,js.x] AND Within[y,js.y,js.end]
THEN Cc[x,y,ic,js.color];
END; ENDLOOP;
END;
-- ///////////////
PutCrossingsInBeadTable:PROCEDURE[i:CARDINAL]=BEGIN j:CARDINAL;
is:Stick←allSticks[i];
IF is.color=none THEN RETURN;
FOR j IN [0..topStick] DO BEGIN
js:Stick←allSticks[j];
IF is.dir=h AND js.dir=v AND is.y IN (js.y..js.end)
AND js.x IN (is.x..is.end)
THEN BEGIN
type:BeadType←ColorToType[is.color][js.color];
IF type#none THEN InsertContact[js.x,is.y,type];
END;
END; ENDLOOP;
END;
-- ///////////////
ConvertMultipleLevelsToTiedBeads:PROCEDURE[i:CARDINAL]= BEGIN
bpi:BeadPtr←Get[i];
bpt1,bpt2:BeadPtr;
SELECT bpi.t FROM
rg,all=>BEGIN
InsertBead[bpi↑];
bpt1←Get[topBead];
InsertBead[bpi↑];
bpt2←Get[topBead];
bpt1.t←rb; bpt1.beadT←topBead;
bpt2.t←bf; bpt2.beadT←i;
bpi .t←bg; bpi .beadT←topBead-1;
END;
rb=>BEGIN
InsertBead[bpi↑];
bpt1←Get[topBead];
bpt1.beadT←i;
bpt1.t←bf;
bpi.beadT←topBead;
bpi.external←bpt1.external←2;
END;
bg=>BEGIN
InsertBead[bpi↑];
bpt1←Get[topBead];
bpt1.beadT←i;
bpt1.t←bf;
bpi.beadT←topBead;
bpi.external←bpt1.external←2;
END;
ENDCASE;
END;
-- ///////////////
DoesBeadHaveNeighbors:PROCEDURE[i:CARDINAL]=BEGIN j:CARDINAL;
bpi:BeadPtr←Get[i];
bpi.beadR←bpi.beadL←bpi.beadU←bpi.beadD←noBead;
FOR j IN [0..topStick] DO BEGIN js:Stick←allSticks[j];
IF SELECT js.color FROM
r,y=>SELECT bpi.t FROM all,jctnR,rg,rb,tt,ttV,dd,ddV,endR=>TRUE,
ENDCASE=>FALSE,
g=> SELECT bpi.t FROM all,jctnG,rg,bg,tt,ttV,dd,ddV,endG=>TRUE,
ENDCASE=>FALSE,
b=> SELECT bpi.t FROM all,jctnB,endB,bf=>TRUE, ENDCASE=>FALSE,
ENDCASE=>FALSE THEN BEGIN
IF js.dir=h AND bpi.y=js.y THEN BEGIN
IF bpi.x IN [js.x..js.end) THEN bpi.beadR←someBead;
IF bpi.x IN (js.x..js.end] THEN bpi.beadL←someBead;
END;
IF js.dir=v AND bpi.x=js.x THEN BEGIN
IF bpi.y IN [js.y..js.end) THEN bpi.beadU←someBead;
IF bpi.y IN (js.y..js.end] THEN bpi.beadD←someBead;
END;
END;
END; ENDLOOP;
END;
-- ///////////////
RecordBeadsNeighbors:PROCEDURE[i:CARDINAL]=BEGIN j:CARDINAL;
bpi:BeadPtr←Get[i];
bpa:BeadPtr;
Find:PROCEDURE[q:CARDINAL] RETURNS[aBead:CARDINAL]=BEGIN
min:BOOLEAN←q=0 OR q=2;
ext:INTEGER←IF min THEN 10000 ELSE 0;
aBead←noBead;
FOR j IN [0..topBead] DO BEGIN
bpj:BeadPtr←Get[j];
sameX:BOOLEAN;
jx:INTEGER←bpj.x; jy:INTEGER←bpj.y;
ay,by:INTEGER;
IF q<2 THEN BEGIN ay←jy; by←bpi.y; sameX←(jx=bpi.x); END
ELSE BEGIN ay←jx; by←bpi.x; sameX←(jy=bpi.y); END;
IF sameX
AND (IF min THEN ay IN (by..ext] ELSE ay IN [ext..by))
AND (IF q<2 THEN desP[bpi.t].bitPerLevelV=desP[bpj.t].bitPerLevelV
ELSE desP[bpi.t].bitPerLevel=desP[bpj.t].bitPerLevel)
THEN BEGIN ext←ay; aBead←j; END;
END; ENDLOOP;
bpa←Get[aBead];
IF noBead=(SELECT q FROM 0=>bpa.beadD, 1=>bpa.beadU,
2=>bpa.beadL, ENDCASE=>bpa.beadR)
THEN aBead←noBead;
END;
IF bpi.beadU=someBead THEN bpi.beadU←Find[0];
IF bpi.beadD=someBead THEN bpi.beadD←Find[1];
IF bpi.beadR=someBead THEN bpi.beadR←Find[2];
IF bpi.beadL=someBead THEN bpi.beadL←Find[3];
END;
-- ///////////////
StickToBeadCoordinates:PROCEDURE[i:CARDINAL]=BEGIN
bpi:BeadPtr←Get[i];
m:CARDINAL←bpi.x; n:CARDINAL←bpi.y;
bpi.x←m*stickScaling; bpi.y←n*stickScaling;
END;
-- ///////////////
WiggleTiedBeadsUpAndDown:PROCEDURE[i:CARDINAL]= BEGIN
New:TYPE=RECORD[rx,ry,gx,gy,bx,by:INTEGER];
bpi:BeadPtr←Get[i];
IF bpi.t=bg AND Get[bpi.beadT].t=rb THEN BEGIN
green:CARDINAL=i;
red:CARDINAL←bpi.beadT;
blue:CARDINAL←Get[red].beadT;
bpg:BeadPtr←Get[green];
bpr:BeadPtr←Get[red];
bpb:BeadPtr←Get[blue];
IF bpb.t#bf OR bpb.beadT#green THEN Error;
BEGIN
lc:Color←IF bpg.beadL#noBead THEN g
ELSE IF bpr.beadL#noBead THEN r ELSE none;
rc:Color←IF bpg.beadR#noBead THEN g
ELSE IF bpr.beadR#noBead THEN r ELSE none;
uc:Color←IF bpg.beadU#noBead THEN g
ELSE IF bpr.beadU#noBead THEN r ELSE none;
dc:Color←IF bpg.beadD#noBead THEN g
ELSE IF bpr.beadD#noBead THEN r ELSE none;
new:New;
IF bpr.beadL#noBead AND bpg.beadL#noBead THEN IllegalInput;
IF bpr.beadR#noBead AND bpg.beadR#noBead THEN IllegalInput;
IF bpr.beadU#noBead AND bpg.beadU#noBead THEN IllegalInput;
IF bpr.beadD#noBead AND bpg.beadD#noBead THEN IllegalInput;
new←SELECT TRUE FROM --
There has got to be a better way!
lc=g AND rc=g AND uc=r =>[0,6,0, 0,0, 0],
lc=g AND rc=g =>[0,-6,0,0,0,-6],
lc=r AND rc=r AND uc=g =>[0,0,0, 6,0, 0],
lc=r AND rc=r =>[0,0,0,-6,0,-6],
uc=g AND dc=g AND lc=r =>[-6,0,0,0,-6,0],
uc=g AND dc=g =>[ 6,0,0,0, 0,0],
uc=r AND dc=r AND lc=g =>[0,0,-6,0,-6,0],
uc=r AND dc=r =>[0,0,6,0, 0, 0],
lc#g AND rc#g AND uc=g =>[0,0,0, 6,0, 0],
lc#g AND rc#g =>[0,0,0,-6,0,-6],
lc#r AND rc#r AND uc=r =>[0, 6,0,0,0, 0],
lc#r AND rc#r =>[0,-6,0,0,0,-6],
uc#g AND dc#g AND rc=g =>[0,0, 6,0, 0,0],
uc#g AND dc#g =>[0,0,-6,0,-6,0],
uc#r AND dc#r AND rc=r =>[ 6,0,0,0, 0,0],
ENDCASE => [-6,0,0,0,-6,0];
bpr.x←bpr.x+new.rx;
bpg.x←bpg.x+new.gx;
bpb.x←bpb.x+new.bx;
bpr.y←bpr.y+new.ry;
bpg.y←bpg.y+new.gy;
bpb.y←bpb.y+new.by;
bpr.external← --1 means 6hx8w--
bpg.external← --1 means 6hx8w--
bpb.external←IF new.ry#0 OR new.gy#0 THEN 1 ELSE 0;
--1 means 12hx8w--
END;
END;
END;
-- ///////////////
AddWires:PROCEDURE[i:CARDINAL]=BEGIN k:CARDINAL;
bi:BeadPtr←Get[i];
bpk,bpt:BeadPtr;
IF (k←bi.beadR)#noBead THEN BEGIN
bpk←Get[k];
IF (topBead←topBead+1) NOT IN [0..noBead) THEN ERROR;
bpt←Get[topBead];
bpt.y←bi.y+10-((bi.y+10) MOD 20);
bpt.beadU←bpt.beadD←bpt.beadT←noBead;
bpt.beadL←i;
bpt.beadR←k;
bpt.t←desP[bi.t].rwc;
bpt.external←0;
bi.beadR←bpk.beadL←topBead;
SetTypeConstants[topBead];
END;
IF (k←bi.beadU)#noBead THEN BEGIN
bpk←Get[k];
IF (topBead←topBead+1) NOT IN [0..noBead) THEN ERROR;
bpt←Get[topBead];
bpt.x←bi.x+10-((bi.x+10) MOD 20);
bpt.beadL←bpt.beadR←bpt.beadT←noBead;
bpt.beadD←i;
bpt.beadU←k;
bpt.t←desP[bi.t].uwc;
bpt.external←0;
bi.beadU←bpk.beadD←topBead;
SetTypeConstants[topBead];
END;
END;

-- ///////////////

SetHeightAndWidth:PROCEDURE[i:CARDINAL]=BEGIN
bpi:BeadPtr←Get[i];
type:BeadType←bpi.t;
bpi.h←desP[type].h;
bpi.w←desP[type].w;
SELECT type FROM-- ext=0,1,or2
bf=>BEGIN
bpi.h←IF bpi.external=1 THEN 12 ELSE 8;
bpi.w←IF bpi.external=0 THEN 12 ELSE 8;
END;
bg,rb=>BEGIN
bpi.h←IF bpi.external=1 THEN 6 ELSE 8;
bpi.w←IF bpi.external=0 THEN 6 ELSE 8;
END;
ENDCASE;
END;

CorrectWireLength:PROCEDURE[i:CARDINAL]=BEGIN
bpi:BeadPtr←Get[i];
IF bpi.wire THEN BEGIN
one,other:CARDINAL;
t:INTEGER;
type:BeadType←bpi.t;
IF bpi.beadU=noBead THEN BEGIN
one←bpi.beadL;
other←bpi.beadR;
t←bpi.x←Get[one].x+Get[one].w;
bpi.w←Get[other].x-t;
END
ELSE BEGIN
one←bpi.beadD;
other←bpi.beadU;
t←bpi.y←Get[one].y+Get[one].h;
bpi.h←Get[other].y-t;
END;
END;
END;
-- ///////////////
MakeCircuits:PUBLIC PROCEDURE=BEGIN i:CARDINAL; k:INTEGER←-1;
FOR i IN [0..topBead] DO Get[i].circuit←noBead; ENDLOOP;
FOR i IN [0..topBead]
DO BEGIN foo:CARDINAL←Get[i].circuit;
IF foo=noBead THEN SetCircuit[i,k←k+1];
END;
ENDLOOP;
END;

SetCircuit:PROCEDURE[i:CARDINAL,k:INTEGER]=BEGIN
bpi:BeadPtr←Get[i];
foo:CARDINAL←bpi.circuit;
IF i=noBead OR foo#noBead THEN RETURN;
bpi.circuit←k;
SELECT bpi.t FROM tt,dd=>NULL;
ENDCASE=>BEGIN
TryCircuitH[bpi.beadL,k]; TryCircuitH[bpi.beadR,k]; END;
SELECT bpi.t FROM ttV,ddV=>NULL;
ENDCASE=>BEGIN
TryCircuitV[bpi.beadU,k]; TryCircuitV[bpi.beadD,k]; END;
SetCircuit[bpi.beadT,k];
END;

TryCircuitH:PROCEDURE[m:CARDINAL,k:INTEGER]=
BEGIN SELECT Get[m].t FROM tt,dd=>NULL; ENDCASE=>SetCircuit[m,k]; END;

TryCircuitV:PROCEDURE[m:CARDINAL,k:INTEGER]=
BEGIN SELECT Get[m].t FROM ttV,ddV=>NULL; ENDCASE=>SetCircuit[m,k]; END;

-- ///////////////


Cc:PROCEDURE[x,y:INTEGER,ic,jc:Color]=BEGIN
InsertContact[x,y,typeFromColor[ic][jc]]; END;

InsertContact:PROCEDURE[x,y:INTEGER,type:BeadType]=BEGIN i:CARDINAL;
bpi,bpt:BeadPtr;
IF type=none THEN RETURN;
IF topBead#177777B THEN FOR i IN [0..topBead] DO
bpi←Get[i];
IF Close[x,bpi.x] AND Close[y,bpi.y]
THEN BEGIN bpi.t←CombineTypes[bpi.t,type]; RETURN; END;
ENDLOOP;
topBead←topBead+1;
IF topBead>noBead THEN Error;
bpt←Get[topBead];
bpt.x←x;
bpt.y←y;
bpt.t←type;
bpt.external←0;
END;

CombineTypes:PROCEDURE[s,t:BeadType] RETURNS[BeadType]=BEGIN
s1:CARDINAL←desP[s].toCode;
t1:CARDINAL←desP[t].toCode;
IF s1>6 OR t1>6 THEN Error;
RETURN[IF s1=6 OR t1=6 THEN all ELSE TwoCodes[s1][t1]];
END;

InsertBead:PUBLIC PROCEDURE[b:Bead]=BEGIN
IF (topBead←topBead+1) NOT IN [0..noBead) THEN ERROR;
Get[topBead]↑←b;
SetTypeConstants[topBead];
END;

SetTypeConstants:PUBLIC PROCEDURE[i:CARDINAL]=BEGIN
bpi:BeadPtr←Get[i];
IF i NOT IN [0..noBead) THEN ERROR;
bpi.wire←SELECT bpi.t FROM wireG,wireR,wireB,wireO=>TRUE, ENDCASE=>FALSE;
END;

CheckBeads:PUBLIC PROCEDURE=BEGIN
i,k:CARDINAL;
FOR i IN [0..topBead] DO BEGIN
bpi:BeadPtr←Get[i];
bpk:BeadPtr;
IF (k←bpi.beadR)#noBead THEN BEGIN
bpk←Get[k];
IF bpk.beadL#i THEN Error;
IF bpi.x+bpi.w#bpk.x THEN Error;
END;
IF (k←bpi.beadU)#noBead THEN BEGIN
bpk←Get[k];
IF bpk.beadD#i THEN Error;
IF bpi.y+bpi.h#bpk.y THEN Error;
END;
END; ENDLOOP;
END;

TwoClose:PROCEDURE[a,b,c:INTEGER] RETURNS[BOOLEAN]=
BEGIN RETURN[Close[a,b] OR Close[a,c]]; END;

Close:PROCEDURE[a,b:INTEGER] RETURNS[BOOLEAN]=BEGIN RETURN[a=b]; END;

Within:PROCEDURE[a,b,c:INTEGER] RETURNS[BOOLEAN]=
BEGIN RETURN[a IN [b..c]]; END;

CloseS:PROCEDURE[a,b:INTEGER] RETURNS[BOOLEAN]=
BEGIN RETURN[a-b IN [-1..1]]; END;

WithinS:PROCEDURE[a,b,c:INTEGER] RETURNS[BOOLEAN]=
BEGIN RETURN[a IN [b-1..c+1]]; END;

RW:PROCEDURE RETURNS[CARDINAL]=
BEGIN right←FALSE; RETURN[inputStream.get[inputStream]]; END;

RB:PROCEDURE RETURNS[Byte]=BEGIN
IF right THEN pieces.a←pieces.b ELSE pieces←LOOPHOLE[RW[]];
right←~right; RETURN[pieces.a]; END;

KeepMesaHappy:PROCEDURE=BEGIN IODefs.WriteChar[’ ]; END;

END..