| (* Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 |
| Free Software Foundation, Inc. *) |
| (* This file is part of GNU Modula-2. |
| |
| GNU Modula-2 is free software; you can redistribute it and/or modify it under |
| the terms of the GNU General Public License as published by the Free |
| Software Foundation; either version 3, or (at your option) any later |
| version. |
| |
| GNU Modula-2 is distributed in the hope that it will be useful, but WITHOUT ANY |
| WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| for more details. |
| |
| You should have received a copy of the GNU General Public License along |
| with gm2; see the file COPYING. If not, write to the Free Software |
| Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) |
| IMPLEMENTATION MODULE RoomMap ; |
| |
| |
| IMPORT Break ; |
| |
| FROM NumberIO IMPORT WriteCard ; |
| FROM StrIO IMPORT WriteLn, WriteString ; |
| FROM Assertion IMPORT Assert ; |
| |
| FROM Geometry IMPORT IsSubLine, IsSubRange, Swap, IntersectionLength, |
| Abs, Max, Min, IsPointOnLine, IsIntersectingRange ; |
| |
| FROM Chance IMPORT GetRand, InitRandom, KillRandom, GetAndDeleteRandom, |
| AddRandom ; |
| |
| FROM StoreCoords IMPORT InitCoords, KillCoords, GetAndDeleteRandomCoord, |
| AddCoord ; |
| |
| FROM BoxMap IMPORT MaxX, MaxY, |
| Boxes, NoOfBoxes, NoOfCorridorBoxes, CreateBoxMap, |
| MinDoorLength, MaxDoorLength ; |
| |
| CONST |
| MaxLineStack = 20 ; |
| CorridorDoorLength = 2 ; |
| |
| VAR |
| NoOfCorridors: CARDINAL ; |
| NoOfLines : CARDINAL ; |
| Lines : ARRAY [1..MaxLineStack] OF Line ; |
| |
| |
| (* |
| CreateRoomMap - copy boxes into rooms and amalgamate boxes into rooms. |
| *) |
| |
| PROCEDURE CreateRoomMap ; |
| BEGIN |
| (* WriteString('Creating Boxes') ; WriteLn ; *) |
| CreateBoxMap ; |
| (* WriteString('Creating Rooms') ; WriteLn ; *) |
| InitRooms ; |
| CreateCorridors ; |
| CreateRooms ; |
| END CreateRoomMap ; |
| |
| |
| (* |
| InitRooms - copies the box array from Module BoxMap into the Room array. |
| *) |
| |
| PROCEDURE InitRooms ; |
| VAR |
| i: CARDINAL ; |
| BEGIN |
| i := 1 ; |
| WHILE i<=NoOfBoxes DO |
| WITH Rooms[i] DO |
| RoomNo := i ; |
| NoOfDoors := 0 ; |
| NoOfWalls := 4 ; |
| (* Treasures := {} ; *) |
| Walls[1].X1 := Boxes[i].x1 ; (* Lower y=c *) |
| Walls[1].Y1 := Boxes[i].y1 ; |
| Walls[1].X2 := Boxes[i].x2 ; |
| Walls[1].Y2 := Boxes[i].y1 ; |
| |
| Walls[2].X1 := Boxes[i].x2 ; (* Right x=c *) |
| Walls[2].Y1 := Boxes[i].y1 ; |
| Walls[2].X2 := Boxes[i].x2 ; |
| Walls[2].Y2 := Boxes[i].y2 ; |
| |
| Walls[3].X1 := Boxes[i].x1 ; (* Top y=c *) |
| Walls[3].Y1 := Boxes[i].y2 ; |
| Walls[3].X2 := Boxes[i].x2 ; |
| Walls[3].Y2 := Boxes[i].y2 ; |
| |
| Walls[4].X1 := Boxes[i].x1 ; (* Left x=c *) |
| Walls[4].Y1 := Boxes[i].y1 ; |
| Walls[4].X2 := Boxes[i].x1 ; |
| Walls[4].Y2 := Boxes[i].y2 |
| END ; |
| INC(i) |
| END ; |
| NoOfRooms := NoOfBoxes ; |
| NoOfCorridors := NoOfCorridorBoxes ; |
| (* Now set all other rooms to void *) |
| i := NoOfRooms+1 ; |
| WHILE i<=MaxNoOfRooms DO |
| Rooms[i].RoomNo := 0 ; |
| INC(i) |
| END |
| ; WriteString('Corridors') ; WriteCard(NoOfCorridors, 4) ; WriteLn ; |
| ; WriteString('Rooms ') ; WriteCard(NoOfRooms, 4) ; WriteLn ; |
| END InitRooms ; |
| |
| |
| (* |
| CreateCorridors - creates corridors from the corridor boxes. |
| *) |
| |
| PROCEDURE CreateCorridors ; |
| BEGIN |
| AmalgamateCorridors ; |
| CreateCorridorDoors |
| END CreateCorridors ; |
| |
| |
| (* |
| CreateRooms - creates rooms from the room boxes. |
| *) |
| |
| PROCEDURE CreateRooms ; |
| BEGIN |
| AmalgamateRooms ; |
| WriteString('Creating RoomDoors') ; WriteLn ; |
| CreateMinRoomDoors ; |
| CreateRoomDoors |
| END CreateRooms ; |
| |
| |
| (* |
| CreateCorridorDoors - places corridors doors along the corridors. |
| *) |
| |
| PROCEDURE CreateCorridorDoors ; |
| VAR |
| i, j: CARDINAL ; |
| BEGIN |
| i := 1 ; |
| WHILE i<=NoOfCorridors DO |
| j := 1 ; |
| WHILE j<=NoOfCorridors DO |
| IF (i#j) AND RoomExists(i) AND RoomExists(j) |
| THEN |
| MakeCorridorDoors(i, j) |
| END ; |
| INC(j) |
| END ; |
| INC(i) |
| END |
| END CreateCorridorDoors ; |
| |
| |
| (* |
| CreateMinRoomDoors - create minimum doors arround map. Thus allowing |
| an entrance into every room. |
| *) |
| |
| PROCEDURE CreateMinRoomDoors ; |
| VAR |
| Done: BOOLEAN ; |
| i : CARDINAL ; |
| BEGIN |
| REPEAT |
| Done := FALSE ; |
| i := 1 ; |
| WHILE (NOT Done) AND (i<=NoOfRooms) DO |
| IF RoomExists(i) |
| THEN |
| IF Rooms[i].NoOfDoors=0 |
| THEN |
| IF MakeDoorInRoomToSafty(i) |
| THEN |
| END ; |
| Done := (Rooms[i].NoOfDoors#0) |
| END |
| END ; |
| INC(i) |
| END |
| UNTIL NOT Done ; |
| (* Now remove all rooms that have no doors *) |
| WriteString('Number of rooms') ; WriteCard(NoOfRooms, 4) ; WriteLn ; |
| i := 1 ; |
| WHILE i<=NoOfRooms DO |
| IF RoomExists(i) AND (Rooms[i].NoOfDoors=0) |
| THEN |
| RemoveRoom(i) ; |
| WriteString('Removing room') ; WriteCard(i, 4) ; WriteLn ; |
| END ; |
| INC(i) |
| END |
| END CreateMinRoomDoors ; |
| |
| |
| (* |
| CreateRoomDoors - places room doors in rooms. |
| *) |
| |
| PROCEDURE CreateRoomDoors ; |
| VAR |
| i, n: CARDINAL ; |
| BEGIN |
| i := NoOfCorridors+1 ; |
| WHILE i<=NoOfRooms DO |
| IF RoomExists(i) |
| THEN |
| n := GetRand(DoorsPerRoom-1 DIV 2)+1 ; |
| WHILE (Rooms[i].NoOfDoors<DoorsPerRoom) AND (n>0) DO |
| IF MakeDoorInRoom(i) |
| THEN |
| END ; |
| DEC(n) |
| END |
| END ; |
| INC(i) |
| END |
| END CreateRoomDoors ; |
| |
| |
| (* |
| MakeCorridorDoors - checks for corridor doors thoughout the corridor rooms. |
| *) |
| |
| PROCEDURE MakeCorridorDoors (r1, r2: CARDINAL) ; |
| VAR |
| i, j: CARDINAL ; |
| BEGIN |
| i := 1 ; |
| WHILE i<=Rooms[r1].NoOfWalls DO |
| j := 1 ; |
| WHILE j<=Rooms[r2].NoOfWalls DO |
| IF IsIntersection( Rooms[r1].Walls[i].X1, Rooms[r1].Walls[i].Y1, |
| Rooms[r1].Walls[i].X2, Rooms[r1].Walls[i].Y2, |
| Rooms[r2].Walls[j].X1, Rooms[r2].Walls[j].Y1, |
| Rooms[r2].Walls[j].X2, Rooms[r2].Walls[j].Y2 ) |
| THEN |
| CheckForCorridorDoor(r1, i, r2, j) |
| END ; |
| INC(j) |
| END ; |
| INC(i) |
| END |
| END MakeCorridorDoors ; |
| |
| |
| (* |
| MakeDoorInRoomToSafty - true is returned if a door is made in room r |
| to a room which already has a door. |
| Thus room, r, is reachable by the whole map. |
| *) |
| |
| PROCEDURE MakeDoorInRoomToSafty (r: CARDINAL) : BOOLEAN ; |
| VAR |
| RoomList, |
| Neighbour: CARDINAL ; |
| Done : BOOLEAN ; |
| BEGIN |
| Done := FALSE ; |
| RoomList := InitRandom() ; |
| AddRandom(RoomList, NoOfRooms) ; (* 1..NoOfRooms *) |
| Neighbour := GetAndDeleteRandom(RoomList) ; |
| WHILE (Neighbour#0) AND (NOT Done) DO |
| IF RoomExists(Neighbour) AND (r#Neighbour) AND |
| IsTouching(r, Neighbour) AND (Rooms[Neighbour].NoOfDoors#0) |
| THEN |
| Done := MakeDoorBetweenRooms(r, Neighbour) |
| END ; |
| Neighbour := GetAndDeleteRandom(RoomList) |
| END ; |
| KillRandom(RoomList) ; |
| RETURN( Done ) |
| END MakeDoorInRoomToSafty ; |
| |
| |
| (* |
| MakeDoorInRoom - true is returned if a door is made in room r. |
| *) |
| |
| PROCEDURE MakeDoorInRoom (r: CARDINAL) : BOOLEAN ; |
| VAR |
| RoomList, |
| Neighbour: CARDINAL ; |
| Done : BOOLEAN ; |
| BEGIN |
| Done := FALSE ; |
| RoomList := InitRandom() ; |
| AddRandom(RoomList, NoOfRooms) ; (* 1..NoOfRooms *) |
| Neighbour := GetAndDeleteRandom(RoomList) ; |
| WHILE (Neighbour#0) AND (NOT Done) DO |
| IF RoomExists(Neighbour) AND (r#Neighbour) AND IsTouching(r, Neighbour) |
| THEN |
| Done := MakeDoorBetweenRooms(r, Neighbour) |
| END ; |
| Neighbour := GetAndDeleteRandom(RoomList) |
| END ; |
| KillRandom(RoomList) ; |
| RETURN( Done ) |
| END MakeDoorInRoom ; |
| |
| |
| (* |
| MakeDoorBetweenRooms - returns true if it makes a door between |
| rooms r1 and r2. |
| *) |
| |
| PROCEDURE MakeDoorBetweenRooms (r1, r2: CARDINAL) : BOOLEAN ; |
| VAR |
| CoordList: CARDINAL ; |
| Success : BOOLEAN ; |
| BEGIN |
| Success := FALSE ; |
| CoordList := InitCoords() ; |
| PushPossibleDoorCoords(CoordList, r1, r2) ; |
| Success := ChooseDoor(CoordList, r1, r2) ; |
| KillCoords(CoordList) ; |
| RETURN( Success ) |
| END MakeDoorBetweenRooms ; |
| |
| |
| (* |
| PushPossibleDoorCoords - pushes the possible door coordinates on the |
| coordinate stack CoordList. |
| The door links rooms r1 and r2 together. |
| *) |
| |
| PROCEDURE PushPossibleDoorCoords (CoordList: CARDINAL; r1, r2: CARDINAL) ; |
| VAR |
| i, j : CARDINAL ; |
| BEGIN |
| i := 1 ; |
| WHILE i<=Rooms[r1].NoOfWalls DO |
| j := 1 ; |
| WHILE j<=Rooms[r2].NoOfWalls DO |
| IF IsIntersection( Rooms[r1].Walls[i].X1, Rooms[r1].Walls[i].Y1, |
| Rooms[r1].Walls[i].X2, Rooms[r1].Walls[i].Y2, |
| Rooms[r2].Walls[j].X1, Rooms[r2].Walls[j].Y1, |
| Rooms[r2].Walls[j].X2, Rooms[r2].Walls[j].Y2 ) |
| THEN |
| IF PossibleDoorLength(r1, i, r2, j)>=MinDoorLength |
| THEN |
| PushPossibleDoorCoordsOnWall(CoordList, r1, i, r2, j) |
| END |
| END ; |
| INC(j) |
| END ; |
| INC(i) |
| END |
| END PushPossibleDoorCoords ; |
| |
| |
| (* |
| PushPossibleDoorCoordsOnWall - pushes the coordinates which can take a door |
| between rooms r1 and r2 on walls w1 and w2 |
| onto the coordinate stack CoordList. |
| *) |
| |
| PROCEDURE PushPossibleDoorCoordsOnWall (CoordList: CARDINAL ; |
| r1, w1, r2, w2: CARDINAL) ; |
| VAR |
| s, e, |
| x1, y1, x2, y2, |
| x3, y3, x4, y4: CARDINAL ; |
| BEGIN |
| WriteString('Pushing walls') ; WriteCard(w1, 4) ; WriteCard(w2, 4) ; WriteLn ; |
| WITH Rooms[r1].Walls[w1] DO |
| x1 := X1 ; |
| y1 := Y1 ; |
| x2 := X2 ; |
| y2 := Y2 |
| END ; |
| WITH Rooms[r2].Walls[w2] DO |
| x3 := X1 ; |
| y3 := Y1 ; |
| x4 := X2 ; |
| y4 := Y2 |
| END ; |
| IF IsVertical(x1, y1, x2, y2) AND IsVertical(x3, y3, x4, y4) |
| THEN |
| Assert(x1=x3) ; Assert(x2=x4) ; |
| IF IsSubRange(y1, y2, y3) |
| THEN |
| s := y3 |
| ELSE |
| Assert(IsSubRange(y3, y4, y1)) ; |
| s := y1 |
| END ; |
| e := Min(y2, y4) ; |
| INC(s) ; |
| DEC(e) ; |
| WHILE s<=e DO |
| IF IsDoorAllowed(r1, r2, x1, s, x1, e) AND |
| IsDoorAllowed(r2, r1, x1, s, x1, e) |
| THEN |
| AddCoord(CoordList, x1, s) |
| ; WriteString('Point') ; WriteCard(x1, 4) ; WriteCard(s, 4) ; WriteLn |
| END ; |
| INC(s) |
| END |
| ELSE |
| Assert(IsHorizontal(x1, y1, x2, y2) AND IsHorizontal(x3, y3, x4, y4)) ; |
| Assert(y1=y3) ; Assert(y2=y4) ; |
| IF IsSubRange(x1, x2, x3) |
| THEN |
| s := x3 |
| ELSE |
| Assert(IsSubRange(x3, x4, x1)) ; |
| s := x1 |
| END ; |
| e := Min(x2, x4) ; |
| INC(s) ; |
| DEC(e) ; |
| WHILE s<=e DO |
| IF IsDoorAllowed(r1, r2, s, y1, e, y1) AND |
| IsDoorAllowed(r2, r1, s, y1, e, y1) |
| THEN |
| AddCoord(CoordList, s, y1) |
| ; WriteString('Point') ; WriteCard(s, 4) ; WriteCard(y1, 4) ; WriteLn |
| END ; |
| INC(s) |
| END |
| END |
| END PushPossibleDoorCoordsOnWall ; |
| |
| |
| (* |
| ChooseDoor - chooses a door from the CoordList which connects rooms |
| r1 and r2. |
| *) |
| |
| PROCEDURE ChooseDoor (CoordList: CARDINAL; r1, r2: CARDINAL) : BOOLEAN ; |
| VAR |
| x, y : CARDINAL ; |
| w1, w2: CARDINAL ; |
| ok : BOOLEAN ; |
| BEGIN |
| GetAndDeleteRandomCoord(CoordList, x, y) ; |
| ok := (x#0) AND (y#0) ; |
| IF ok |
| THEN |
| w1 := FindWall(r1, x, y) ; |
| w2 := FindWall(r2, x, y) ; |
| MakeRoomDoor(r1, w1, r2, w2, x, y) |
| END ; |
| RETURN( ok ) |
| END ChooseDoor ; |
| |
| |
| (* |
| FindWall - returns the wall number of a room r1 which has the point x, y |
| on it. A corner point will return a wall of zero. |
| *) |
| |
| PROCEDURE FindWall (r: CARDINAL; x, y: CARDINAL) : CARDINAL ; |
| VAR |
| Found: BOOLEAN ; |
| i : CARDINAL ; |
| BEGIN |
| i := 1 ; |
| Found := FALSE ; |
| WITH Rooms[r] DO |
| WHILE (i<=NoOfWalls) AND (NOT Found) DO |
| WITH Walls[i] DO |
| IF ((x=X1) AND (y=Y1)) OR ((x=X2) AND (y=Y2)) |
| THEN |
| (* Corner has been found *) |
| Found := TRUE ; |
| i := 0 |
| ELSIF IsPointOnLine(x, y, X1, Y1, X2, Y2) |
| THEN |
| Found := TRUE |
| ELSE |
| INC(i) |
| END |
| END |
| END |
| END ; |
| IF Found |
| THEN |
| RETURN( i ) |
| ELSE |
| RETURN( 0 ) |
| END |
| END FindWall ; |
| |
| |
| (* |
| MakeRoomDoor - makes a door between rooms r1 and r2 on walls w1 and w2 |
| at position x, y. |
| *) |
| |
| PROCEDURE MakeRoomDoor (r1: CARDINAL; w1: CARDINAL; r2: CARDINAL; w2: CARDINAL; |
| x, y: CARDINAL) ; |
| VAR |
| l, h, List, |
| x1, y1, x2, y2, |
| x3, y3, x4, y4: CARDINAL ; |
| Done : BOOLEAN ; |
| BEGIN |
| WriteString('Making walls') ; WriteCard(w1, 4) ; WriteCard(w2, 4) ; WriteLn ; |
| WITH Rooms[r1].Walls[w1] DO |
| x1 := X1 ; |
| y1 := Y1 ; |
| x2 := X2 ; |
| y2 := Y2 |
| END ; |
| WITH Rooms[r2].Walls[w2] DO |
| x3 := X1 ; |
| y3 := Y1 ; |
| x4 := X2 ; |
| y4 := Y2 |
| END ; |
| IF IsVertical(x1, y1, x2, y2) AND IsVertical(x3, y3, x4, y4) |
| THEN |
| Assert(x1=x3) ; Assert(x2=x4) ; |
| Done := FALSE ; |
| List := InitRandom() ; |
| AddRandom(List, MaxDoorLength) ; |
| REPEAT |
| l := GetAndDeleteRandom(List) ; |
| IF l>=MinDoorLength |
| THEN |
| h := Min(y+l-1, Min(y2, y4)-1) ; |
| Done := IsDoorAllowed(r1, r2, x, y, x, h) AND |
| IsDoorAllowed(r2, r1, x, y, x, h) |
| END |
| UNTIL (l=0) OR Done ; |
| KillRandom(List) ; |
| Assert(l#0) ; |
| FixRoomDoor(r2, r1, x, y, x, h) |
| ELSIF IsHorizontal(x1, y1, x2, y2) AND IsHorizontal(x3, y3, x4, y4) |
| THEN |
| Assert(y1=y3) ; Assert(y2=y4) ; |
| Done := FALSE ; |
| List := InitRandom() ; |
| AddRandom(List, MaxDoorLength) ; |
| REPEAT |
| l := GetAndDeleteRandom(List) ; |
| IF l>=MinDoorLength |
| THEN |
| h := Min(x+l-1, Min(x2, x4)-1) ; |
| Done := IsDoorAllowed(r1, r2, x, y, h, y) AND |
| IsDoorAllowed(r2, r1, x, y, h, y) |
| END |
| UNTIL (l=0) OR Done ; |
| KillRandom(List) ; |
| Assert(l#0) ; |
| FixRoomDoor(r2, r1, x, y, h, y) |
| ELSE |
| HALT |
| END |
| END MakeRoomDoor ; |
| |
| |
| (* |
| IsDoorAllowed - checks whether a door can be built in r1 leading to r2 |
| the coordinates of the door are x1, y1, x2, y2. |
| *) |
| |
| PROCEDURE IsDoorAllowed (r1, r2: CARDINAL; x1, y1, x2, y2: CARDINAL) : BOOLEAN ; |
| VAR |
| ok : BOOLEAN ; |
| i, w: CARDINAL ; |
| BEGIN |
| ok := (NOT DoorsClash(r1, x1, y1, x2, y2)) AND |
| (Rooms[r1].NoOfDoors<DoorsPerRoom) AND |
| (Max(Abs(x1, x2)+1, Abs(y1, y2)+1)>=MinDoorLength) ; |
| IF ok |
| THEN |
| w := FindWall(r1, x1, y1) ; |
| IF IsVertical(x1, y1, x2, y2) |
| THEN |
| i := y1 ; |
| WHILE (i<=y2) AND ok DO |
| ok := (w=FindWall(r1, x1, i)) ; |
| INC(i) |
| END |
| ELSIF IsHorizontal(x1, y1, x2, y2) |
| THEN |
| i := x1 ; |
| WHILE (i<=x2) AND ok DO |
| ok := (w=FindWall(r1, i, y1)) ; |
| INC(i) |
| END |
| END |
| END ; |
| RETURN( ok ) |
| END IsDoorAllowed ; |
| |
| |
| (* |
| FixRoomDoor - places a door between rooms r1 and r2 with coordinates |
| x1, y1, x2, y2. |
| *) |
| |
| PROCEDURE FixRoomDoor (r1, r2: CARDINAL; x1, y1, x2, y2: CARDINAL) ; |
| BEGIN |
| IF IsConnectionSecret(r1, r2) |
| THEN |
| AddDoor(r1, r2, x1, y1, x2, y2, Secret) ; |
| AddDoor(r2, r1, x1, y1, x2, y2, Secret) |
| ELSIF (NOT Adjacent(r1, r2)) AND (GetRand(100)>49) |
| THEN |
| AddDoor(r1, r2, x1, y1, x2, y2, Secret) ; |
| AddDoor(r2, r1, x1, y1, x2, y2, Secret) |
| ELSE |
| AddDoor(r1, r2, x1, y1, x2, y2, Closed) ; |
| AddDoor(r2, r1, x1, y1, x2, y2, Closed) |
| END |
| END FixRoomDoor ; |
| |
| |
| (* |
| IsConnectionSecret - returns true if the rooms, r1 and r2, are |
| connected via a secret door. |
| *) |
| |
| PROCEDURE IsConnectionSecret (r1, r2: CARDINAL) : BOOLEAN ; |
| VAR |
| i: CARDINAL ; |
| BEGIN |
| i := 1 ; |
| WITH Rooms[r1] DO |
| WHILE i<=NoOfDoors DO |
| WITH Doors[i] DO |
| IF (LeadsTo=r1) AND (StateOfDoor=Secret) |
| THEN |
| RETURN( TRUE ) |
| ELSE |
| INC(i) |
| END |
| END |
| END |
| END ; |
| RETURN( FALSE ) |
| END IsConnectionSecret ; |
| |
| |
| (* |
| CheckForCorridorDoor - checks whether a door can be built on walls |
| w1 and w2 of rooms r1 and r2. |
| *) |
| |
| PROCEDURE CheckForCorridorDoor (r1: CARDINAL; w1: CARDINAL; |
| r2: CARDINAL; w2: CARDINAL) ; |
| VAR |
| l: CARDINAL ; |
| BEGIN |
| l := PossibleDoorLength(r1, w1, r2, w2) ; |
| (* WriteString('Intersection length') ; WriteCard(l, 4) ; WriteLn ; *) |
| IF l>=CorridorDoorLength |
| THEN |
| BuildCorridorDoor(r1, w1, r2, w2) |
| END |
| END CheckForCorridorDoor ; |
| |
| |
| (* |
| BuildCorridorDoor - will build a door on walls w1 and w2. |
| BuildCorridorDoor works out the coordinates |
| for the corridor doors. |
| *) |
| |
| PROCEDURE BuildCorridorDoor (r1: CARDINAL; w1: CARDINAL; |
| r2: CARDINAL; w2: CARDINAL) ; |
| VAR |
| x1, y1, x2, y2, |
| x3, y3, x4, y4: CARDINAL ; |
| BEGIN |
| WITH Rooms[r1].Walls[w1] DO |
| x1 := X1 ; |
| y1 := Y1 ; |
| x2 := X2 ; |
| y2 := Y2 |
| END ; |
| WITH Rooms[r2].Walls[w2] DO |
| x3 := X1 ; |
| y3 := Y1 ; |
| x4 := X2 ; |
| y4 := Y2 |
| END ; |
| IF IsVertical(x1, y1, x2, y2) AND IsVertical(x3, y3, x4, y4) |
| THEN |
| Assert(x1=x3) ; Assert(x2=x4) ; |
| IF Abs(y1, y2)<Abs(y3, y4) |
| THEN |
| AttemptBuildCorridorDoor(r1, r2, x1, y1+1, x2, y2-1) |
| ELSE |
| AttemptBuildCorridorDoor(r1, r2, x1, y3+1, x2, y4-1) |
| END |
| ELSIF IsHorizontal(x1, y1, x2, y2) AND IsHorizontal(x3, y3, x4, y4) |
| THEN |
| Assert(y1=y3) ; Assert(y2=y4) ; |
| IF Abs(x1, x2)<Abs(x3, x4) |
| THEN |
| AttemptBuildCorridorDoor(r1, r2, x1+1, y1, x2-1, y2) |
| ELSE |
| AttemptBuildCorridorDoor(r1, r2, x3+1, y1, x4-1, y4) |
| END |
| END |
| END BuildCorridorDoor ; |
| |
| |
| (* |
| AttemptBuildCorridorDoor - attempts to make a corridor door |
| between rooms r1 and r2 with |
| coordinates x1, y1, x2, y2. |
| *) |
| |
| PROCEDURE AttemptBuildCorridorDoor (r1, r2: CARDINAL ; |
| x1, y1, x2, y2: CARDINAL) ; |
| BEGIN |
| IF IsDoorAllowed(r1, r2, x1, y1, x2, y2) AND |
| IsDoorAllowed(r2, r1, x1, y1, x2, y2) |
| THEN |
| IF IsConnectionSecret(r1, r2) |
| THEN |
| AddDoor(r1, r2, x1, y1, x2, y2, Secret) ; |
| AddDoor(r2, r1, x1, y1, x2, y2, Secret) |
| ELSIF (NOT Adjacent(r1, r2)) AND (GetRand(100)>65) |
| THEN |
| AddDoor(r1, r2, x1, y1, x2, y2, Secret) ; |
| AddDoor(r2, r1, x1, y1, x2, y2, Secret) |
| ELSE |
| AddDoor(r1, r2, x1, y1, x2, y2, Open) ; |
| AddDoor(r2, r1, x1, y1, x2, y2, Open) |
| END |
| ELSE |
| WriteString('Not allowing corridor door!') ; WriteLn |
| END |
| END AttemptBuildCorridorDoor ; |
| |
| |
| (* |
| DoorsClash - returns true if there does exist a door which clashes with |
| x1, y1, x2, y2 in room r1. |
| *) |
| |
| PROCEDURE DoorsClash (r: CARDINAL; x1, y1, x2, y2: CARDINAL) : BOOLEAN ; |
| VAR |
| Clash: BOOLEAN ; |
| i : CARDINAL ; |
| BEGIN |
| IF IsVertical(x1, y1, x2, y2) |
| THEN |
| INC(y2) ; |
| IF y1>1 |
| THEN |
| DEC(y1) |
| END |
| ELSE |
| INC(x2) ; |
| IF x1>1 |
| THEN |
| DEC(x1) |
| END |
| END ; |
| Clash := FALSE ; |
| WITH Rooms[r] DO |
| i := 1 ; |
| WHILE (i<=NoOfDoors) AND (NOT Clash) DO |
| WITH Doors[i].Position DO |
| IF IsIntersection(x1, y1, x2, y2, X1, Y1, X2, Y2) |
| THEN |
| Clash := TRUE |
| END |
| END ; |
| INC(i) |
| END |
| END ; |
| RETURN( Clash ) |
| END DoorsClash ; |
| |
| |
| (* |
| AddDoor - adds a door in room r1 that leads to a door in r2. |
| The coordinates of the door are x1, y1, x2, y2 and the |
| door type is in Status. |
| *) |
| |
| PROCEDURE AddDoor (r1, r2: CARDINAL; |
| x1, y1, x2, y2: CARDINAL; Status: DoorStatus) ; |
| BEGIN |
| ; Assert(IsTouching(r1, r2)) |
| ; Assert(IsDoorAllowed(r1, r2, x1, y1, x2, y2)) ; |
| ; Assert(r1#r2) ; |
| ; Assert(RoomExists(r1) AND RoomExists(r2)) ; |
| WITH Rooms[r1] DO |
| Assert(NoOfDoors<DoorsPerRoom) ; |
| INC(NoOfDoors) ; |
| WITH Doors[NoOfDoors] DO |
| Position.X1 := x1 ; |
| Position.Y1 := y1 ; |
| Position.X2 := x2 ; |
| Position.Y2 := y2 ; |
| StateOfDoor := Status ; |
| LeadsTo := r2 |
| END |
| END |
| END AddDoor ; |
| |
| |
| (* |
| PossibleDoorLength - returns the possible door length between rooms |
| r1 and r2 on wall w1 and w2. |
| *) |
| |
| PROCEDURE PossibleDoorLength (r1: CARDINAL; w1: CARDINAL; |
| r2: CARDINAL; w2: CARDINAL) : CARDINAL ; |
| VAR |
| l, |
| x1, x2, x3, x4, |
| y1, y2, y3, y4: CARDINAL ; |
| BEGIN |
| WITH Rooms[r1].Walls[w1] DO |
| x1 := X1 ; |
| y1 := Y1 ; |
| x2 := X2 ; |
| y2 := Y2 |
| END ; |
| WITH Rooms[r2].Walls[w2] DO |
| x3 := X1 ; |
| y3 := Y1 ; |
| x4 := X2 ; |
| y4 := Y2 |
| END ; |
| IF IsVertical(x1, y1, x2, y2) AND IsVertical(x3, y3, x4, y4) |
| THEN |
| l := IntersectionLength(y1, y2, y3, y4)+1 ; |
| IF (IsSubRange(y1, y2, y3) OR IsSubRange(y3, y4, y1)) AND (l>0) |
| THEN |
| DEC(l) |
| END ; |
| IF (IsSubRange(y1, y2, y4) OR IsSubRange(y3, y4, y2)) AND (l>0) |
| THEN |
| DEC(l) |
| END |
| ELSIF IsHorizontal(x1, y1, x2, y2) AND IsHorizontal(x3, y3, x4, y4) |
| THEN |
| l := IntersectionLength(x1, x2, x3, x4)+1 ; |
| IF (IsSubRange(x1, x2, x3) OR IsSubRange(x3, x4, x1)) AND (l>0) |
| THEN |
| DEC(l) |
| END ; |
| IF (IsSubRange(x1, x2, x4) OR IsSubRange(x3, x4, x2)) AND (l>0) |
| THEN |
| DEC(l) |
| END |
| ELSE |
| l := 0 |
| END ; |
| RETURN( l ) |
| END PossibleDoorLength ; |
| |
| |
| (* |
| AmalgamateCorridors - joins corridors together. |
| *) |
| |
| PROCEDURE AmalgamateCorridors ; |
| VAR |
| i, j: CARDINAL ; |
| Done: BOOLEAN ; |
| BEGIN |
| REPEAT |
| Done := FALSE ; |
| i := 1 ; |
| WHILE (NOT Done) AND (i<=NoOfCorridors) DO |
| j := 1 ; |
| WHILE (NOT Done) AND (j<=NoOfCorridors) DO |
| IF (i#j) AND RoomExists(i) AND RoomExists(j) |
| THEN |
| IF Amalgamate(i, j) |
| THEN |
| Done := TRUE |
| END |
| END ; |
| INC(j) |
| END ; |
| INC(i) |
| END |
| UNTIL NOT Done |
| END AmalgamateCorridors ; |
| |
| |
| (* |
| AmalgamateRooms - joins rooms together. |
| *) |
| |
| PROCEDURE AmalgamateRooms ; |
| VAR |
| i, j: CARDINAL ; |
| Done: BOOLEAN ; |
| BEGIN |
| REPEAT |
| Done := FALSE ; |
| i := NoOfCorridors+1 ; |
| WHILE (NOT Done) AND (i<=NoOfRooms) DO |
| j := NoOfCorridors+1 ; |
| WHILE (NOT Done) AND (j<=NoOfRooms) DO |
| IF (i#j) AND RoomExists(i) AND RoomExists(j) |
| THEN |
| IF Amalgamate(i, j) |
| THEN |
| Done := TRUE |
| END |
| END ; |
| INC(j) |
| END ; |
| INC(i) |
| END |
| UNTIL NOT Done |
| END AmalgamateRooms ; |
| |
| |
| (* |
| Amalgamate - returns true if it can join two rooms r1 and r2 together. |
| *) |
| |
| PROCEDURE Amalgamate (r1, r2: CARDINAL) : BOOLEAN ; |
| BEGIN |
| IF IsTouching(r1, r2) |
| THEN |
| NoOfLines := 0 ; |
| CopyWallsToLines(r1) ; |
| CopyWallsToLines(r2) ; |
| RemoveRoom(r1) ; |
| RemoveRoom(r2) ; |
| IF CompactLines() AND IsLineRoomSatisfied() |
| THEN |
| CopyLinesToWalls(r1) ; |
| InsertRoom(r1) ; |
| RETURN( TRUE ) |
| ELSE |
| InsertRoom(r1) ; |
| InsertRoom(r2) ; |
| RETURN( FALSE ) |
| END |
| ELSE |
| RETURN( FALSE ) |
| END |
| END Amalgamate ; |
| |
| |
| (* |
| CompactLines - returns true if the lines in the line buffer are |
| reduced by forming a bigger room. |
| *) |
| |
| PROCEDURE CompactLines () : BOOLEAN ; |
| VAR |
| Done, |
| Compacted: BOOLEAN ; |
| i, j : CARDINAL ; |
| BEGIN |
| Compacted := FALSE ; |
| REPEAT |
| Done := FALSE ; |
| i := 1 ; |
| WHILE (i<=NoOfLines) AND (NOT Done) DO |
| j := 1 ; |
| WHILE (j<=NoOfLines) AND (NOT Done) DO |
| IF (i#j) AND (NOT IsNulLine(i)) AND (NOT IsNulLine(j)) |
| THEN |
| IF IsIntersectionLine(i, j) |
| THEN |
| DeleteIntersectionLine(i, j) ; |
| LinkUpLines ; |
| Done := TRUE ; |
| Compacted := TRUE |
| END |
| END ; |
| INC(j) |
| END ; |
| INC(i) |
| END |
| UNTIL NOT Done ; |
| RETURN( Compacted ) |
| END CompactLines ; |
| |
| |
| (* |
| LinkUpLines - attempts to join lines that naturally run in to each other. |
| *) |
| |
| PROCEDURE LinkUpLines ; |
| VAR |
| Joined: BOOLEAN ; |
| i, j : CARDINAL ; |
| BEGIN |
| Joined := FALSE ; |
| i := 1 ; |
| WHILE (i<=NoOfLines) AND (NOT Joined) DO |
| j := 1 ; |
| WHILE (j<=NoOfLines) AND (NOT Joined) DO |
| Joined := JoinedLines(i, j) ; |
| INC(j) |
| END ; |
| INC(i) |
| END |
| END LinkUpLines ; |
| |
| |
| (* |
| JoinedLines - returns true if it can join lines i and j. |
| *) |
| |
| PROCEDURE JoinedLines (i, j: CARDINAL) : BOOLEAN ; |
| VAR |
| Joined : BOOLEAN ; |
| x1, x2, x3, x4, |
| y1, y2, y3, y4: CARDINAL ; |
| BEGIN |
| WITH Lines[i] DO |
| x1 := X1 ; |
| y1 := Y1 ; |
| x2 := X2 ; |
| y2 := Y2 |
| END ; |
| WITH Lines[j] DO |
| x3 := X1 ; |
| y3 := Y1 ; |
| x4 := X2 ; |
| y4 := Y2 |
| END ; |
| Joined := FALSE ; |
| (* X1 <= X2 - always *) |
| WITH Lines[i] DO |
| IF IsVertical(x1, y1, x2, y2) AND IsVertical(x3, y3, x4, y4) AND (x1=x3) |
| THEN |
| IF y4=y1 |
| THEN |
| AddLine(x3, y3, x2, y2) ; |
| DeleteLine(i) ; |
| DeleteLine(j) ; |
| Joined := TRUE |
| ELSIF y2=y3 |
| THEN |
| AddLine(x1, y1, x4, y4) ; |
| DeleteLine(i) ; |
| DeleteLine(j) ; |
| Joined := TRUE |
| END |
| ELSIF IsHorizontal(x1, y1, x2, y2) AND IsHorizontal(x3, y3, x4, y4) AND |
| (y1=y3) |
| THEN |
| IF x4=x1 |
| THEN |
| AddLine(x3, y3, x2, y2) ; |
| DeleteLine(i) ; |
| DeleteLine(j) ; |
| Joined := TRUE |
| ELSIF x2=x3 |
| THEN |
| AddLine(x1, y1, x4, y4) ; |
| DeleteLine(i) ; |
| DeleteLine(j) ; |
| Joined := TRUE |
| END |
| END |
| END ; |
| RETURN( Joined ) |
| END JoinedLines ; |
| |
| |
| (* |
| IsIntersectionLine - returns true if lines i and j intersect. |
| *) |
| |
| PROCEDURE IsIntersectionLine (i, j: CARDINAL) : BOOLEAN ; |
| BEGIN |
| RETURN( |
| IsIntersection( |
| Lines[i].X1, Lines[i].Y1, Lines[i].X2, Lines[i].Y2, |
| Lines[j].X1, Lines[j].Y1, Lines[j].X2, Lines[j].Y2) |
| ) |
| END IsIntersectionLine ; |
| |
| |
| (* |
| DeleteIntersectionLine - joins two lines together, i and j, and |
| removes the intersection. |
| *) |
| |
| PROCEDURE DeleteIntersectionLine (i, j: CARDINAL) ; |
| VAR |
| x1, x2, x3, x4, |
| y1, y2, y3, y4: CARDINAL ; |
| BEGIN |
| WITH Lines[i] DO |
| x1 := X1 ; |
| y1 := Y1 ; |
| x2 := X2 ; |
| y2 := Y2 |
| END ; |
| WITH Lines[j] DO |
| x3 := X1 ; |
| y3 := Y1 ; |
| x4 := X2 ; |
| y4 := Y2 |
| END ; |
| IF IsVertical(x1, y1, x2, y2) AND IsVertical(x3, y3, x4, y4) |
| THEN |
| DeleteLine(i) ; |
| DeleteLine(j) ; |
| SubtractIntersection(y1, y2, y3, y4) ; |
| AddLine(x1, y1, x2, y2) ; |
| AddLine(x3, y3, x4, y4) |
| ELSIF IsHorizontal(x1, y1, x2, y2) AND IsHorizontal(x3, y3, x4, y4) |
| THEN |
| DeleteLine(i) ; |
| DeleteLine(j) ; |
| SubtractIntersection(x1, x2, x3, x4) ; |
| AddLine(x1, y1, x2, y2) ; |
| AddLine(x3, y3, x4, y4) |
| END |
| END DeleteIntersectionLine ; |
| |
| |
| (* |
| SubtractIntersection - deletes the intersecting entities of the range |
| i1..i2 j1..j2. |
| *) |
| |
| PROCEDURE SubtractIntersection (VAR i1, i2, j1, j2: CARDINAL) ; |
| VAR |
| k1, k2, |
| l1, l2: CARDINAL ; |
| BEGIN |
| Assert(i1<=i2) ; |
| Assert(j1<=j2) ; |
| IF IsSubRange(i1, i2, j1) |
| THEN |
| k1 := i1 ; |
| k2 := j1 |
| ELSIF IsSubRange(j1, j2, i1) |
| THEN |
| k1 := j1 ; |
| k2 := i1 |
| END ; |
| IF IsSubRange(i1, i2, j2) |
| THEN |
| l1 := j2 ; |
| l2 := i2 |
| ELSIF IsSubRange(j1, j2, i2) |
| THEN |
| l1 := i2 ; |
| l2 := j2 |
| END ; |
| i1 := k1 ; |
| i2 := k2 ; |
| j1 := l1 ; |
| j2 := l2 |
| END SubtractIntersection ; |
| |
| |
| (* |
| AddLine - adds a line to the lines buffer. |
| *) |
| |
| PROCEDURE AddLine (x1, y1, x2, y2: CARDINAL) ; |
| VAR |
| i: CARDINAL ; |
| BEGIN |
| IF (x1>x2) OR (y1>y2) |
| THEN |
| Swap(x1, x2) ; |
| Swap(y1, y2) |
| ELSIF (x1#x2) OR (y1#y2) |
| THEN |
| (* Do not store points *) |
| IF NOT InsertLine(x1, y1, x2, y2) |
| THEN |
| INC(NoOfLines) ; |
| WITH Lines[NoOfLines] DO |
| X1 := x1 ; |
| Y1 := y1 ; |
| X2 := x2 ; |
| Y2 := y2 |
| END |
| END |
| (* ; DisplayLines *) |
| END |
| END AddLine ; |
| |
| |
| (* |
| InsertLine - attempts to insert a line in a free slot, |
| true is returned if successfull. |
| *) |
| |
| PROCEDURE InsertLine (x1, y1, x2, y2: CARDINAL) : BOOLEAN ; |
| VAR |
| Success: BOOLEAN ; |
| i : CARDINAL ; |
| BEGIN |
| i := 1 ; |
| Success := FALSE ; |
| WHILE (NOT Success) AND (i<=NoOfLines) DO |
| IF IsNulLine(i) |
| THEN |
| WITH Lines[i] DO |
| X1 := x1 ; |
| Y1 := y1 ; |
| X2 := x2 ; |
| Y2 := y2 |
| END ; |
| Success := TRUE |
| ELSE |
| INC(i) |
| END |
| END ; |
| RETURN( Success ) |
| END InsertLine ; |
| |
| |
| (* |
| DeleteLine - deletes a line from the lines buffer. |
| *) |
| |
| PROCEDURE DeleteLine (l: CARDINAL) ; |
| BEGIN |
| WITH Lines[l] DO |
| X1 := 0 ; |
| Y1 := 0 ; |
| X2 := 0 ; |
| Y2 := 0 |
| END |
| (* ; DisplayLines *) |
| END DeleteLine ; |
| |
| |
| PROCEDURE DisplayLines ; |
| VAR |
| i: CARDINAL ; |
| BEGIN |
| WriteString('Lines') ; WriteLn ; |
| i := 1 ; |
| WHILE i<=NoOfLines DO |
| WITH Lines[i] DO |
| WriteCard(X1, 4) ; WriteCard(Y1, 4) ; |
| WriteCard(X2, 4) ; WriteCard(Y2, 4) ; WriteLn |
| END ; |
| INC(i) |
| END |
| END DisplayLines ; |
| |
| |
| (* |
| IsNulLine - returns true if line l is a nul line. |
| *) |
| |
| PROCEDURE IsNulLine (l: CARDINAL) : BOOLEAN ; |
| BEGIN |
| WITH Lines[l] DO |
| RETURN( (X1=0) AND (Y1=0) AND (X2=0) AND (Y2=0) ) |
| END |
| END IsNulLine ; |
| |
| |
| (* |
| RemoveRoom - removes a room, r, from the room list. |
| *) |
| |
| PROCEDURE RemoveRoom (r: CARDINAL) ; |
| BEGIN |
| Rooms[r].RoomNo := 0 (* No longer exists *) |
| END RemoveRoom ; |
| |
| |
| (* |
| InsertRoom - inserts a room, r, back into the room list. |
| *) |
| |
| PROCEDURE InsertRoom (r: CARDINAL) ; |
| BEGIN |
| Rooms[r].RoomNo := r |
| END InsertRoom ; |
| |
| |
| (* |
| RoomExist - returns true if a room, r, exists. |
| *) |
| |
| PROCEDURE RoomExists (r: CARDINAL) : BOOLEAN ; |
| BEGIN |
| RETURN( Rooms[r].RoomNo#0 ) |
| END RoomExists ; |
| |
| |
| (* |
| IsLineRoomSatisfied - returns true if the line room meets the requirements |
| of a room. |
| *) |
| |
| PROCEDURE IsLineRoomSatisfied () : BOOLEAN ; |
| VAR |
| Count, i: CARDINAL ; |
| BEGIN |
| Count := 0 ; |
| i := 1 ; |
| WHILE i<=NoOfLines DO |
| IF NOT IsNulLine(i) |
| THEN |
| INC(Count) |
| END ; |
| INC(i) |
| END ; |
| RETURN( Count<=WallsPerRoom ) |
| (* Must also check for a door into another room *) |
| END IsLineRoomSatisfied ; |
| |
| |
| (* |
| CopyWallsToLines - copies walls from room r into the lines buffer. |
| *) |
| |
| PROCEDURE CopyWallsToLines (r: CARDINAL) ; |
| VAR |
| i: CARDINAL ; |
| BEGIN |
| i := 1 ; |
| WITH Rooms[r] DO |
| WHILE i<=NoOfWalls DO |
| INC(NoOfLines) ; |
| WITH Lines[NoOfLines] DO |
| X1 := Walls[i].X1 ; |
| Y1 := Walls[i].Y1 ; |
| X2 := Walls[i].X2 ; |
| Y2 := Walls[i].Y2 |
| END ; |
| INC(i) |
| END |
| END |
| END CopyWallsToLines ; |
| |
| |
| (* |
| CopyLinesToWalls - copies the lines buffer into the walls of room r. |
| *) |
| |
| PROCEDURE CopyLinesToWalls (r: CARDINAL) ; |
| BEGIN |
| WITH Rooms[r] DO |
| NoOfWalls := 0 ; |
| WHILE NoOfLines>0 DO |
| IF NOT IsNulLine(NoOfLines) |
| THEN |
| INC(NoOfWalls) ; |
| WITH Lines[NoOfLines] DO |
| Walls[NoOfWalls].X1 := X1 ; |
| Walls[NoOfWalls].Y1 := Y1 ; |
| Walls[NoOfWalls].X2 := X2 ; |
| Walls[NoOfWalls].Y2 := Y2 |
| END |
| END ; |
| DEC(NoOfLines) |
| END |
| END |
| END CopyLinesToWalls ; |
| |
| |
| (* |
| IsTouching - returns true if room r1 and r2 touch each other. |
| *) |
| |
| PROCEDURE IsTouching (r1, r2: CARDINAL) : BOOLEAN ; |
| VAR |
| i, j: CARDINAL ; |
| ok : BOOLEAN ; |
| BEGIN |
| ok := FALSE ; |
| i := 1 ; |
| WHILE (NOT ok) AND (i<=Rooms[r1].NoOfWalls) DO |
| j := 1 ; |
| WHILE (NOT ok) AND (j<=Rooms[r2].NoOfWalls) DO |
| ok := IsIntersection(Rooms[r1].Walls[i].X1, Rooms[r1].Walls[i].Y1, |
| Rooms[r1].Walls[i].X2, Rooms[r1].Walls[i].Y2, |
| Rooms[r2].Walls[j].X1, Rooms[r2].Walls[j].Y1, |
| Rooms[r2].Walls[j].X2, Rooms[r2].Walls[j].Y2) ; |
| INC(j) |
| END ; |
| INC(i) |
| END ; |
| RETURN( ok ) |
| END IsTouching ; |
| |
| |
| (* |
| IsIntersection - returns true if the line x1, y1, x2, y2 touches |
| line X1, Y1, X2, Y2. |
| This routine does not consider perpendicular |
| intersections. |
| *) |
| |
| PROCEDURE IsIntersection (x1, y1, x2, y2, X1, Y1, X2, Y2: CARDINAL) : BOOLEAN ; |
| BEGIN |
| Assert(x1#0) ; |
| Assert(X1#0) ; |
| IF IsVertical(x1, y1, x2, y2) AND IsVertical(X1, Y1, X2, Y2) AND |
| (x1=X1) |
| THEN |
| RETURN( IsIntersectingRange(y1, y2, Y1, Y2) ) |
| ELSIF IsHorizontal(x1, y1, x2, y2) AND IsHorizontal(X1, Y1, X2, Y2) AND |
| (y1=Y1) |
| THEN |
| RETURN( IsIntersectingRange(x1, x2, X1, X2) ) |
| ELSE |
| RETURN( FALSE ) |
| END |
| END IsIntersection ; |
| |
| |
| (* |
| IsVertical - returns true if line x1, y1, x2, y2 is vertical. |
| *) |
| |
| PROCEDURE IsVertical (x1, y1, x2, y2: CARDINAL) : BOOLEAN ; |
| BEGIN |
| RETURN( (x1=x2) AND (y1#y2) ) |
| END IsVertical ; |
| |
| |
| (* |
| IsHorizontal - returns true if line x1, y1, x2, y2 is horizontal. |
| *) |
| |
| PROCEDURE IsHorizontal (x1, y1, x2, y2: CARDINAL) : BOOLEAN ; |
| BEGIN |
| RETURN( (y1=y2) AND (x1#x2) ) |
| END IsHorizontal ; |
| |
| |
| (* |
| Adjacent - tests whether two rooms r1 & r2 are adjacent. |
| *) |
| |
| PROCEDURE Adjacent (r1, r2: CARDINAL) : BOOLEAN ; |
| VAR |
| i: CARDINAL ; |
| BEGIN |
| WITH Rooms[r1] DO |
| i := NoOfDoors ; |
| WHILE i>0 DO |
| IF Doors[i].LeadsTo=r2 |
| THEN |
| RETURN( TRUE ) |
| ELSE |
| DEC(i) |
| END |
| END |
| END ; |
| RETURN( FALSE ) |
| END Adjacent ; |
| |
| |
| PROCEDURE Stop ; |
| BEGIN |
| HALT |
| END Stop ; |
| |
| |
| END RoomMap. |