1 (* Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010
2 Free Software Foundation, Inc. *)
3 (* This file is part of GNU Modula-2.
5 GNU Modula-2 is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License as published by the Free
7 Software Foundation; either version 3, or (at your option) any later
10 GNU Modula-2 is distributed in the hope that it will be useful, but WITHOUT ANY
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 You should have received a copy of the GNU General Public License along
16 with gm2; see the file COPYING. If not, write to the Free Software
17 Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *)
19 IMPLEMENTATION MODULE AdvMap ;
23 FROM Scan IMPORT WriteError, GetNextSymbol, OpenSource, CloseSource ;
24 FROM StrIO IMPORT ReadString, WriteString, WriteLn ;
25 FROM NumberIO IMPORT WriteCard ;
26 FROM StrLib IMPORT StrEqual, StrLen, StrCopy ;
27 FROM ASCII IMPORT cr, lf, nul, EOL ;
31 CurrentRoom : CARDINAL ;
32 CurrentSymbol : ARRAY [0..20] OF CHAR ;
33 FatelError : BOOLEAN ;
36 (* IncPosition increments the x,y coordinates according *)
37 (* the Direction sent. *)
39 PROCEDURE IncPosition (VAR x, y: CARDINAL ; Dir: CARDINAL) ;
58 (* Adjacent tests whether two rooms R1 & R2 are adjacent *)
59 (* Assume that access to map has been granted. *)
61 PROCEDURE Adjacent (R1, R2: CARDINAL) : BOOLEAN ;
63 i, r1, r2 : CARDINAL ;
69 WHILE (i>0) AND (NOT ok) DO
70 IF Doors[i].LeadsTo=R2
82 (* The following procedures test and read the syntax marking out the *)
83 (* map of the adventure game. Displaying syntactic errors if occurred *)
86 ReadAdvMap - read map, Name, into memory.
87 TRUE is returned if the operation was successful.
90 PROCEDURE ReadAdvMap (Name: ARRAY OF CHAR) : BOOLEAN ;
94 Success := OpenSource(Name) ;
97 GetNextSymbol(CurrentSymbol) ;
98 WHILE (NOT StrEqual( CurrentSymbol, 'END.' )) AND (NOT FatelError) DO
100 GetNextSymbol(CurrentSymbol)
103 Success := NOT FatelError
105 WriteString('cannot open: ') ; WriteString(Name) ; WriteLn
115 IF NOT StrEqual( CurrentSymbol, 'ROOM' )
117 WriteError('ROOM --- Expected') ;
120 GetNextSymbol(CurrentSymbol) ;
122 IF (CurrentRoom<1) OR (CurrentRoom>MaxNoOfRooms)
124 WriteError('Out Of Range Error - Room No.') ;
126 WriteString('Non Recoverable Error') ;
129 WITH Rooms[CurrentRoom] DO
134 GetNextSymbol(CurrentSymbol) ;
136 WHILE (NOT StrEqual( CurrentSymbol, 'END' )) AND
138 IF StrEqual( CurrentSymbol, 'WALL' )
141 ELSIF StrEqual( CurrentSymbol, 'DOOR' )
144 ELSIF StrEqual( CurrentSymbol, 'TREASURE' )
148 WriteError('WALL, DOOR, TREASURE, END --- Expected') ;
150 GetNextSymbol(CurrentSymbol)
166 GetNextSymbol(CurrentSymbol) ;
167 WITH Rooms[CurrentRoom] DO
170 IF NoOfWalls>WallsPerRoom
172 WriteError('Out Of Range Error - Too Many Walls') ;
174 WriteString('Non Recoverable Error') ;
178 GetNextSymbol(CurrentSymbol) ;
180 GetNextSymbol(CurrentSymbol) ;
182 GetNextSymbol(CurrentSymbol) ;
185 IF (x1#x2) AND (y1#y2)
187 WriteError('Diagonal Wall --- Not Allowed') ;
191 (* Always have the lowest value of x in x1 OR y in y1 *)
193 IF (x1<x2) OR (y1<y2)
195 Walls[NoOfWalls].X1 := x1 ;
196 Walls[NoOfWalls].Y1 := y1 ;
197 Walls[NoOfWalls].X2 := x2 ;
198 Walls[NoOfWalls].Y2 := y2
200 Walls[NoOfWalls].X1 := x2 ;
201 Walls[NoOfWalls].Y1 := y2 ;
202 Walls[NoOfWalls].X2 := x1 ;
203 Walls[NoOfWalls].Y2 := y1
206 GetNextSymbol(CurrentSymbol) ;
207 UNTIL StrEqual( CurrentSymbol, 'WALL' ) OR
208 StrEqual( CurrentSymbol, 'DOOR' ) OR
209 StrEqual( CurrentSymbol, 'TREASURE' ) OR
210 StrEqual( CurrentSymbol, 'END' ) OR
224 GetNextSymbol(CurrentSymbol) ;
225 WITH Rooms[CurrentRoom] DO
228 IF NoOfDoors>DoorsPerRoom
230 WriteError('Out Of Range Error - Too Many Doors') ;
232 WriteString('Non Recoverable Error') ;
236 GetNextSymbol(CurrentSymbol) ;
238 GetNextSymbol(CurrentSymbol) ;
240 GetNextSymbol(CurrentSymbol) ;
243 IF (x1#x2) AND (y1#y2)
245 WriteError('Diagonal Door --- Not Allowed') ;
249 (* Always have the lowest value of x in x1 OR y in y1 *)
251 IF (x1<x2) OR (y1<y2)
253 Doors[NoOfDoors].Position.X1 := x1 ;
254 Doors[NoOfDoors].Position.Y1 := y1 ;
255 Doors[NoOfDoors].Position.X2 := x2 ;
256 Doors[NoOfDoors].Position.Y2 := y2
258 Doors[NoOfDoors].Position.X1 := x2 ;
259 Doors[NoOfDoors].Position.Y1 := y2 ;
260 Doors[NoOfDoors].Position.X2 := x1 ;
261 Doors[NoOfDoors].Position.Y2 := y1
263 GetNextSymbol(CurrentSymbol) ;
264 IF NOT StrEqual( CurrentSymbol, 'STATUS' )
266 WriteError('STATUS --- Expected') ;
269 GetNextSymbol(CurrentSymbol) ;
270 IF StrEqual( CurrentSymbol, 'CLOSED' )
272 Doors[NoOfDoors].StateOfDoor := Closed
273 ELSIF StrEqual( CurrentSymbol, 'SECRET' )
275 Doors[NoOfDoors].StateOfDoor := Secret
276 ELSIF StrEqual( CurrentSymbol, 'OPEN' )
278 Doors[NoOfDoors].StateOfDoor := Open
280 WriteError('Illegal Door Status')
282 GetNextSymbol(CurrentSymbol) ;
283 IF NOT StrEqual( CurrentSymbol, 'LEADS' )
285 WriteError('LEADS --- Expected') ;
288 GetNextSymbol(CurrentSymbol) ;
289 IF NOT StrEqual( CurrentSymbol, 'TO' )
291 WriteError('TO --- Expected') ;
294 GetNextSymbol(CurrentSymbol) ;
298 WriteError('Out Of Range Error - Room No.') ;
301 Doors[NoOfDoors].LeadsTo := x1
304 GetNextSymbol(CurrentSymbol) ;
305 UNTIL StrEqual( CurrentSymbol, 'DOOR' ) OR
306 StrEqual( CurrentSymbol, 'WALL' ) OR
307 StrEqual( CurrentSymbol, 'TREASURE' ) OR
308 StrEqual( CurrentSymbol, 'END' ) OR
315 PROCEDURE ReadTreasure ;
317 x, y, TreasureNo: CARDINAL ;
321 GetNextSymbol(CurrentSymbol) ;
323 WITH Rooms[CurrentRoom] DO
324 IF NOT StrEqual( CurrentSymbol, 'AT' )
326 WriteError('AT --- Expected') ;
329 GetNextSymbol(CurrentSymbol) ;
331 GetNextSymbol(CurrentSymbol) ;
333 GetNextSymbol(CurrentSymbol) ;
334 IF NOT StrEqual( CurrentSymbol, 'IS' )
336 WriteError('IS --- Expected') ;
339 GetNextSymbol(CurrentSymbol) ;
340 ReadCard( TreasureNo ) ;
342 IF (TreasureNo<=MaxNoOfTreasures) AND (TreasureNo>0)
344 (* Tell Room about treasures *)
346 INCL( Treasures, TreasureNo ) ;
348 (* Tell Treasures about Treasures! and Room *)
350 Treasure[TreasureNo].Xpos := x ;
351 Treasure[TreasureNo].Ypos := y ;
352 Treasure[TreasureNo].Rm := CurrentRoom ;
354 WriteError('Out Of Range Error - Treasure No.') ;
358 GetNextSymbol(CurrentSymbol) ;
359 UNTIL StrEqual( CurrentSymbol, 'WALL' ) OR
360 StrEqual( CurrentSymbol, 'DOOR' ) OR
361 StrEqual( CurrentSymbol, 'TREASURE' ) OR
362 StrEqual( CurrentSymbol, 'END' ) OR
368 PROCEDURE ReadRoomNo ;
372 ReadCard( CurrentRoom ) ;
373 IF (CurrentRoom>0) AND (CurrentRoom<=MaxNoOfRooms)
375 IF CurrentRoom>ActualNoOfRooms
377 ActualNoOfRooms := CurrentRoom
384 PROCEDURE ReadCard (VAR c: CARDINAL) ;
394 High := HIGH(CurrentSymbol) ;
396 ch := CurrentSymbol[i] ;
397 IF (ch>='0') AND (ch<='9')
399 c := c*10+ORD(ch)-ORD('0')
402 WriteError('Cardinal Number Expected') ;
406 UNTIL (i>High) OR (ch=nul) ;
413 ActualNoOfRooms := 0 ;