(* 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. *)
MODULE Semantic ;
FROM SYSTEM IMPORT ADR ;
FROM libc IMPORT exit, system ;
FROM StrLib IMPORT StrCopy, StrConCat ;
FROM StrIO IMPORT WriteString, WriteLn ;
FROM NumberIO IMPORT WriteCard ;
FROM Args IMPORT GetArg ;
FROM libc IMPORT system ;
(*
FROM FIO IMPORT File, OpenToWrite, Close, Exists, ReportError, WriteShort,
WriteChar, IsNoError ;
*)
FROM FIO IMPORT File, OpenToWrite, Close, Exists, WriteChar, IsNoError ;
FROM AdvMap IMPORT ReadAdvMap, Rooms, DoorStatus, ActualNoOfRooms,
MaxNoOfTreasures, Treasure ;
CONST
MaxFileName = 4096 ;
VAR
ErrorInRoom: BOOLEAN ;
PROCEDURE GetOppositeDoor (r, x1, y1, x2, y2: CARDINAL ;
VAR doorno: CARDINAL ; VAR ok: BOOLEAN) ;
VAR
xok, yok: BOOLEAN ;
BEGIN
ok := FALSE ;
doorno := 1 ;
WITH Rooms[r] DO
WHILE (NOT ok) AND (doorno<=NoOfDoors) DO
xok := (x1=Doors[doorno].Position.X1) AND
(x2=Doors[doorno].Position.X2) ;
yok := (y1=Doors[doorno].Position.Y1) AND
(y2=Doors[doorno].Position.Y2) ;
IF xok AND yok
THEN
ok := TRUE
ELSE
INC( doorno )
END
END
END
END GetOppositeDoor ;
PROCEDURE GetWallOnDoor (r, x1, y1, x2, y2: CARDINAL ;
VAR ok: BOOLEAN) ;
VAR
wallno: CARDINAL ;
BEGIN
ok := FALSE ;
wallno := 1 ;
WITH Rooms[r] DO
WHILE (NOT ok) AND (wallno<=NoOfWalls) DO
WITH Walls[wallno] DO
IF (Walls[wallno].X1=x1) AND (Walls[wallno].X2=x2)
THEN
IF (Walls[wallno].Y1<=y1) AND (Walls[wallno].Y2>=y2)
THEN
ok := TRUE
END
END ;
IF (Walls[wallno].Y1=y1) AND (Walls[wallno].Y2=y2)
THEN
IF (Walls[wallno].X1<=x1) AND (Walls[wallno].X2>=x2)
THEN
ok := TRUE
END
END ;
INC( wallno )
END
END
END
END GetWallOnDoor ;
PROCEDURE HorizWallOnDoor (r, x1, y1: CARDINAL ;
VAR ok: BOOLEAN) ;
VAR
wallno: CARDINAL ;
BEGIN
ok := FALSE ;
wallno := 1 ;
WITH Rooms[r] DO
WHILE (NOT ok) AND (wallno<=NoOfWalls) DO
WITH Walls[wallno] DO
IF (Walls[wallno].X1=Walls[wallno].X2) AND (x1=Walls[wallno].X1)
THEN
IF (Walls[wallno].Y1<=y1) AND (Walls[wallno].Y2>=y1)
THEN
ok := TRUE
END
END
END ;
INC( wallno )
END
END
END HorizWallOnDoor ;
PROCEDURE VertWallOnDoor (r, x1, y1: CARDINAL ;
VAR ok: BOOLEAN) ;
VAR
wallno: CARDINAL ;
BEGIN
ok := FALSE ;
wallno := 1 ;
WITH Rooms[r] DO
WHILE (NOT ok) AND (wallno<=NoOfWalls) DO
WITH Walls[wallno] DO
IF (Walls[wallno].Y1=Walls[wallno].Y2) AND (y1=Walls[wallno].Y1)
THEN
IF (Walls[wallno].X1<=x1) AND (Walls[wallno].X2>=x1)
THEN
ok := TRUE
END
END
END ;
INC( wallno )
END
END
END VertWallOnDoor ;
(*
AnalyzeSemantic -
*)
PROCEDURE AnalyzeSemantic ;
VAR
room: CARDINAL ;
BEGIN
FOR room := 1 TO ActualNoOfRooms DO
AnalyzeRoom(room)
END
END AnalyzeSemantic ;
(*
AnalyzeRoom -
*)
PROCEDURE AnalyzeRoom (room: CARDINAL) ;
VAR
door: CARDINAL ;
BEGIN
WITH Rooms[room] DO
IF NoOfDoors#0
THEN
FOR door := 1 TO NoOfDoors DO
AnalyzeDoor(room, door)
END
END
END
END AnalyzeRoom ;
(*
AnalyzeDoor -
*)
PROCEDURE AnalyzeDoor (room, door: CARDINAL) ;
VAR
OtherDoor,
i : CARDINAL ;
ok : BOOLEAN ;
BEGIN
WITH Rooms[room] DO
WITH Doors[door] DO
IF LeadsTo#0
THEN
GetOppositeDoor( LeadsTo, Position.X1, Position.Y1,
Position.X2, Position.Y2 ,OtherDoor, ok ) ;
IF ok
THEN
IF StateOfDoor#Rooms[LeadsTo].Doors[OtherDoor].StateOfDoor
THEN
WriteString('Inconsistant Door STATUS in room') ;
WriteCard( room, 6 ) ; WriteString('Door NO.') ;
WriteCard( door, 6 ) ; WriteLn ;
ErrorInRoom := TRUE
END
ELSE
WriteString('Inconsistant Door LEADSTO in room') ;
WriteCard( room, 6 ) ; WriteString(' Door NO.') ;
WriteCard( door, 6 ) ; WriteString(' - OR -') ;WriteLn ;
WriteString('Inconsistant Door COORDS in room') ;
WriteCard( room, 6 ) ; WriteString(' Door NO.') ;
WriteCard( door, 6 ) ; WriteLn ;
ErrorInRoom := TRUE
END ;
GetWallOnDoor( room, Position.X1, Position.Y1,
Position.X2, Position.Y2, ok ) ;
IF NOT ok
THEN
WriteString('Door NOT ON WALL in room') ;
WriteCard( room, 6 ) ; WriteString(' Door NO.') ;
WriteCard( door, 6 ) ; WriteLn ;
ErrorInRoom := TRUE
END ;
IF Position.X1=Position.X2
THEN
i := Position.Y1 ;
REPEAT
VertWallOnDoor( LeadsTo, Position.X1, i, ok ) ;
INC( i ) ;
UNTIL ok OR (i>Position.Y2)
ELSE
i := Position.X1 ;
REPEAT
HorizWallOnDoor( LeadsTo, i, Position.Y1, ok ) ;
INC( i )
UNTIL ok OR (i>Position.X2)
END ;
IF ok
THEN
WriteString('Adjacent Room CONFLICT with DOOR in ROOM') ;
WriteCard( room, 6 ) ; WriteString(' Door NO.') ;
WriteCard( door, 6 ) ; WriteLn ;
WriteString('Adjacent Room is') ; WriteCard( LeadsTo, 6 ) ;
WriteLn ;
ErrorInRoom := TRUE
END
END
END
END
END AnalyzeDoor ;
(*
(*
CrunchRooms -
*)
PROCEDURE CrunchRooms (f: File) ;
VAR
room: CARDINAL ;
BEGIN
WriteShort(f, ActualNoOfRooms) ;
FOR room := 1 TO ActualNoOfRooms DO
CrunchRoom(f, room)
END
END CrunchRooms ;
(*
CrunchRoom -
*)
PROCEDURE CrunchRoom (f: File; room: CARDINAL) ;
VAR
i: CARDINAL ;
BEGIN
WITH Rooms[room] DO
WriteShort(f, NoOfWalls) ;
FOR i := 1 TO NoOfWalls DO
CrunchWall(f, room, i)
END ;
WriteShort(f, NoOfDoors) ;
FOR i := 1 TO NoOfDoors DO
CrunchDoor(f, room, i)
END
END
END CrunchRoom ;
(*
CrunchDoor -
*)
PROCEDURE CrunchDoor (f: File; room: CARDINAL; doorno: CARDINAL) ;
BEGIN
WITH Rooms[room].Doors[doorno] DO
WriteShort(f, Position.X1) ;
WriteShort(f, Position.Y1) ;
WriteShort(f, Position.X2) ;
WriteShort(f, Position.Y2) ;
WriteShort(f, LeadsTo) ;
WriteChar(f, VAL(CHAR, StateOfDoor))
END
END CrunchDoor ;
(*
CrunchWall -
*)
PROCEDURE CrunchWall (f: File; room: CARDINAL; wallno: CARDINAL) ;
BEGIN
WITH Rooms[room].Walls[wallno] DO
WriteShort(f, X1) ;
WriteShort(f, Y1) ;
WriteShort(f, X2) ;
WriteShort(f, Y2)
END
END CrunchWall ;
(*
CrunchTreasures -
*)
PROCEDURE CrunchTreasures (f: File) ;
VAR
i: CARDINAL ;
BEGIN
FOR i := 1 TO MaxNoOfTreasures DO
WITH Treasure[i] DO
WriteShort(f, Xpos) ;
WriteShort(f, Ypos) ;
WriteShort(f, Rm)
END
END
END CrunchTreasures ;
(*
CrunchMap -
*)
PROCEDURE CrunchMap (a: ARRAY OF CHAR) ;
VAR
f: File ;
c: ARRAY [0..MaxFileName] OF CHAR ;
BEGIN
StrConCat(a, '.bin', a) ;
IF Exists(a)
THEN
StrCopy('/bin/rm -f ', c) ;
StrConCat(c, a, c) ;
IF system(ADR(c))#0
THEN
WriteString('failed to ') ; WriteString(c) ; WriteLn ;
exit(1)
END
END ;
f := OpenToWrite(a) ;
IF IsNoError(f)
THEN
CrunchRooms(f) ;
CrunchTreasures(f) ;
Close(f)
ELSE
WriteString('error when opening ') ; WriteString(a) ;
WriteString(' for writing: ') ; ReportError(f) ; WriteLn
END
END CrunchMap ;
*)
VAR
FileName: ARRAY [0..MaxFileName] OF CHAR ;
BEGIN
IF GetArg(FileName, 1)
THEN
IF ReadAdvMap(FileName)
THEN
ErrorInRoom := FALSE ;
AnalyzeSemantic ;
(*
IF NOT ErrorInRoom
THEN
CrunchMap(FileName)
END
*)
END
END
END Semantic.