StoreMark:
PUBLIC PROC [t: Tile, m: Mark] =
BEGIN
length: INT ← Rope.Length[m.name];
IF Rope.Fetch[m.name, length-1] = '^
THEN {
-- strip off '^ and export it
mark: Mark ← NEW[MarkRec ← m^];
mark.name ← Rope.Substr[m.name, 0, length-1];
t.exportMarks ← CONS[mark, t.exportMarks];
};
m.owner ← LOOPHOLE[t]; -- a unique id for the tile
SELECT
TRUE
FROM
Rope.Equal[m.name, "top"] => t.top ← m;
Rope.Equal[m.name, "bottom"] => t.bottom ← m;
Rope.Equal[m.name, "left"] => t.left ← m;
Rope.Equal[m.name, "right"] => t.right ← m;
Rope.Equal[m.name, "ul"] => t.ul ← m;
Rope.Equal[m.name, "ur"] => t.ur ← m;
Rope.Equal[m.name, "ll"] => t.ll ← m;
Rope.Equal[m.name, "lr"] => t.lr ← m;
ENDCASE => t.markList ← CONS[m, t.markList];
END;
DefaultMarks:
PUBLIC PROC [t: Tile, m: Mod ←
NIL] =
BEGIN
left, bottom: INT ← 0;
right: INT ← t.obj.size.x;
top: INT ← t.obj.size.y;
IF m #
NIL
THEN {
-- get marks from module
IF m.ul # NIL AND t.ul = NIL THEN StoreMark[t, NEW[MarkRec ← [name: "ul", pos: m.ul^]]];
IF m.ur # NIL AND t.ur = NIL THEN StoreMark[t, NEW[MarkRec ← [name: "ur", pos: m.ur^]]];
IF m.ll # NIL AND t.ll = NIL THEN StoreMark[t, NEW[MarkRec ← [name: "ll", pos: m.ll^]]];
IF m.lr # NIL AND t.lr = NIL THEN StoreMark[t, NEW[MarkRec ← [name: "lr", pos: m.lr^]]];
IF m.top # NIL AND t.top = NIL THEN StoreMark[t, NEW[MarkRec ← [name: "top", pos: m.top^]]];
IF m.bottom # NIL AND t.bottom = NIL THEN StoreMark[t, NEW[MarkRec ← [name: "bottom", pos: m.bottom^]]];
IF m.left # NIL AND t.left = NIL THEN StoreMark[t, NEW[MarkRec ← [name: "left", pos: m.left^]]];
IF m.right # NIL AND t.right = NIL THEN StoreMark[t, NEW[MarkRec ← [name: "right", pos: m.right^]]];
};
-- fabricate default box
IF t.top # NIL THEN top ← t.top.pos.y;
IF t.bottom # NIL THEN bottom ← t.bottom.pos.y;
IF t.left # NIL THEN left ← t.left.pos.x;
IF t.right # NIL THEN right ← t.right.pos.x;
IF t.ul # NIL THEN {left ← MIN[t.ul.pos.x, left]; top ← MAX[t.ul.pos.y, top]};
IF t.ur # NIL THEN {right ← MAX[t.ur.pos.x, right]; top ← MAX[t.ur.pos.y, top]};
IF t.ll # NIL THEN {left ← MIN[t.ur.pos.x, left]; bottom ← MIN[t.ur.pos.y, bottom]};
IF t.lr # NIL THEN {right ← MAX[t.ur.pos.x, right]; bottom ← MIN[t.ur.pos.y, bottom]};
-- fill in defaults
IF t.top = NIL THEN StoreMark[t, NEW[MarkRec ← [name: "top", pos: [(left+right)/2, top]]]];
IF t.bottom = NIL THEN StoreMark[t, NEW[MarkRec ← [name: "bottom", pos: [(left+right)/2, bottom]]]];
IF t.left = NIL THEN StoreMark[t, NEW[MarkRec ← [name: "left", pos: [left, (top+bottom)/2]]]];
IF t.right = NIL THEN StoreMark[t, NEW[MarkRec ← [name: "right", pos: [right, (top+bottom)/2]]]];
IF t.ul = NIL THEN StoreMark[t, NEW[MarkRec ← [name: "ul", pos: [left, top]]]];
IF t.ur = NIL THEN StoreMark[t, NEW[MarkRec ← [name: "ur", pos: [right, top]]]];
IF t.ll = NIL THEN StoreMark[t, NEW[MarkRec ← [name: "ll", pos: [left, bottom]]]];
IF t.lr = NIL THEN StoreMark[t, NEW[MarkRec ← [name: "lr", pos: [right, bottom]]]];
END;
GetMark:
PUBLIC
PROC [fromTile: Tile, markName: Rope.
ROPE]
RETURNS [Mark] =
BEGIN
SELECT
TRUE
FROM
Rope.Equal[markName, "top"] => RETURN[fromTile.top];
Rope.Equal[markName, "bottom"] => RETURN[fromTile.bottom];
Rope.Equal[markName, "left"] => RETURN[fromTile.left];
Rope.Equal[markName, "right"] => RETURN[fromTile.right];
Rope.Equal[markName, "ul"] => RETURN[fromTile.ul];
Rope.Equal[markName, "ur"] => RETURN[fromTile.ur];
Rope.Equal[markName, "ll"] => RETURN[fromTile.ll];
Rope.Equal[markName, "lr"] => RETURN[fromTile.lr];
ENDCASE => {
FOR marks: MarkList ← fromTile.markList, marks.rest
WHILE marks#
NIL
DO
IF Rope.Equal[markName, marks.first.name] THEN RETURN[marks.first];
ENDLOOP;
};
RETURN[NIL];
END;
OrientStdMark:
PUBLIC PROC [cell: Tile, orient: Orientation]
RETURNS [left, right, top, bottom, ul, ur, ll, lr: Mark] =
BEGIN
M2: TYPE = RECORD[a, b: Mark];
M4: TYPE = RECORD[a, b, c, d: Mark];
swapX, swapY, rotate: BOOL ← FALSE;
IF CDOrient.IncludesOddRot90[orient] THEN rotate ← ~rotate;
IF CDOrient.IncludesMirrorX[orient] THEN swapX ← ~swapX;
IF CDOrient.ConcentrateOnRotate90[orient] = CDOrient.rotate180
OR CDOrient.ConcentrateOnRotate90[orient] = CDOrient.rotate270
THEN
BEGIN swapX ← ~swapX; swapY ← ~swapY END;
left ← cell.left;
right ← cell.right;
top ← cell.top;
bottom ← cell.bottom;
ul ← cell.ul;
ur ← cell.ur;
ll ← cell.ll;
lr ← cell.lr;
IF rotate
THEN {
[bottom, left, top, right] ← M4[right, bottom, left, top];
[lr, ll, ul, ur] ← M4[ur, lr, ll, ul];
};
IF swapX
THEN {
[right, left] ← M2[left, right];
[ur, ul] ← M2[ul, ur];
[lr, ll] ← M2[ll, lr];
};
IF swapY
THEN {
[bottom, top] ← M2[top, bottom];
[ll, ul] ← M2[ul, ll];
[lr, ur] ← M2[ur, lr];
};
END;
SetModDefaults:
PUBLIC PROC [m: Mod, pc: PlacedTile] =
BEGIN
l, r, t, b, ul, ur, ll, lr: Mark;
[l, r, t, b, ul, ur, ll, lr] ← OrientStdMark[pc.tile, pc.orient];
-- mark top
IF t #
NIL
THEN {
tPos: CD.Position ← PlacedMarkLoc[pc, t];
IF m.top =
NIL
THEN
m.top ← NEW[CD.Position ← tPos]
ELSE
IF tPos.y > m.top.y
OR (tPos.y = m.top.y
AND tPos.x < m.top.x)
THEN
m.top^ ← tPos;
};
-- mark bottom
IF b #
NIL
THEN {
tPos: CD.Position ← PlacedMarkLoc[pc, b];
IF m.bottom =
NIL
THEN
m.bottom ← NEW[CD.Position ← tPos]
ELSE
IF tPos.y < m.bottom.y
OR (tPos.y = m.bottom.y
AND tPos.x < m.bottom.x)
THEN
m.bottom^ ← tPos;
};
-- mark right
IF r #
NIL
THEN {
tPos: CD.Position ← PlacedMarkLoc[pc, r];
IF m.right =
NIL
THEN
m.right ← NEW[CD.Position ← tPos]
ELSE
IF tPos.x > m.right.x
OR (tPos.x = m.right.x
AND tPos.y < m.right.y)
THEN
m.right^ ← tPos;
};
-- mark left
IF l #
NIL
THEN {
tPos: CD.Position ← PlacedMarkLoc[pc, l];
IF m.left =
NIL
THEN
m.left ← NEW[CD.Position ← tPos]
ELSE
IF tPos.x < m.left.x
OR (tPos.x = m.left.x
AND tPos.y < m.left.y)
THEN
m.left^ ← tPos;
};
-- mark ul
IF ul #
NIL
THEN {
tPos: CD.Position ← PlacedMarkLoc[pc, ul];
IF m.ul =
NIL
THEN
m.ul ← NEW[CD.Position ← tPos]
ELSE
IF -tPos.x + tPos.y > -m.ul.x + m.ul.y
OR (-tPos.x + tPos.y = -m.ul.x + m.ul.y
AND tPos.x < m.ul.x)
THEN
m.ul^ ← tPos;
};
-- mark ur
IF ur #
NIL
THEN {
tPos: CD.Position ← PlacedMarkLoc[pc, ur];
IF m.ur =
NIL
THEN
m.ur ← NEW[CD.Position ← tPos]
ELSE
IF tPos.x + tPos.y > m.ur.x + m.ur.y
OR (tPos.x + tPos.y = m.ur.x + m.ur.y
AND tPos.x > m.ur.x)
THEN
m.ur^ ← tPos;
};
-- mark ll
IF ll #
NIL
THEN {
tPos: CD.Position ← PlacedMarkLoc[pc, ll];
IF m.ll =
NIL
THEN
m.ll ← NEW[CD.Position ← tPos]
ELSE
IF tPos.x + tPos.y < m.ll.x + m.ll.y
OR (tPos.x + tPos.y = m.ll.x + m.ll.y
AND tPos.x < m.ll.x)
THEN
m.ll^ ← tPos;
};
-- mark lr
IF lr #
NIL
THEN {
tPos: CD.Position ← PlacedMarkLoc[pc, lr];
IF m.lr =
NIL
THEN
m.lr ← NEW[CD.Position ← tPos]
ELSE
IF tPos.x - tPos.y > m.lr.x - m.lr.y
OR (tPos.x - tPos.y = m.lr.x - m.lr.y
AND tPos.x > m.lr.x)
THEN
m.lr^ ← tPos;
};
END;