1
2(********************************************************************)
3(*                                                                  *)
4(*  castle.sd7    Castle Adventure                                  *)
5(*  Copyright (C) 2004, 2005  Thomas Mertes                         *)
6(*                                                                  *)
7(*  This program is free software; you can redistribute it and/or   *)
8(*  modify it under the terms of the GNU General Public License as  *)
9(*  published by the Free Software Foundation; either version 2 of  *)
10(*  the License, or (at your option) any later version.             *)
11(*                                                                  *)
12(*  This program is distributed in the hope that it will be useful, *)
13(*  but WITHOUT ANY WARRANTY; without even the implied warranty of  *)
14(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   *)
15(*  GNU General Public License for more details.                    *)
16(*                                                                  *)
17(*  You should have received a copy of the GNU General Public       *)
18(*  License along with this program; if not, write to the           *)
19(*  Free Software Foundation, Inc., 51 Franklin Street,             *)
20(*  Fifth Floor, Boston, MA  02110-1301, USA.                       *)
21(*                                                                  *)
22(********************************************************************)
23
24
25$ include "seed7_05.s7i";
26  include "osfiles.s7i";
27  include "float.s7i";
28  include "draw.s7i";
29  include "keybd.s7i";
30  include "dialog.s7i";
31  include "pic32.s7i";
32  include "time.s7i";
33  include "duration.s7i";
34
35
36const integer: ROOM_LINES        is  18;
37const integer: ROOM_COLUMNS      is  24;
38
39const integer: INVENTORY_LINE    is  16;
40
41const integer: MAX_STRENGTH      is 200;
42
43const integer: MAX_INVENTORY     is   6;
44const integer: PIXMAP_SIZE       is  32;
45const integer: STEP_SIZE         is  16;
46const integer: BORDER_DIST       is  20;
47const integer: LEGEND_XPOS       is 2 * BORDER_DIST + ROOM_COLUMNS * PIXMAP_SIZE + 16;
48const integer: LEGEND_YPOS_MIN   is   8;
49const integer: LEGEND_COLUMN     is (LEGEND_XPOS + PIXMAP_SIZE) div 6 + 3;
50const integer: BUTTONS_1_XPOS    is LEGEND_XPOS - 3 * 96;
51const integer: BUTTONS_2_XPOS    is LEGEND_XPOS - 2 * 96;
52const integer: BUTTONS_3_XPOS    is LEGEND_XPOS - 96;
53const integer: BUTTONS_1_COLUMN  is (BUTTONS_1_XPOS + PIXMAP_SIZE) div 6 + 3;
54const integer: BUTTONS_2_COLUMN  is (BUTTONS_2_XPOS + PIXMAP_SIZE) div 6 + 3;
55const integer: BUTTONS_3_COLUMN  is (BUTTONS_3_XPOS + PIXMAP_SIZE) div 6 + 3;
56const integer: BUTTON_YPOS_MIN   is 2 * BORDER_DIST + ROOM_LINES * PIXMAP_SIZE + 16;
57const integer: BUTTON_TEXT_LINE1 is BUTTON_YPOS_MIN div 16 + 2;
58
59const type: directionType is new enum
60    NORTH, SOUTH, EAST, WEST, UP, DOWN
61  end enum;
62
63const func string: str (in directionType: direction) is
64  return str(ord(direction));
65
66const func directionType: (attr directionType) parse (in string: stri) is
67  return directionType conv (integer(stri));
68
69enable_io(directionType);
70
71
72const type: itemType is new enum
73    NO_ITEM, BOOK, CRYSTAL_BALL, GLASSES, HELMET,
74    KEY, LAMP, MAGIC_WAND, SWORD, WINE_FLASK,
75    CROWN, DIAMOND, FANCY_GOBLET, GOLDBAR, HARP,
76    HOLY_CROSS, HOURGLASS, JADE_FIGURINE, LARGE_GEM,
77    NECKLACE, RUBYS, SCEPTER, SILVER_BARS
78  end enum;
79
80const itemType: MIN_ITEM is succ(itemType.first);
81const itemType: MAX_ITEM is itemType.last;
82
83
84const type: monsterType is new enum
85    NO_MONSTER, ANGRY_DEMON1, ANGRY_DEMON2,
86    UGLY_OGRE1, UGLY_OGRE2, BIG_SPIDER,
87    SMALL_SPIDER, SNAKE, BAT, VAMPIRE,
88    FAIRY1, FAIRY2, DOOR1, DOOR2, DOOR3, DOOR4
89  end enum;
90
91const monsterType: MIN_MONSTER is succ(monsterType.first);
92const monsterType: MAX_MONSTER is monsterType.last;
93
94
95(* Rooms *)
96const integer: NO_ROOM            is  0;
97const integer: COURTYARD          is  1;
98const integer: WEST_BALLROOM      is  4;
99const integer: WEST_DINING_ROOM   is  8;
100const integer: KITCHEN            is  9;
101const integer: CHEFS_QUARTERS     is 10;
102const integer: STORAGE_ROOM       is 11;
103const integer: MUSEUM             is 12;
104const integer: THRONE_ROOM        is 14;
105const integer: GARDEN_NORTH       is 17;
106const integer: GARDEN_SOUTH       is 18;
107const integer: UPPER_HALL_CENTER  is 19;
108const integer: UPPER_HALL_WEST    is 20;
109const integer: UPPER_HALL_EAST    is 21;
110const integer: GUARDS_HALL        is 22;
111const integer: KNIGHTS_HALL       is 24;
112const integer: LOWER_BATTLEMENT   is 26;
113const integer: CORRIDOR28         is 28;
114const integer: GUEST_ROOM         is 29;
115const integer: BALCONY            is 33;
116const integer: RED_ROOM           is 37;
117const integer: YELLOW_ROOM        is 40;
118const integer: CORRIDOR52         is 52;
119const integer: CORRIDOR54         is 54;
120const integer: KINGS_STUDY        is 56;
121const integer: EMPTY_ROOM         is 57;
122const integer: LIBRARY_WEST_END   is 58;
123const integer: LIBRARY_EAST_END   is 59;
124const integer: CASTLE_WALL        is 60;
125const integer: WEST_TOWER_MIDDLE  is 62;
126const integer: EAST_TOWER_TOP     is 65;
127const integer: LABORATORY         is 66;
128const integer: SORCERERS_QUARTERS is 67;
129const integer: WINE_CELLAR        is 68;
130const integer: MAZE70             is 70;
131const integer: MAZE73             is 73;
132const integer: MAZE74             is 74;
133const integer: WINDING_PASSAGE1   is 76;
134const integer: WINDING_PASSAGE2   is 77;
135const integer: WINDING_PASSAGE3   is 78;
136const integer: TORTURE_ROOM       is 79;
137const integer: DUNGEON_ENTRANCE   is 82;
138const integer: SECRET_ROOM        is 83;
139const integer: ESCAPED            is 84;
140const integer: CASTLE             is 85;
141const integer: MAX_ROOM           is 85;
142
143
144const type: itemSet is set of itemType;
145
146const func string: str (in itemSet: aSet) is
147  return str(bitset conv aSet);
148
149const func itemSet: (attr itemSet) parse (in string: stri) is
150  return itemSet conv (bitset(stri));
151
152enable_io(itemSet);
153
154
155const type: graphObj is new struct
156    var string: name is "";
157    var string: adjective is "";
158    var array string: picture is 0 times "";
159    var PRIMITIVE_WINDOW: pixmap is PRIMITIVE_WINDOW.value;
160    var integer: xPos is 0;
161    var integer: yPos is 0;
162    var PRIMITIVE_WINDOW: saved_pixmap is PRIMITIVE_WINDOW.value;
163    var integer: saved_xPos is 0;
164    var integer: saved_yPos is 0;
165  end struct;
166
167const type: itemObj is sub graphObj struct
168    var itemType: ident is NO_ITEM;
169    var integer: room_num is 0;
170  end struct;
171
172const type: monsterObj is sub graphObj struct
173    var monsterType: ident is NO_MONSTER;
174    var integer: attack is 0;
175    var integer: strength is 0;
176    var integer: room_num is 0;
177    var directionType: direction is NORTH;
178    var boolean: living is FALSE;
179  end struct;
180
181const type: playerObj is sub graphObj struct
182    var integer: room is 0;
183    var directionType: direction is NORTH;
184    var itemSet: inventory is itemSet.EMPTY_SET;
185    var integer: strength is 0;
186    var boolean: living is TRUE;
187  end struct;
188
189const type: roomType is new struct
190    var array string: data is ROOM_LINES times "";
191    var array string: description is 5 times "";
192    var array [directionType] integer: exits is directionType times 0;
193  end struct;
194
195const type: scoreType is new struct
196    var string: name is "";
197    var integer: points is 0;
198  end struct;
199
200
201var text: screen is STD_NULL;
202var array [itemType] itemObj: item is itemType times itemObj.value;
203var array [monsterType] monsterObj: monster is monsterType times monsterObj.value;
204var playerObj: player is playerObj.value;
205var array roomType: room is MAX_ROOM times roomType.value;
206var scoreType: highScore is scoreType.value;
207var graphObj: stair_up is graphObj.value;
208var graphObj: stair_down is graphObj.value;
209
210var array string: message is 0 times "";
211var boolean: flaskFilled is FALSE;
212var boolean: exitGame is FALSE;
213
214var PRIMITIVE_WINDOW: query_pixmap is PRIMITIVE_WINDOW.value;
215var PRIMITIVE_WINDOW: wall_pixmap is PRIMITIVE_WINDOW.value;
216var PRIMITIVE_WINDOW: colored_wall1_pixmap is PRIMITIVE_WINDOW.value;
217var PRIMITIVE_WINDOW: colored_wall2_pixmap is PRIMITIVE_WINDOW.value;
218var PRIMITIVE_WINDOW: vertical_pixmap is PRIMITIVE_WINDOW.value;
219var PRIMITIVE_WINDOW: horizontal_pixmap is PRIMITIVE_WINDOW.value;
220var PRIMITIVE_WINDOW: left_upper_pixmap is PRIMITIVE_WINDOW.value;
221var PRIMITIVE_WINDOW: right_upper_pixmap is PRIMITIVE_WINDOW.value;
222var PRIMITIVE_WINDOW: left_lower_pixmap is PRIMITIVE_WINDOW.value;
223var PRIMITIVE_WINDOW: right_lower_pixmap is PRIMITIVE_WINDOW.value;
224var PRIMITIVE_WINDOW: railing_pixmap is PRIMITIVE_WINDOW.value;
225var PRIMITIVE_WINDOW: gate_pixmap is PRIMITIVE_WINDOW.value;
226var PRIMITIVE_WINDOW: small_bush_pixmap is PRIMITIVE_WINDOW.value;
227var PRIMITIVE_WINDOW: big_bush_pixmap is PRIMITIVE_WINDOW.value;
228var PRIMITIVE_WINDOW: statue_pixmap is PRIMITIVE_WINDOW.value;
229var PRIMITIVE_WINDOW: fountain_pixmap is PRIMITIVE_WINDOW.value;
230var PRIMITIVE_WINDOW: wood_pixmap is PRIMITIVE_WINDOW.value;
231var PRIMITIVE_WINDOW: stone_pixmap is PRIMITIVE_WINDOW.value;
232var PRIMITIVE_WINDOW: gray_pixmap is PRIMITIVE_WINDOW.value;
233var PRIMITIVE_WINDOW: water_pixmap is PRIMITIVE_WINDOW.value;
234var PRIMITIVE_WINDOW: bed_left_pixmap is PRIMITIVE_WINDOW.value;
235var PRIMITIVE_WINDOW: bed_right_pixmap is PRIMITIVE_WINDOW.value;
236var PRIMITIVE_WINDOW: bed_top_pixmap is PRIMITIVE_WINDOW.value;
237var PRIMITIVE_WINDOW: bed_bottom_pixmap is PRIMITIVE_WINDOW.value;
238var PRIMITIVE_WINDOW: bed_white_middle_pixmap is PRIMITIVE_WINDOW.value;
239var PRIMITIVE_WINDOW: bed_red_middle_pixmap is PRIMITIVE_WINDOW.value;
240var PRIMITIVE_WINDOW: bed_blue_middle_pixmap is PRIMITIVE_WINDOW.value;
241var PRIMITIVE_WINDOW: bed_purple_middle_pixmap is PRIMITIVE_WINDOW.value;
242var PRIMITIVE_WINDOW: bed_yellow_middle_pixmap is PRIMITIVE_WINDOW.value;
243var PRIMITIVE_WINDOW: chain_pixmap is PRIMITIVE_WINDOW.value;
244var PRIMITIVE_WINDOW: k_pixmap is PRIMITIVE_WINDOW.value;
245var PRIMITIVE_WINDOW: b_pixmap is PRIMITIVE_WINDOW.value;
246var PRIMITIVE_WINDOW: floor_pixmap is PRIMITIVE_WINDOW.value;
247var PRIMITIVE_WINDOW: eye_pixmap is PRIMITIVE_WINDOW.value;
248var PRIMITIVE_WINDOW: hand_pixmap is PRIMITIVE_WINDOW.value;
249var PRIMITIVE_WINDOW: take_pixmap is PRIMITIVE_WINDOW.value;
250var PRIMITIVE_WINDOW: drop_pixmap is PRIMITIVE_WINDOW.value;
251var PRIMITIVE_WINDOW: load_pixmap is PRIMITIVE_WINDOW.value;
252var PRIMITIVE_WINDOW: save_pixmap is PRIMITIVE_WINDOW.value;
253var PRIMITIVE_WINDOW: exit_pixmap is PRIMITIVE_WINDOW.value;
254
255
256const array string: query_pic is [](
257  "  WWWW  ",
258  " W    W ",
259  " W    W ",
260  "    WW  ",
261  "   WW   ",
262  "   WW   ",
263  "        ",
264  "   WW   ");
265
266
267const array string: wall_pic is [](
268  "WBBBBBBBWBBBBBBB",
269  "WBBBBBBBWBBBBBBB",
270  "WBBBBBBBWBBBBBBB",
271  "WWWWWWWWWWWWWWWW",
272  "RRRRWRRRRRRRWRRR",
273  "RRRRWRRRRRRRWRRR",
274  "RRRRWRRRRRRRWRRR",
275  "WWWWWWWWWWWWWWWW",
276  "WBBBBBBBWBBBBBBB",
277  "WBBBBBBBWBBBBBBB",
278  "WBBBBBBBWBBBBBBB",
279  "WWWWWWWWWWWWWWWW",
280  "RRRRWRRRRRRRWRRR",
281  "RRRRWRRRRRRRWRRR",
282  "RRRRWRRRRRRRWRRR",
283  "WWWWWWWWWWWWWWWW");
284
285
286const array string: colored_wall1_pic is [](
287  "WGGGGGGGWMMMMMMM",
288  "WGGGGGGGWMMMMMMM",
289  "WGGGGGGGWMMMMMMM",
290  "WWWWWWWWWWWWWWWW",
291  "RRRRWmmmmmmmWBBB",
292  "RRRRWmmmmmmmWBBB",
293  "RRRRWmmmmmmmWBBB",
294  "WWWWWWWWWWWWWWWW",
295  "WgggggggWOOOOOOO",
296  "WgggggggWOOOOOOO",
297  "WgggggggWOOOOOOO",
298  "WWWWWWWWWWWWWWWW",
299  "YYYYWbbbbbbbWBBB",
300  "YYYYWbbbbbbbWBBB",
301  "YYYYWbbbbbbbWBBB",
302  "WWWWWWWWWWWWWWWW");
303
304
305const array string: colored_wall2_pic is [](
306  "WgggggggWOOOOOOO",
307  "WgggggggWOOOOOOO",
308  "WgggggggWOOOOOOO",
309  "WWWWWWWWWWWWWWWW",
310  "BBBBWbbbbbbbWRRR",
311  "BBBBWbbbbbbbWRRR",
312  "BBBBWbbbbbbbWRRR",
313  "WWWWWWWWWWWWWWWW",
314  "WGGGGGGGWMMMMMMM",
315  "WGGGGGGGWMMMMMMM",
316  "WGGGGGGGWMMMMMMM",
317  "WWWWWWWWWWWWWWWW",
318  "BBBBWrrrrrrrWYYY",
319  "BBBBWrrrrrrrWYYY",
320  "BBBBWrrrrrrrWYYY",
321  "WWWWWWWWWWWWWWWW");
322
323
324const array string: vertical_pic is [](
325  "       WW       ",
326  "       WW       ",
327  "       WW       ",
328  "       WW       ",
329  "       WW       ",
330  "       WW       ",
331  "       WW       ",
332  "       WW       ",
333  "       WW       ",
334  "       WW       ",
335  "       WW       ",
336  "       WW       ",
337  "       WW       ",
338  "       WW       ",
339  "       WW       ",
340  "       WW       ");
341
342
343const array string: horizontal_pic is [](
344  "                ",
345  "                ",
346  "                ",
347  "                ",
348  "                ",
349  "                ",
350  "                ",
351  "WWWWWWWWWWWWWWWW",
352  "WWWWWWWWWWWWWWWW",
353  "                ",
354  "                ",
355  "                ",
356  "                ",
357  "                ",
358  "                ",
359  "                ");
360
361
362const array string: left_upper_pic is [](
363  "                ",
364  "                ",
365  "                ",
366  "                ",
367  "                ",
368  "                ",
369  "                ",
370  "       WWWWWWWWW",
371  "       WWWWWWWWW",
372  "       WW       ",
373  "       WW       ",
374  "       WW       ",
375  "       WW       ",
376  "       WW       ",
377  "       WW       ",
378  "       WW       ");
379
380
381const array string: right_upper_pic is [](
382  "                ",
383  "                ",
384  "                ",
385  "                ",
386  "                ",
387  "                ",
388  "                ",
389  "WWWWWWWWW       ",
390  "WWWWWWWWW       ",
391  "       WW       ",
392  "       WW       ",
393  "       WW       ",
394  "       WW       ",
395  "       WW       ",
396  "       WW       ",
397  "       WW       ");
398
399
400const array string: left_lower_pic is [](
401  "       WW       ",
402  "       WW       ",
403  "       WW       ",
404  "       WW       ",
405  "       WW       ",
406  "       WW       ",
407  "       WW       ",
408  "       WWWWWWWWW",
409  "       WWWWWWWWW",
410  "                ",
411  "                ",
412  "                ",
413  "                ",
414  "                ",
415  "                ",
416  "                ");
417
418
419const array string: right_lower_pic is [](
420  "       WW       ",
421  "       WW       ",
422  "       WW       ",
423  "       WW       ",
424  "       WW       ",
425  "       WW       ",
426  "       WW       ",
427  "WWWWWWWWW       ",
428  "WWWWWWWWW       ",
429  "                ",
430  "                ",
431  "                ",
432  "                ",
433  "                ",
434  "                ",
435  "                ");
436
437
438const array string: railing_pic is [](
439  "       WW       ",
440  "       WW       ",
441  "       WW       ",
442  "       WW       ",
443  "       WW       ",
444  "       WW       ",
445  "       WW       ",
446  "       WWWWWWWWW",
447  "       WWWWWWWWW",
448  "       WW       ",
449  "       WW       ",
450  "       WW       ",
451  "       WW       ",
452  "       WW       ",
453  "       WW       ",
454  "       WW       ");
455
456
457const array string: gate_pic is [](
458  "                ",
459  "                ",
460  "                ",
461  "                ",
462  "                ",
463  " bbbbbbbbbbbbbb ",
464  "bbbbbrrrrrbbbrrr",
465  "brrrrbbbbbrrrbbb",
466  "bbbbbbrrrbbbbbbb",
467  "rrrrrrbbbrrrrrbb",
468  " bbbbbbbbbbbbbb ",
469  "                ",
470  "                ",
471  "                ",
472  "                ",
473  "                ");
474
475
476const array string: small_bush_pic is [](
477  "     G GG       ",
478  "   G  GG  GG  G ",
479  " G  G  G G   G  ",
480  "  GGGG GG G GGG ",
481  "      GG  GGG   ",
482  " GGG   G G   GG ",
483  "   GGG GG GG GGG",
484  " G  G GG  G G   ",
485  " G  GG G  GG G G",
486  "GG GG Gg  g  GG ",
487  " G  g  g g   G  ",
488  "GGG  g ggGG GGGG",
489  "   g  gg   g    ",
490  "    g  g  gGG   ",
491  "     g g g      ",
492  "      ggg       ");
493
494
495const array string: big_bush_pic is [](
496  "   G G GG  GG   ",
497  "  GG  GG  gG GG ",
498  " G  g  gGg G gG ",
499  "  GGgg gg g ggGG",
500  "GG    gg  ggg   ",
501  " GgGG Gg gG  GgG",
502  "   ggG gg gg ggG",
503  "GG  g gg  g g   ",
504  "GgG gg gG gg G G",
505  "Gg gg gb  bG gG ",
506  " g  b  b b   g  ",
507  "GggG b bbgG ggGG",
508  "   b  bb   b    ",
509  "  GGb  b  bgGG  ",
510  "     b b b      ",
511  "      bbb       ");
512
513
514const array string: wood_pic is [](
515  "bbbbbbbbbbbbbbrr",
516  "rrbbbbbrrrrbbbbb",
517  "bbrrrrrbbbbrrrbb",
518  "bbbbbbbbbbbbbbbb",
519  "rrrbbbbbbbbbbbbb",
520  "bbbrrbbbbrrrrrrb",
521  "bbbbbrrrrrbbbbbb",
522  "bbbbbbbbbbbbrrrr",
523  "rrrrbbbbbrrrbbbb",
524  "bbbbrrrrrbbbbbbb",
525  "bbbbbbbbbbbbbrrr",
526  "rrbbbbbbrrrrrbbb",
527  "bbbbbbbbbbbbbbbb",
528  "bbbrrrrbbbbbrrrb",
529  "rrrbbbbrrrrrbbbb",
530  "bbbbbbbbbbbbbbbb");
531
532
533const array string: stone_pic is [](
534  "xxxxxxxxxWxxxxxx",
535  "xxxxxxxxxWxxxxxx",
536  "xxxxxxxxxWxxxxxx",
537  "xxxxxxxxxWxxxxxx",
538  "WWWWWWWWWWWWWWWW",
539  "xxxWxxxxxxxxxxxx",
540  "xxxWxxxxxxxxxxxx",
541  "xxxWxxxxxxxxxxxx",
542  "xxxWxxxxxxxxxxxx",
543  "xxxWxxxxxxxxxxxx",
544  "WWWWWWWWWWWWWWWW",
545  "xxxxxxxxxxxxWxxx",
546  "xxxxxxxxxxxxWxxx",
547  "xxxxxxxxxxxxWxxx",
548  "xxxxxxxxxxxxWxxx",
549  "WWWWWWWWWWWWWWWW");
550
551
552const array string: gray_pic is [](
553  "xxxxxxxxxxxxxxxx",
554  "xxxxxxxxxxxxxxxx",
555  "xxxxxxxxxxxxxxxx",
556  "xxxxxxxxxxxxxxxx",
557  "xxxxxxxxxxxxxxxx",
558  "xxxxxxxxxxxxxxxx",
559  "xxxxxxxxxxxxxxxx",
560  "xxxxxxxxxxxxxxxx",
561  "xxxxxxxxxxxxxxxx",
562  "xxxxxxxxxxxxxxxx",
563  "xxxxxxxxxxxxxxxx",
564  "xxxxxxxxxxxxxxxx",
565  "xxxxxxxxxxxxxxxx",
566  "xxxxxxxxxxxxxxxx",
567  "xxxxxxxxxxxxxxxx",
568  "xxxxxxxxxxxxxxxx");
569
570
571const array string: water_pic is [](
572  "BBBBBBBBBBBBBBBB",
573  "BBBBBBBBBBBBBBBB",
574  "BBBBBBBBBBBBBBBB",
575  "BBBBBBBBBBBBBBBB",
576  "BBBBBBBBBBBBBBBB",
577  "BBBBBBBBBBBBBBBB",
578  "BBBBBBBBBBBBBBBB",
579  "BBBBBBBBBBBBBBBB",
580  "BBBBBBBBBBBBBBBB",
581  "BBBBBBBBBBBBBBBB",
582  "BBBBBBBBBBBBBBBB",
583  "BBBBBBBBBBBBBBBB",
584  "BBBBBBBBBBBBBBBB",
585  "BBBBBBBBBBBBBBBB",
586  "BBBBBBBBBBBBBBBB",
587  "BBBBBBBBBBBBBBBB");
588
589
590const array string: bed_left_pic is [](
591  "            bbbb",
592  "            bbbb",
593  "            bbbb",
594  "            bbbb",
595  "             bb ",
596  "             bb ",
597  "             bb ",
598  "             bb ",
599  "             bb ",
600  "             bb ",
601  "             bb ",
602  "             bb ",
603  "            bbbb",
604  "            bbbb",
605  "            bbbb",
606  "            bbbb");
607
608
609const array string: bed_right_pic is [](
610  "bbbb            ",
611  "bbbb            ",
612  "bbbb            ",
613  "bbbb            ",
614  " bb             ",
615  " bb             ",
616  " bb             ",
617  " bb             ",
618  " bb             ",
619  " bb             ",
620  " bb             ",
621  " bb             ",
622  "bbbb            ",
623  "bbbb            ",
624  "bbbb            ",
625  "bbbb            ");
626
627
628const array string: bed_top_pic is [](
629  "                ",
630  "                ",
631  "                ",
632  "                ",
633  "                ",
634  "                ",
635  "                ",
636  "                ",
637  "                ",
638  "                ",
639  "                ",
640  "                ",
641  "bbbb        bbbb",
642  "bbbbbbbbbbbbbbbb",
643  "bbbbbbbbbbbbbbbb",
644  "bbbb        bbbb");
645
646
647const array string: bed_bottom_pic is [](
648  "bbbb        bbbb",
649  "bbbbbbbbbbbbbbbb",
650  "bbbbbbbbbbbbbbbb",
651  "bbbb        bbbb",
652  "                ",
653  "                ",
654  "                ",
655  "                ",
656  "                ",
657  "                ",
658  "                ",
659  "                ",
660  "                ",
661  "                ",
662  "                ",
663  "                ");
664
665
666const array string: bed_white_middle_pic is [](
667  "WWWWWWWWWWWWWWWW",
668  "WWWWWWWWWWWWWWWW",
669  "WWWWWWWWWWWWWWWW",
670  "WWWWWWWWWWWWWWWW",
671  "WWWWWWWWWWWWWWWW",
672  "WWWWWWWWWWWWWWWW",
673  "WWWWWWWWWWWWWWWW",
674  "WWWWWWWWWWWWWWWW",
675  "WWWWWWWWWWWWWWWW",
676  "WWWWWWWWWWWWWWWW",
677  "WWWWWWWWWWWWWWWW",
678  "WWWWWWWWWWWWWWWW",
679  "WWWWWWWWWWWWWWWW",
680  "WWWWWWWWWWWWWWWW",
681  "WWWWWWWWWWWWWWWW",
682  "WWWWWWWWWWWWWWWW");
683
684
685const array string: bed_red_middle_pic is [](
686  "RRRRRRRRRRRRRRRR",
687  "RRRRRRRRRRRRRRRR",
688  "RRRRRRRRRRRRRRRR",
689  "RRRRRRRRRRRRRRRR",
690  "RRRRRRRRRRRRRRRR",
691  "RRRRRRRRRRRRRRRR",
692  "RRRRRRRRRRRRRRRR",
693  "RRRRRRRRRRRRRRRR",
694  "RRRRRRRRRRRRRRRR",
695  "RRRRRRRRRRRRRRRR",
696  "RRRRRRRRRRRRRRRR",
697  "RRRRRRRRRRRRRRRR",
698  "RRRRRRRRRRRRRRRR",
699  "RRRRRRRRRRRRRRRR",
700  "RRRRRRRRRRRRRRRR",
701  "RRRRRRRRRRRRRRRR");
702
703
704const array string: bed_blue_middle_pic is [](
705  "BBBBBBBBBBBBBBBB",
706  "BBBBBBBBBBBBBBBB",
707  "BBBBBBBBBBBBBBBB",
708  "BBBBBBBBBBBBBBBB",
709  "BBBBBBBBBBBBBBBB",
710  "BBBBBBBBBBBBBBBB",
711  "BBBBBBBBBBBBBBBB",
712  "BBBBBBBBBBBBBBBB",
713  "BBBBBBBBBBBBBBBB",
714  "BBBBBBBBBBBBBBBB",
715  "BBBBBBBBBBBBBBBB",
716  "BBBBBBBBBBBBBBBB",
717  "BBBBBBBBBBBBBBBB",
718  "BBBBBBBBBBBBBBBB",
719  "BBBBBBBBBBBBBBBB",
720  "BBBBBBBBBBBBBBBB");
721
722
723const array string: bed_purple_middle_pic is [](
724  "mmmmmmmmmmmmmmmm",
725  "mmmmmmmmmmmmmmmm",
726  "mmmmmmmmmmmmmmmm",
727  "mmmmmmmmmmmmmmmm",
728  "mmmmmmmmmmmmmmmm",
729  "mmmmmmmmmmmmmmmm",
730  "mmmmmmmmmmmmmmmm",
731  "mmmmmmmmmmmmmmmm",
732  "mmmmmmmmmmmmmmmm",
733  "mmmmmmmmmmmmmmmm",
734  "mmmmmmmmmmmmmmmm",
735  "mmmmmmmmmmmmmmmm",
736  "mmmmmmmmmmmmmmmm",
737  "mmmmmmmmmmmmmmmm",
738  "mmmmmmmmmmmmmmmm",
739  "mmmmmmmmmmmmmmmm");
740
741
742const array string: bed_yellow_middle_pic is [](
743  "YYYYYYYYYYYYYYYY",
744  "YYYYYYYYYYYYYYYY",
745  "YYYYYYYYYYYYYYYY",
746  "YYYYYYYYYYYYYYYY",
747  "YYYYYYYYYYYYYYYY",
748  "YYYYYYYYYYYYYYYY",
749  "YYYYYYYYYYYYYYYY",
750  "YYYYYYYYYYYYYYYY",
751  "YYYYYYYYYYYYYYYY",
752  "YYYYYYYYYYYYYYYY",
753  "YYYYYYYYYYYYYYYY",
754  "YYYYYYYYYYYYYYYY",
755  "YYYYYYYYYYYYYYYY",
756  "YYYYYYYYYYYYYYYY",
757  "YYYYYYYYYYYYYYYY",
758  "YYYYYYYYYYYYYYYY");
759
760
761const array string: chain_pic is [](
762  "        BBB   BB",
763  "       B   B B  ",
764  "       B  BBBBB ",
765  "       BB  B B  ",
766  "       BBBB   BB",
767  "      BB        ",
768  "    BBB         ",
769  "   B B B        ",
770  "   B   B        ",
771  "   B B B        ",
772  "    BBB         ",
773  "      BBBBB   BB",
774  "       BB  B B  ",
775  "       B  BBBBB ",
776  "       B   B B  ",
777  "        BBB   BB");
778
779
780const array string: k_pic is [](
781  " WW     ",
782  "  W     ",
783  "  W     ",
784  "  W  WW ",
785  "  W WW  ",
786  "  WWW   ",
787  "  W WW  ",
788  " WW  WW ");
789
790
791const array string: b_pic is [](
792  " WW     ",
793  "  W     ",
794  "  W     ",
795  "  WWWW  ",
796  "  W   W ",
797  "  W   W ",
798  "  W   W ",
799  " W WWW  ");
800
801
802const array string: up_pic is [](
803  "                  WddW          ",
804  "                  WdddW         ",
805  "                  WddddW        ",
806  "            WWWWWWWdddddW       ",
807  "            WW     WdddddW      ",
808  "            WdW     WdddddW     ",
809  "            WddW     WdddddW    ",
810  "            WdddW     WdddddWWWW",
811  "            WddddW     WddddW   ",
812  "      WWWWWWWdddddW     WdddW   ",
813  "      WW     WdddddW     WddW   ",
814  "      WdW     WdddddW     WdW   ",
815  "      WddW     WdddddW     WW   ",
816  "      WdddW     WdddddWWWWWWW   ",
817  "      WddddW     WddddW         ",
818  "WWWWWWWdddddW     WdddW        W",
819  "WW     WdddddW     WddW       W ",
820  "WdW     WdddddW     WdW      W  ",
821  "WddW     WdddddW     WW     W   ",
822  "WdddW     WdddddWWWWWWW    W    ",
823  "WddddW     WddddW         W     ",
824  "WdddddW     WdddW        W      ",
825  " WdddddW     WddW       W       ",
826  "  WdddddW     WdW      W        ",
827  "   WdddddW     WW     W         ",
828  "    WdddddWWWWWWW    W          ",
829  "     WddddW         W           ",
830  "      WdddW        W            ",
831  "       WddW       W             ",
832  "        WdW      W              ",
833  "         WW     W               ",
834  "          WWWWWW                ");
835
836
837const array string: down_pic is [](
838    "           WWWWWWWWWWWWWWWWWWWWW",
839    "          WW                    ",
840    "         WdW                    ",
841    "        WddW                    ",
842    "       WdddW           W        ",
843    "      WddddW            W       ",
844    "     WdddddWWWWWWW       W      ",
845    "    WdddddW     WW        W   W ",
846    "   WdddddW     WdW         W  W ",
847    "  WdddddW     WddW          W W ",
848    " WdddddW     WdddW           WW ",
849    "WdddddW     WddddW        WWWWW ",
850    "WddddW     WdddddWWWWWWW        ",
851    "WdddW     WdddddW     WW        ",
852    "WddW     WdddddW     WdW        ",
853    "WdW     WdddddW     WddW        ",
854    "WW     WdddddW     WdddW        ",
855    "WWWWWWWdddddW     WddddW        ",
856    "      WddddW     WdddddWWWWWWW  ",
857    "      WdddW     WdddddW     WW  ",
858    "      WddW     WdddddW     WdW  ",
859    "      WdW     WdddddW     WddW  ",
860    "      WW     WdddddW     WdddW  ",
861    "      WWWWWWWdddddW     WddddW  ",
862    "            WddddW     WdddddWWW",
863    "            WdddW     WdddddW   ",
864    "            WddW     WdddddW    ",
865    "            WdW     WdddddW     ",
866    "            WW     WdddddW      ",
867    "            WWWWWWWdddddW       ",
868    "                  WddddW        ",
869    "                  WdddW         ");
870
871
872const array string: big_spider_pic is [](
873  " B            B ",
874  "  B          B  ",
875  "   B        B   ",
876  "    B      B    ",
877  "     B    B     ",
878  "BBB   B  B   BBB",
879  "   BBBWWWWBBB   ",
880  "     WWWWWW     ",
881  "     WWWWWW     ",
882  "   BBBWWWWBBB   ",
883  "BBB   B  B   BBB",
884  "     B    B     ",
885  "    B      B    ",
886  "   B        B   ",
887  "  B          B  ",
888  " B            B ");
889
890
891const array string: small_spider_pic is [](
892  "                ",
893  "  B          B  ",
894  "   B        B   ",
895  "    B      B    ",
896  "     B    B     ",
897  " BBB  B  B  BBB ",
898  "    BBBWWBBB    ",
899  "      WWWW      ",
900  "    BBBWWBBB    ",
901  " BBB  B  B  BBB ",
902  "     B    B     ",
903  "    B      B    ",
904  "   B        B   ",
905  "  B          B  ",
906  "                ",
907  "                ");
908
909
910const array string: fairy_pic is [](
911  "  xxxx        YYYYY        xxxx ",
912  " xxccxx      YYYYYYY      xxccxx",
913  " xccccxx    YYWWWWWYY    xxccccx",
914  " xcccccxx   YYWBWBWYY   xxcccccx",
915  " xxcccccxx  YYWWWWWYY  xxcccccxx",
916  "  xccccccxx YYWOWOWYY xxccccccx ",
917  " xxccBcBccxx XWWOWWX xxcccccccxx",
918  " xcccccccccxxXXWWWXXxxcccccccccx",
919  " xccBcWcBcccWWWWWWWWWccccccccccx",
920  " xxcccRccccWWRRWWWRRWWccccccccxx",
921  "  xccBRBccWWRRRRWRRRRWWcccccccx ",
922  " xxcccRccWWWRRRRWRRRRWWWccccccxx",
923  " xccccRcWWWcxRRWWWRRxcWWWccccccx",
924  " xccccRWWWcxxXWWWWWXxxcWWWWccccx",
925  " xxccWWWWcxx XWWYWWX xxcWWWWccxx",
926  "  xccWWWcxx XWWWWWWWX xxcWWWccx ",
927  " xxcccccxx XRRRRRRRRRX xxcccccxx",
928  " xcccccxx  XWWRRRRRWWX  xxcccccx",
929  " xccccxx   XWWWRRRWWWX   xxccccx",
930  " xxccxx    XWWWWRWWWWX    xxccxx",
931  "  xxxx      XWWWXWWWX      xxxx ",
932  "            XWWWXWWWX           ",
933  "            XWWWXWWWX           ",
934  "            XWWWXWWWX           ",
935  "             XWWXWWX            ",
936  "             XWWXWWX            ",
937  "             XWWXWWX            ",
938  "             XWWXWWX            ",
939  "             XWWXWWX            ",
940  "             XWWXWWX            ",
941  "             XWWXWWX            ",
942  "            XWWWXWWWX           ");
943
944
945const array string: large_gem_pic is [](
946  "                ",
947  "  RRRR    RRRR  ",
948  " RrrrrR  RrrrrR ",
949  "RrrrrrrRRrrrrrrR",
950  "RrrrrrrrrrrrrrrR",
951  "RrrrrrrrrrrrrrrR",
952  "RrrrrrrrrrrrrrrR",
953  "RrrrrrrrrrrrrrrR",
954  " RrrrrrrrrrrrrR ",
955  "  RrrrrrrrrrrR  ",
956  "   RrrrrrrrrR   ",
957  "    RrrrrrrR    ",
958  "     RrrrrR     ",
959  "      RrrR      ",
960  "       RR       ",
961  "                ");
962
963
964const array string: floor_pic is [](
965  "        ",
966  "        ",
967  "        ",
968  "        ",
969  "        ",
970  "        ",
971  "        ",
972  "        ");
973
974
975const array string: player_pic is [](
976  "      bbbb      ",
977  "     bbbbbb     ",
978  "     bBOOBb     ",
979  "     OOOOOO     ",
980  "     OWWWWO     ",
981  "      OOOO      ",
982  "   xbbbbbbbbx   ",
983  "  xxbbbbbbbbxx  ",
984  " xx bbbbbbbb xx ",
985  "Ox  bbbbbbbb  xO",
986  "OO  bbbbbbbb  OO",
987  "     YY  YY     ",
988  "     YY  YY     ",
989  "     YY  YY     ",
990  "     YY  YY     ",
991  "   rrrr  rrrr   ");
992
993
994const func PRIMITIVE_WINDOW: createPixmap (in array string: pattern) is
995  return createPixmap(pattern, PIXMAP_SIZE div length(pattern), black);
996
997
998const proc: initRoomData is func
999  local
1000    var file: dat_file is STD_NULL;
1001    var integer: number is 0;
1002    var integer: line is 0;
1003    var directionType: direction is NORTH;
1004  begin
1005    dat_file := open(dir(PROGRAM) & "/castle.dat", "r");
1006    for number range 1 to MAX_ROOM do
1007      for line range 1 to ROOM_LINES do
1008        room[number].data[line] := getln(dat_file);
1009      end for;
1010      for line range 1 to 5 do
1011        room[number].description[line] := getln(dat_file);
1012      end for;
1013      for direction range NORTH to DOWN do
1014        read(dat_file, room[number].exits[direction]);
1015      end for;
1016    end for;
1017    close(dat_file);
1018  end func;
1019
1020
1021const proc: initMonster (
1022    in monsterType: monster_ident,
1023    in string: monster_adjective,
1024    in string: monster_name,
1025    in array string: monster_pic,
1026    in integer: monster_line,
1027    in integer: monster_column,
1028    in integer: monster_attack,
1029    in integer: monster_strength,
1030    in integer: monster_room_num) is func
1031  begin
1032    monster[monster_ident].ident     := monster_ident;
1033    monster[monster_ident].adjective := monster_adjective;
1034    monster[monster_ident].name      := monster_name;
1035    monster[monster_ident].picture   := monster_pic;
1036    monster[monster_ident].pixmap    := PRIMITIVE_WINDOW.value;
1037    monster[monster_ident].yPos      := pred(monster_line) * PIXMAP_SIZE;
1038    monster[monster_ident].xPos      := pred(monster_column) * PIXMAP_SIZE;
1039    monster[monster_ident].attack    := monster_attack;
1040    monster[monster_ident].strength  := monster_strength;
1041    monster[monster_ident].room_num  := monster_room_num;
1042    monster[monster_ident].direction := NORTH;
1043    monster[monster_ident].living    := TRUE;
1044  end func;
1045
1046
1047const proc: initMonsterData is func
1048  begin
1049    initMonster(ANGRY_DEMON1, "Angry", "Demon",   demon_pic,         7, 13, 5, 160, THRONE_ROOM);
1050    initMonster(ANGRY_DEMON2, "Angry", "Demon",   demon_pic,        10,  6, 5, 160, KNIGHTS_HALL);
1051    initMonster(UGLY_OGRE1,   "Ugly",  "Ogre",    ogre_pic,          9, 13, 4,  80, WEST_BALLROOM);
1052    initMonster(UGLY_OGRE2,   "Ugly",  "Ogre",    ogre_pic,         12, 12, 4,  80, UPPER_HALL_EAST);
1053    initMonster(BIG_SPIDER,   "Big",   "Spider",  big_spider_pic,   14, 18, 3,  80, MAZE73);
1054    initMonster(SMALL_SPIDER, "Small", "Spider",  small_spider_pic,  5, 17, 1,  60, MAZE70);
1055    initMonster(SNAKE,        "",      "Snake",   snake_pic,        14, 17, 3,  60, GARDEN_NORTH);
1056    initMonster(BAT,          "",      "Bat",     bat_pic,           7, 18, 2,  40, WINE_CELLAR);
1057    initMonster(VAMPIRE,      "",      "Vampire", vampire_pic,      10, 24, 0,   0, CORRIDOR28);
1058    initMonster(FAIRY1,       "",      "Fairy",   fairy_pic,        10,  1, 0,   0, CORRIDOR52);
1059    initMonster(FAIRY2,       "",      "Fairy",   fairy_pic,         1, 12, 0,   0, CORRIDOR54);
1060    initMonster(DOOR1,        "",      "Door",    grating_pic,      15,  9, 0,   0, WINE_CELLAR);
1061    initMonster(DOOR2,        "",      "",        grating_pic,      15, 10, 0,   0, WINE_CELLAR);
1062    initMonster(DOOR3,        "",      "Door",    grating_pic,       9, 14, 0,   0, DUNGEON_ENTRANCE);
1063    initMonster(DOOR4,        "",      "",        grating_pic,      10, 14, 0,   0, DUNGEON_ENTRANCE);
1064  end func;
1065
1066
1067const func itemType: (attr itemType) conv (in char: ch) is func
1068  result
1069    var itemType: item_ident is NO_ITEM;
1070  local
1071    var integer: number is 0;
1072  begin
1073    number := succ(ord(ch) - ord('a'));
1074    if number >= ord(MIN_ITEM) and number <= ord(MAX_ITEM) then
1075      item_ident := itemType conv number;
1076    end if;
1077  end func;
1078
1079
1080const func char: (attr char) conv (in itemType: anItem) is
1081  return chr(pred(ord('a') + ord(anItem)));
1082
1083
1084const proc: initItem (
1085    in itemType: item_ident,
1086    in string: item_name,
1087    in array string: item_pic,
1088    in integer: item_line,
1089    in integer: item_column,
1090    in integer: item_room_num) is func
1091  begin
1092    item[item_ident].ident    := item_ident;
1093    item[item_ident].name     := item_name;
1094    item[item_ident].picture  := item_pic;
1095    item[item_ident].pixmap   := PRIMITIVE_WINDOW.value;
1096    item[item_ident].yPos     := pred(item_line) * PIXMAP_SIZE;
1097    item[item_ident].xPos     := pred(item_column) * PIXMAP_SIZE;
1098    item[item_ident].room_num := item_room_num;
1099    if item_room_num <> NO_ROOM then
1100      room[item_room_num].data[item_line] @:= [item_column] char conv item_ident;
1101    end if;
1102  end func;
1103
1104
1105const proc: initItemData is func
1106  begin
1107    initItem(BOOK,          "Book",          book_pic,          11, 11, NO_ROOM); # LIBRARY_WEST_END
1108    initItem(CRYSTAL_BALL,  "Crystal Ball",  crystal_ball_pic,  13, 10, LABORATORY);
1109    initItem(GLASSES,       "Eye Glasses",   glasses_pic,       12, 18, NO_ROOM); # YELLOW_ROOM
1110    initItem(HELMET,        "Helmet",        helmet_pic,         5, 12, GUARDS_HALL);
1111    initItem(KEY,           "Key",           key_pic,            7, 12, NO_ROOM); # KINGS_STUDY
1112    initItem(LAMP,          "Lamp",          lamp_pic,          14, 19, GARDEN_NORTH);
1113    initItem(MAGIC_WAND,    "Magic Wand",    magic_wand_pic,     9,  4, KNIGHTS_HALL);
1114    initItem(SWORD,         "Sword",         sword_pic,          5, 11, MUSEUM);
1115    initItem(WINE_FLASK,    "Wine Flask",    flask_pic,         11,  8, NO_ROOM); # CHEFS_QUARTERS
1116    initItem(CROWN,         "Crown",         crown_pic,          5,  9, THRONE_ROOM);
1117    initItem(DIAMOND,       "Diamond",       diamond_pic,       10, 13, EMPTY_ROOM);
1118    initItem(FANCY_GOBLET,  "Fancy Goblet",  goblet_pic,        14,  6, WEST_DINING_ROOM);
1119    initItem(GOLDBAR,       "Goldbar",       goldbar_pic,       14, 23, MAZE74);
1120    initItem(HARP,          "Harp",          harp_pic,           8, 16, EAST_TOWER_TOP);
1121    initItem(HOLY_CROSS,    "Holy Cross",    holy_cross_pic,    13, 15, RED_ROOM);
1122    initItem(HOURGLASS,     "Hourglass",     hourglass_pic,     14,  6, UPPER_HALL_WEST);
1123    initItem(JADE_FIGURINE, "Jade Figurine", jade_figurine_pic, 10, 13, GUEST_ROOM);
1124    initItem(LARGE_GEM,     "Large Gem",     large_gem_pic,     10, 12, NO_ROOM); # GARDEN_SOUTH
1125    initItem(NECKLACE,      "Necklace",      necklace_pic,       9, 12, NO_ROOM); # UPPER_HALL_CENTER
1126    initItem(RUBYS,         "Ruby",          ruby_pic,          16,  4, CASTLE_WALL);
1127    initItem(SCEPTER,       "Scepter",       scepter_pic,       10, 12, SECRET_ROOM);
1128    initItem(SILVER_BARS,   "Silver Bars",   silver_bars_pic,    8,  7, LOWER_BATTLEMENT);
1129  end func;
1130
1131
1132const proc: initPlayerData is func
1133  begin
1134    player.pixmap := createPixmap(player_pic);
1135    player.xPos := 13 * PIXMAP_SIZE;
1136    player.yPos := 14 * PIXMAP_SIZE;
1137    player.saved_pixmap := PRIMITIVE_WINDOW.value;
1138    player.saved_xPos := 0;
1139    player.saved_yPos := 0;
1140    player.room := COURTYARD;
1141    player.direction := SOUTH;
1142    player.inventory := itemSet.EMPTY_SET;
1143    player.strength := MAX_STRENGTH;
1144    player.living := TRUE;
1145  end func;
1146
1147
1148const proc: loadHighScore is func
1149  local
1150    var file: aFile is STD_NULL;
1151  begin
1152    aFile := open("castle.scr", "r");
1153    if aFile <> STD_NULL then
1154      read(aFile, highScore.points);
1155      read(aFile, highScore.name);
1156      close(aFile);
1157    else
1158      highScore.name := "";
1159      highScore.points := 0;
1160    end if;
1161  end func;
1162
1163
1164const proc: saveHighScore is func
1165  local
1166    var file: aFile is STD_NULL;
1167  begin
1168    aFile := open("castle.scr", "w");
1169    if aFile <> STD_NULL then
1170      write(aFile, highScore.points);
1171      write(aFile, " ");
1172      writeln(aFile, highScore.name);
1173      close(aFile);
1174    end if;
1175  end func;
1176
1177
1178const proc: initGame is func
1179  begin
1180    query_pixmap := createPixmap(query_pic);
1181    wall_pixmap := createPixmap(wall_pic);
1182    colored_wall1_pixmap := createPixmap(colored_wall1_pic);
1183    colored_wall2_pixmap := createPixmap(colored_wall2_pic);
1184    vertical_pixmap := createPixmap(vertical_pic);
1185    horizontal_pixmap := createPixmap(horizontal_pic);
1186    left_upper_pixmap := createPixmap(left_upper_pic);
1187    right_upper_pixmap := createPixmap(right_upper_pic);
1188    left_lower_pixmap := createPixmap(left_lower_pic);
1189    right_lower_pixmap := createPixmap(right_lower_pic);
1190    railing_pixmap := createPixmap(railing_pic);
1191    gate_pixmap := createPixmap(gate_pic);
1192    small_bush_pixmap := createPixmap(small_bush_pic);
1193    big_bush_pixmap := createPixmap(big_bush_pic);
1194    statue_pixmap := createPixmap(statue_pic);
1195    fountain_pixmap := createPixmap(fountain_pic);
1196    wood_pixmap := createPixmap(wood_pic);
1197    stone_pixmap := createPixmap(stone_pic);
1198    gray_pixmap := createPixmap(gray_pic);
1199    water_pixmap := createPixmap(water_pic);
1200    bed_left_pixmap := createPixmap(bed_left_pic);
1201    bed_right_pixmap := createPixmap(bed_right_pic);
1202    bed_top_pixmap := createPixmap(bed_top_pic);
1203    bed_bottom_pixmap := createPixmap(bed_bottom_pic);
1204    bed_white_middle_pixmap := createPixmap(bed_white_middle_pic);
1205    bed_red_middle_pixmap := createPixmap(bed_red_middle_pic);
1206    bed_blue_middle_pixmap := createPixmap(bed_blue_middle_pic);
1207    bed_purple_middle_pixmap := createPixmap(bed_purple_middle_pic);
1208    bed_yellow_middle_pixmap := createPixmap(bed_yellow_middle_pic);
1209    chain_pixmap := createPixmap(chain_pic);
1210    k_pixmap := createPixmap(k_pic);
1211    b_pixmap := createPixmap(b_pic);
1212    floor_pixmap := createPixmap(floor_pic);
1213    eye_pixmap := createPixmap(eye_pic);
1214    hand_pixmap := createPixmap(hand_pic);
1215    take_pixmap := createPixmap(take_pic);
1216    drop_pixmap := createPixmap(drop_pic);
1217    load_pixmap := createPixmap(load_pic);
1218    save_pixmap := createPixmap(save_pic);
1219    exit_pixmap := createPixmap(exit_pic);
1220
1221    stair_up.pixmap := createPixmap(up_pic);
1222    stair_up.name := "Stairs up";
1223    stair_down.pixmap := createPixmap(down_pic);
1224    stair_down.name := "Stairs down";
1225
1226    message := 0 times "";
1227    exitGame := FALSE;
1228    flaskFilled := FALSE;
1229
1230    initRoomData;
1231    initMonsterData;
1232    initItemData;
1233    initPlayerData;
1234    loadHighScore;
1235  end func;
1236
1237
1238const proc: displayBox (in color: boxColor) is func
1239  local
1240    const integer: width is 2 * BORDER_DIST + ROOM_COLUMNS * PIXMAP_SIZE;
1241    const integer: height is 2 * BORDER_DIST + ROOM_LINES * PIXMAP_SIZE;
1242  begin
1243    hline(1, 0, width - 2, boxColor);
1244    vline(0, 1, height - 2, boxColor);
1245    hline(1, height - 1, width - 2, boxColor);
1246    vline(width - 1, 1, height - 2, boxColor);
1247    point(1, 1, boxColor);
1248    point(width - 2, 1, boxColor);
1249    point(width - 2, height - 2, boxColor);
1250    point(1, height - 2, boxColor);
1251  end func;
1252
1253
1254const func PRIMITIVE_WINDOW: getPixmap (inout graphObj: currObject) is func
1255  result
1256    var PRIMITIVE_WINDOW: pixmap is PRIMITIVE_WINDOW.value;
1257  begin
1258    if currObject.pixmap = PRIMITIVE_WINDOW.value then
1259      currObject.pixmap := createPixmap(currObject.picture,
1260          PIXMAP_SIZE div length(currObject.picture), black);
1261    end if;
1262    pixmap := currObject.pixmap;
1263  end func;
1264
1265
1266const proc: displayRoom (in roomType: current_room) is func
1267  local
1268    var integer: line is 0;
1269    var integer: column is 0;
1270    var char: ch is ' ';
1271    var PRIMITIVE_WINDOW: field_pixmap is PRIMITIVE_WINDOW.value;
1272    var itemType: item_ident is NO_ITEM;
1273    var integer: number is 0;
1274  begin
1275    for line range 1 to ROOM_LINES do
1276      for column range 1 to length(current_room.data[line]) do
1277        ch := current_room.data[line][column];
1278        if ch <> ' ' then
1279          case ch of
1280            when {'#'}: field_pixmap := wall_pixmap;
1281            when {':'}: field_pixmap := colored_wall1_pixmap;
1282            when {';'}: field_pixmap := colored_wall2_pixmap;
1283            when {'|'}: field_pixmap := vertical_pixmap;
1284            when {'-'}: field_pixmap := horizontal_pixmap;
1285            when {','}: field_pixmap := left_upper_pixmap;
1286            when {'.'}: field_pixmap := right_upper_pixmap;
1287            when {'`'}: field_pixmap := left_lower_pixmap;
1288            when {'''}: field_pixmap := right_lower_pixmap;
1289            when {'>'}: field_pixmap := railing_pixmap;
1290            when {'='}: field_pixmap := gate_pixmap;
1291            when {'+'}: field_pixmap := small_bush_pixmap;
1292            when {'*'}: field_pixmap := big_bush_pixmap;
1293            when {'$'}: field_pixmap := statue_pixmap;
1294            when {'?'}: field_pixmap := fountain_pixmap;
1295            when {'@'}: field_pixmap := wood_pixmap;
1296            when {'&'}: field_pixmap := stone_pixmap;
1297            when {'%'}: field_pixmap := gray_pixmap;
1298            when {'~'}: field_pixmap := water_pixmap;
1299            when {']'}: field_pixmap := bed_left_pixmap;
1300            when {'['}: field_pixmap := bed_right_pixmap;
1301            when {'_'}: field_pixmap := bed_top_pixmap;
1302            when {'^'}: field_pixmap := bed_bottom_pixmap;
1303            when {'W'}: field_pixmap := bed_white_middle_pixmap;
1304            when {'R'}: field_pixmap := bed_red_middle_pixmap;
1305            when {'N'}: field_pixmap := bed_blue_middle_pixmap;
1306            when {'P'}: field_pixmap := bed_purple_middle_pixmap;
1307            when {'Y'}: field_pixmap := bed_yellow_middle_pixmap;
1308            when {'{'}: field_pixmap := chain_pixmap;
1309            when {'K'}: field_pixmap := k_pixmap;
1310            when {'B'}: field_pixmap := b_pixmap;
1311            when {'U'}: field_pixmap := stair_up.pixmap;
1312            when {'D'}: field_pixmap := stair_down.pixmap;
1313            when {' '}: field_pixmap := floor_pixmap;
1314            when {'a' .. 'z'}:
1315              item_ident := itemType conv ch;
1316              if item_ident <> NO_ITEM then
1317                field_pixmap := getPixmap(item[item_ident]);
1318              else
1319                field_pixmap := query_pixmap;
1320              end if;
1321            otherwise:
1322              field_pixmap := query_pixmap;
1323              write("undefined char no ");
1324              writeln(ord(ch));
1325          end case;
1326          put(curr_win, BORDER_DIST + pred(column) * PIXMAP_SIZE,
1327              BORDER_DIST + pred(line) * PIXMAP_SIZE, field_pixmap);
1328        end if;
1329      end for;
1330    end for;
1331    rect(8, BUTTON_YPOS_MIN, 300, 50, black);
1332    color(white, black);
1333    for number range 1 to length(current_room.description) do
1334      setPos(screen, pred(BUTTON_TEXT_LINE1 + number), 2);
1335      write(screen, current_room.description[number]);
1336    end for;
1337  end func;
1338
1339
1340const proc: displayObj (inout graphObj: currObject) is func
1341  begin
1342    put(curr_win, BORDER_DIST + currObject.saved_xPos,
1343        BORDER_DIST + currObject.saved_yPos, currObject.saved_pixmap);
1344    currObject.saved_pixmap := getPixmap(BORDER_DIST + currObject.xPos,
1345        BORDER_DIST + currObject.yPos, PIXMAP_SIZE, PIXMAP_SIZE);
1346    put(curr_win, BORDER_DIST + currObject.xPos,
1347        BORDER_DIST + currObject.yPos, getPixmap(currObject));
1348    currObject.saved_xPos := currObject.xPos;
1349    currObject.saved_yPos := currObject.yPos;
1350  end func;
1351
1352
1353const proc: displayMonster is func
1354  local
1355    var monsterType: monster_ident is NO_MONSTER;
1356  begin
1357    for monster_ident range MIN_MONSTER to MAX_MONSTER do
1358      if monster[monster_ident].room_num = player.room then
1359        displayObj(monster[monster_ident]);
1360      end if;
1361    end for;
1362 end func;
1363
1364
1365const proc: objectLegend (inout graphObj: currObject, in integer: line) is func
1366  begin
1367    put(curr_win, LEGEND_XPOS, LEGEND_YPOS_MIN + pred(line) * PIXMAP_SIZE, getPixmap(currObject));
1368    color(white, black);
1369    setPos(screen, 2 * line, LEGEND_COLUMN);
1370    if currObject.adjective <> "" then
1371      write(screen, currObject.adjective & " " & currObject.name);
1372    else
1373      write(screen, currObject.name);
1374    end if;
1375  end func;
1376
1377
1378const proc: displayLegend is func
1379  local
1380    var monsterType: monster_ident is NO_MONSTER;
1381    var itemType: item_ident is NO_ITEM;
1382    var integer: line is 1;
1383  begin
1384    rect(LEGEND_XPOS, LEGEND_YPOS_MIN, 200, 576, black);
1385    for monster_ident range MIN_MONSTER to MAX_MONSTER do
1386      if monster[monster_ident].room_num = player.room and
1387          monster[monster_ident].name <> "" then
1388        objectLegend(monster[monster_ident], line);
1389        incr(line);
1390      end if;
1391    end for;
1392    for item_ident range MIN_ITEM to MAX_ITEM do
1393      if item[item_ident].room_num = player.room and
1394          not item_ident in player.inventory then
1395        objectLegend(item[item_ident], line);
1396        incr(line);
1397      end if;
1398    end for;
1399    if room[player.room].exits[UP] <> 0 then
1400      objectLegend(stair_up, line);
1401      incr(line);
1402    end if;
1403    if room[player.room].exits[DOWN] <> 0 then
1404      objectLegend(stair_down, line);
1405      incr(line);
1406    end if;
1407  end func;
1408
1409
1410const func integer: sizeOfLegend is func
1411  result
1412    var integer: line is 0;
1413  local
1414    var monsterType: monster_ident is NO_MONSTER;
1415    var itemType: item_ident is NO_ITEM;
1416  begin
1417    for monster_ident range MIN_MONSTER to MAX_MONSTER do
1418      if monster[monster_ident].room_num = player.room and
1419          monster[monster_ident].name <> "" then
1420        incr(line);
1421      end if;
1422    end for;
1423    for item_ident range MIN_ITEM to MAX_ITEM do
1424      if item[item_ident].room_num = player.room and
1425          not item_ident in player.inventory then
1426        incr(line);
1427      end if;
1428    end for;
1429    if room[player.room].exits[UP] <> 0 then
1430      incr(line);
1431    end if;
1432    if room[player.room].exits[DOWN] <> 0 then
1433      incr(line);
1434    end if;
1435  end func;
1436
1437
1438const proc: collectedTreasures is func
1439  local
1440    var itemType: item_ident is NO_ITEM;
1441    var integer: line is 1;
1442  begin
1443    rect(LEGEND_XPOS, 0, width(curr_win) - LEGEND_XPOS,
1444        BORDER_DIST + PIXMAP_SIZE * 14, black);
1445    color(white, black);
1446    setPos(screen, 2 * line - 1, LEGEND_COLUMN);
1447    write(screen, "You have collected");
1448    setPos(screen, 2 * line, LEGEND_COLUMN);
1449    write(screen, "these Treasures");
1450    incr(line);
1451    for item_ident range CROWN to MAX_ITEM do
1452      if item_ident in player.inventory or
1453          item[item_ident].room_num = COURTYARD then
1454        objectLegend(item[item_ident], line);
1455        incr(line);
1456      end if;
1457    end for;
1458    if line = 2 then
1459      color(white, black);
1460      setPos(screen, 2 * line, LEGEND_COLUMN);
1461      write(screen, "NONE");
1462    end if;
1463  end func;
1464
1465
1466const proc: killedMonsters is func
1467  local
1468    var monsterType: monster_ident is NO_MONSTER;
1469    var integer: line is 16;
1470  begin
1471    rect(LEGEND_XPOS, 15 * PIXMAP_SIZE, width(curr_win) - LEGEND_XPOS,
1472        BORDER_DIST + PIXMAP_SIZE * 7, black);
1473    color(white, black);
1474    setPos(screen, 2 * line - 1, LEGEND_COLUMN);
1475    write(screen, "You have killed");
1476    setPos(screen, 2 * line, LEGEND_COLUMN);
1477    write(screen, "these Monsters");
1478    incr(line);
1479    if not monster[ANGRY_DEMON1].living or not monster[ANGRY_DEMON2].living then
1480      objectLegend(monster[ANGRY_DEMON1], line);
1481      if not monster[ANGRY_DEMON1].living and not monster[ANGRY_DEMON2].living then
1482        setPos(screen, 2 * line, LEGEND_COLUMN + 15);
1483        write(screen, "two times");
1484      end if;
1485      incr(line);
1486    end if;
1487    if not monster[UGLY_OGRE1].living or not monster[UGLY_OGRE2].living then
1488      objectLegend(monster[UGLY_OGRE1], line);
1489      if not monster[UGLY_OGRE1].living and not monster[UGLY_OGRE2].living then
1490        setPos(screen, 2 * line, LEGEND_COLUMN + 15);
1491        write(screen, "two times");
1492      end if;
1493      incr(line);
1494    end if;
1495    for monster_ident range BIG_SPIDER to BAT do
1496      if not monster[monster_ident].living and
1497          monster[monster_ident].name <> "" then
1498        objectLegend(monster[monster_ident], line);
1499        incr(line);
1500      end if;
1501    end for;
1502    if line = 17 then
1503      color(white, black);
1504      setPos(screen, 2 * line, LEGEND_COLUMN);
1505      write(screen, "NONE");
1506    end if;
1507  end func;
1508
1509
1510const func integer: getInventoryStartLine is func
1511  result
1512    var integer: startLine is 0;
1513  begin
1514    startLine := succ(sizeOfLegend);
1515    if startLine < INVENTORY_LINE then
1516      startLine := INVENTORY_LINE;
1517    end if;
1518  end func;
1519
1520
1521const proc: displayInventoryItem (in integer: item_num) is func
1522  local
1523    var integer: item_line is 1;
1524    var itemType: item_ident is NO_ITEM;
1525  begin
1526    for item_ident range MIN_ITEM to MAX_ITEM do
1527      if item_ident in player.inventory then
1528        if item_line = item_num then
1529          objectLegend(item[item_ident], getInventoryStartLine + item_line);
1530        end if;
1531        incr(item_line);
1532      end if;
1533    end for;
1534  end func;
1535
1536
1537const proc: displayInventoryList is func
1538  local
1539    var integer: line is 0;
1540    var itemType: item_ident is NO_ITEM;
1541  begin
1542    line := succ(getInventoryStartLine);
1543    if player.inventory = itemSet.EMPTY_SET then
1544      color(white, black);
1545      setPos(screen, 2 * line, LEGEND_COLUMN);
1546      write(screen, "Nothing");
1547      incr(line);
1548    else
1549      for item_ident range MIN_ITEM to MAX_ITEM do
1550        if item_ident in player.inventory then
1551          objectLegend(item[item_ident], line);
1552          incr(line);
1553        end if;
1554      end for;
1555    end if;
1556  end func;
1557
1558
1559const proc: displayInventory is func
1560  local
1561    var integer: startLine is 0;
1562  begin
1563    startLine := getInventoryStartLine;
1564    rect(LEGEND_XPOS, LEGEND_YPOS_MIN + pred(startLine) * PIXMAP_SIZE,
1565        182, PIXMAP_SIZE * (card(player.inventory) + 2), black);
1566    color(white, black);
1567    setPos(screen, 2 * startLine, LEGEND_COLUMN);
1568    write(screen, "Inventory");
1569    displayInventoryList;
1570  end func;
1571
1572
1573const proc: displayMessage is func
1574  local
1575    var integer: number is 0;
1576  begin
1577    rect(186, BUTTON_YPOS_MIN, 346, 70, black);
1578    color(screen, white, black);
1579    for number range 1 to length(message) do
1580      setPos(screen, BUTTON_TEXT_LINE1 + pred(number), 32);
1581      write(screen, message[number]);
1582    end for;
1583  end func;
1584
1585
1586const proc: displayCommands (in PRIMITIVE_WINDOW: bmp) is func
1587  begin
1588    put(curr_win, BUTTONS_1_XPOS, BUTTON_YPOS_MIN, load_pixmap);
1589    setPos(screen, BUTTON_TEXT_LINE1, BUTTONS_1_COLUMN);
1590    write(screen, "Load");
1591    put(curr_win, BUTTONS_1_XPOS, BUTTON_YPOS_MIN + 32, save_pixmap);
1592    setPos(screen, BUTTON_TEXT_LINE1 + 2, BUTTONS_1_COLUMN);
1593    write(screen, "Save");
1594    put(curr_win, BUTTONS_1_XPOS, BUTTON_YPOS_MIN + 64, exit_pixmap);
1595    setPos(screen, BUTTON_TEXT_LINE1 + 4, BUTTONS_1_COLUMN);
1596    write(screen, "Exit");
1597    put(curr_win, BUTTONS_2_XPOS, BUTTON_YPOS_MIN, take_pixmap);
1598    setPos(screen, BUTTON_TEXT_LINE1, BUTTONS_2_COLUMN);
1599    write(screen, "Take");
1600    put(curr_win, BUTTONS_2_XPOS, BUTTON_YPOS_MIN + 32, drop_pixmap);
1601    setPos(screen, BUTTON_TEXT_LINE1 + 2, BUTTONS_2_COLUMN);
1602    write(screen, "Drop");
1603    put(curr_win, BUTTONS_3_XPOS, BUTTON_YPOS_MIN, eye_pixmap);
1604    setPos(screen, BUTTON_TEXT_LINE1, BUTTONS_3_COLUMN);
1605    write(screen, "Look");
1606    put(curr_win, BUTTONS_3_XPOS, BUTTON_YPOS_MIN + 32, hand_pixmap);
1607    setPos(screen, BUTTON_TEXT_LINE1 + 2, BUTTONS_3_COLUMN);
1608    write(screen, "Use");
1609  end func;
1610
1611
1612const proc: displayAll is func
1613  begin
1614    clear(curr_win, black);
1615    displayRoom(room[player.room]);
1616    displayMessage;
1617    displayMonster;
1618    displayObj(player);
1619    displayLegend;
1620    displayInventory;
1621    displayCommands(curr_win);
1622    displayBox(white);
1623  end func;
1624
1625
1626const proc: floodTrap is func
1627  local
1628    var string: s1 is "";
1629    var string: s2 is "";
1630    var integer: number is 0;
1631  begin
1632    s1 := room[WINDING_PASSAGE3].data[9];
1633    s2 := room[WINDING_PASSAGE3].data[10];
1634
1635    s1 @:= [12] '#';
1636    s1 @:= [24] '#';
1637    s2 @:= [12] '#';
1638    s2 @:= [24] '#';
1639
1640    room[WINDING_PASSAGE3].data[9] := s1;
1641    room[WINDING_PASSAGE3].data[10] := s2;
1642    for number range 13 to 23 do
1643      s1 @:= [number] '~';
1644      s2 @:= [number] '~';
1645
1646      room[WINDING_PASSAGE3].data[9] := s1;
1647      room[WINDING_PASSAGE3].data[10] := s2;
1648      displayAll;
1649    end for;
1650  end func;
1651
1652
1653const proc: checkRoom is func
1654  begin
1655    case player.room of
1656      when {WINDING_PASSAGE1}:
1657        room[WINDING_PASSAGE2].data[18] := "   #################### ";
1658      when {WINDING_PASSAGE3}:
1659        room[WINDING_PASSAGE2].data[18] := "   #################### ";
1660        if player.xPos = 544 and not NECKLACE in player.inventory then
1661          message := [] ("You have sprung a Trap!!");
1662          displayAll;
1663          floodTrap;
1664          message &:= [] ("The room has filled with water and you drowned!");
1665
1666          displayAll;
1667
1668          player.living := FALSE;
1669        end if;
1670      when {SECRET_ROOM}:
1671        room[WINDING_PASSAGE2].data[18] := "   ########  ########## ";
1672      when {WINDING_PASSAGE2}:
1673        if room[WINDING_PASSAGE2].data[18][12] = '#' and player.yPos > 512 then
1674          room[WINDING_PASSAGE2].data[18] := "   ########  ########## ";
1675        end if;
1676      when {WEST_TOWER_MIDDLE}:
1677        room[SORCERERS_QUARTERS].data[8]  := "######            |#    ";
1678        room[SORCERERS_QUARTERS].data[9]  := "                  |#    ";
1679        room[SORCERERS_QUARTERS].data[10] := "                  |#    ";
1680        room[SORCERERS_QUARTERS].data[11] := "######            |#    ";
1681      when {LABORATORY}:
1682        room[SORCERERS_QUARTERS].data[8]  := "######             #####";
1683        room[SORCERERS_QUARTERS].data[9]  := "                        ";
1684        room[SORCERERS_QUARTERS].data[10] := "                        ";
1685        room[SORCERERS_QUARTERS].data[11] := "######             #####";
1686      when {SORCERERS_QUARTERS}:
1687        if room[SORCERERS_QUARTERS].data[10][20] = '#' and player.xPos > 544 then
1688          room[SORCERERS_QUARTERS].data[8]  := "######             #####";
1689          room[SORCERERS_QUARTERS].data[9]  := "                        ";
1690          room[SORCERERS_QUARTERS].data[10] := "                        ";
1691          room[SORCERERS_QUARTERS].data[11] := "######             #####";
1692        end if;
1693    end case;
1694  end func;
1695
1696
1697const proc: hideItem (in itemObj: anItem) is func
1698  local
1699    var integer: line is 0;
1700    var integer: column is 0;
1701  begin
1702    if anItem.room_num <> NO_ROOM then
1703      line   := succ(anItem.yPos div PIXMAP_SIZE);
1704      column := succ(anItem.xPos div PIXMAP_SIZE);
1705      room[anItem.room_num].data[line] @:= [column] ' ';
1706    end if;
1707  end func;
1708
1709
1710const proc: showItem (in itemObj: anItem) is func
1711  local
1712    var integer: line is 0;
1713    var integer: column is 0;
1714  begin
1715    if anItem.room_num <> NO_ROOM then
1716      line   := succ(anItem.yPos div PIXMAP_SIZE);
1717      column := succ(anItem.xPos div PIXMAP_SIZE);
1718      room[anItem.room_num].data[line] @:= [column] char conv (anItem.ident);
1719    end if;
1720  end func;
1721
1722
1723const proc: loadGame is func
1724  local
1725    var file: load_file is STD_NULL;
1726    var monsterType: monster_ident is NO_MONSTER;
1727    var itemType: item_ident is NO_ITEM;
1728  begin
1729    if fileType("castle.sav") = FILE_REGULAR then
1730      if isOkay([]("Do you want to load a saved game.", "This will end the current game?")) then
1731        load_file := open("castle.sav", "r");
1732        for monster_ident range MIN_MONSTER to MAX_MONSTER do
1733          readln(load_file, monster[monster_ident].adjective);
1734          readln(load_file, monster[monster_ident].xPos);
1735          readln(load_file, monster[monster_ident].yPos);
1736          readln(load_file, monster[monster_ident].strength);
1737          readln(load_file, monster[monster_ident].direction);
1738          readln(load_file, monster[monster_ident].living);
1739        end for;
1740        for item_ident range MIN_ITEM to MAX_ITEM do
1741          hideItem(item[item_ident]);
1742          readln(load_file, item[item_ident].xPos);
1743          readln(load_file, item[item_ident].yPos);
1744          readln(load_file, item[item_ident].room_num);
1745        end for;
1746        readln(load_file, player.xPos);
1747        readln(load_file, player.yPos);
1748        readln(load_file, player.room);
1749        readln(load_file, player.direction);
1750        readln(load_file, player.inventory);
1751        readln(load_file, player.strength);
1752        close(load_file);
1753
1754        message := [] ("Game Loaded Successful!");
1755        for item_ident range MIN_ITEM to MAX_ITEM do
1756          if item_ident not in player.inventory then
1757            showItem(item[item_ident]);
1758          end if;
1759        end for;
1760        player.saved_pixmap := PRIMITIVE_WINDOW.value;
1761        checkRoom;
1762        displayAll;
1763      end if;
1764    else
1765      message := [] ("There Is No Saved Game To Load!");
1766      displayMessage;
1767    end if;
1768  end func;
1769
1770
1771const proc: saveGame is func
1772  local
1773    var file: save_file is STD_NULL;
1774    var monsterType: monster_ident is NO_MONSTER;
1775    var itemType: item_ident is NO_ITEM;
1776  begin
1777    if fileType("castle.sav") = FILE_REGULAR then
1778      if isOkay([]("Do you want to overwrite the", "game currently saved?")) then
1779        removeFile("castle.sav");
1780      end if;
1781    end if;
1782    if fileType("castle.sav") = FILE_ABSENT then
1783      save_file := open("castle.sav", "w");
1784      for monster_ident range MIN_MONSTER to MAX_MONSTER do
1785        writeln(save_file, monster[monster_ident].adjective);
1786        writeln(save_file, monster[monster_ident].xPos);
1787        writeln(save_file, monster[monster_ident].yPos);
1788        writeln(save_file, monster[monster_ident].strength);
1789        writeln(save_file, monster[monster_ident].direction);
1790        writeln(save_file, monster[monster_ident].living);
1791      end for;
1792      for item_ident range MIN_ITEM to MAX_ITEM do
1793        writeln(save_file, item[item_ident].xPos);
1794        writeln(save_file, item[item_ident].yPos);
1795        writeln(save_file, item[item_ident].room_num);
1796      end for;
1797      writeln(save_file, player.xPos);
1798      writeln(save_file, player.yPos);
1799      writeln(save_file, player.room);
1800      writeln(save_file, player.direction);
1801      writeln(save_file, player.inventory);
1802      writeln(save_file, player.strength);
1803      close(save_file);
1804
1805      message := [] ("Game Saved Successful!");
1806      displayMessage;
1807    end if;
1808  end func;
1809
1810
1811const func monsterType: searchMonster (in integer: xPos, in integer: yPos) is func
1812  result
1813    var monsterType: monsterFound is NO_MONSTER;
1814  local
1815    var monsterType: monster_ident is NO_MONSTER;
1816  begin
1817    for monster_ident range MIN_MONSTER to MAX_MONSTER do
1818      if monster[monster_ident].room_num = player.room and
1819          xPos >= monster[monster_ident].xPos and
1820          xPos < monster[monster_ident].xPos + PIXMAP_SIZE and
1821          yPos >= monster[monster_ident].yPos and
1822          yPos < monster[monster_ident].yPos + PIXMAP_SIZE then
1823        monsterFound := monster_ident;
1824      end if;
1825    end for;
1826  end func;
1827
1828
1829const func monsterType: hitMonster (in integer: xPos, in integer: yPos) is func
1830  result
1831    var monsterType: monsterMet is NO_MONSTER;
1832  local
1833    var monsterType: monster_ident is NO_MONSTER;
1834  begin
1835    for monster_ident range MIN_MONSTER to MAX_MONSTER do
1836      if monster[monster_ident].room_num = player.room and monster[monster_ident].living then
1837        if abs(xPos - monster[monster_ident].xPos) < PIXMAP_SIZE and
1838            abs(yPos - monster[monster_ident].yPos) < PIXMAP_SIZE then
1839          monsterMet := monster_ident;
1840        end if;
1841      end if;
1842    end for;
1843  end func;
1844
1845
1846const func itemType: selectItem (in PRIMITIVE_WINDOW: symbol, in string: name, in integer: invSize) is func
1847  result
1848    var itemType: itemSelected is NO_ITEM;
1849  local
1850    var char: command is ' ';
1851    var integer: startLine is 0;
1852    var integer: position is 0;
1853    var itemType: item_ident is NO_ITEM;
1854    var integer: count is 0;
1855    var boolean: getCommand is FALSE;
1856    var integer: xPos is 0;
1857    var integer: yPos is 0;
1858  begin
1859    if card(player.inventory) >= invSize then
1860      startLine := getInventoryStartLine;
1861      rect(LEGEND_XPOS, LEGEND_YPOS_MIN + pred(startLine) * PIXMAP_SIZE,
1862          PIXMAP_SIZE, PIXMAP_SIZE, black);
1863      box(LEGEND_XPOS - 3, LEGEND_YPOS_MIN + pred(startLine) * PIXMAP_SIZE - 3,
1864          187, succ(card(player.inventory))  * PIXMAP_SIZE + 6, light_red);
1865      rect(LEGEND_XPOS + PIXMAP_SIZE, LEGEND_YPOS_MIN + pred(startLine) * PIXMAP_SIZE,
1866          150, PIXMAP_SIZE, light_gray);
1867      put(curr_win, LEGEND_XPOS + PIXMAP_SIZE, LEGEND_YPOS_MIN + pred(startLine) * PIXMAP_SIZE,
1868          symbol);
1869      color(white, black);
1870      setPos(screen, 2 * startLine, LEGEND_COLUMN + 5);
1871      write(screen, name);
1872      displayInventoryList;
1873      position := 0;
1874      command := getc(KEYBOARD);
1875      while command not in {' ', KEY_NL, KEY_ESC} do
1876        getCommand := TRUE;
1877        rect(LEGEND_XPOS + PIXMAP_SIZE, LEGEND_YPOS_MIN + pred(startLine + position) * PIXMAP_SIZE,
1878            150, PIXMAP_SIZE, black);
1879        if position >= 1 then
1880          displayInventoryItem(position);
1881        else
1882          put(curr_win, LEGEND_XPOS + PIXMAP_SIZE, LEGEND_YPOS_MIN + pred(startLine) * PIXMAP_SIZE,
1883              symbol);
1884          color(white, black);
1885          setPos(screen, 2 * startLine, LEGEND_COLUMN + 5);
1886          write(screen, name);
1887        end if;
1888        if command = KEY_UP and position > 1 then
1889          decr(position);
1890        elsif command = KEY_DOWN and position < card(player.inventory) then
1891          incr(position);
1892        elsif command = KEY_MOUSE1 then
1893          xPos := getxpos(KEYBOARD);
1894          yPos := getypos(KEYBOARD);
1895          if xPos >= LEGEND_XPOS and xPos < LEGEND_XPOS + 128 and
1896              yPos >= LEGEND_YPOS_MIN + startLine * PIXMAP_SIZE and
1897              yPos <= LEGEND_YPOS_MIN + (startLine + card(player.inventory)) * PIXMAP_SIZE then
1898            position := (yPos - LEGEND_YPOS_MIN - startLine * PIXMAP_SIZE) div 32 + 1;
1899          else
1900            position := 0;
1901          end if;
1902          command := ' ';
1903          getCommand := FALSE;
1904        end if;
1905        rect(LEGEND_XPOS + PIXMAP_SIZE, LEGEND_YPOS_MIN + pred(startLine + position) * PIXMAP_SIZE,
1906            150, PIXMAP_SIZE, light_gray);
1907        if position >= 1 then
1908          displayInventoryItem(position);
1909        else
1910          put(curr_win, LEGEND_XPOS + PIXMAP_SIZE, LEGEND_YPOS_MIN + pred(startLine) * PIXMAP_SIZE,
1911              symbol);
1912          color(white, black);
1913          setPos(screen, 2 * startLine, LEGEND_COLUMN + 5);
1914          write(screen, name);
1915        end if;
1916        if getCommand then
1917          command := getc(KEYBOARD);
1918        end if;
1919      end while;
1920      rect(LEGEND_XPOS + PIXMAP_SIZE, LEGEND_YPOS_MIN + pred(startLine + position) * PIXMAP_SIZE,
1921          150, PIXMAP_SIZE, black);
1922      displayInventoryItem(position);
1923      if position >= 1  and command in {' ', KEY_NL} then
1924        count := 0;
1925        for item_ident range MIN_ITEM to MAX_ITEM do
1926          if item_ident in player.inventory then
1927            incr(count);
1928            if count = position then
1929              itemSelected := item_ident;
1930            end if;
1931          end if;
1932        end for;
1933      end if;
1934      rect(LEGEND_XPOS, LEGEND_YPOS_MIN + pred(startLine) * PIXMAP_SIZE,
1935          182, PIXMAP_SIZE, black);
1936      setPos(screen, 2 * startLine, LEGEND_COLUMN);
1937      color(white, black);
1938      write(screen, "Inventory");
1939      box(LEGEND_XPOS - 3, LEGEND_YPOS_MIN + pred(startLine) * PIXMAP_SIZE - 3,
1940          187, succ(card(player.inventory))  * PIXMAP_SIZE + 6, black);
1941    end if;
1942  end func;
1943
1944
1945const proc: dropItem (in itemType: item_ident) is func
1946  local
1947    var directionType: direction is NORTH;
1948    var integer: column is 0;
1949    var integer: line is 0;
1950
1951  begin
1952    direction := player.direction;
1953    repeat
1954      if direction = NORTH then
1955        line :=   player.yPos               div PIXMAP_SIZE;
1956        column := player.xPos               div PIXMAP_SIZE + 1;
1957        incr(direction);
1958      elsif direction = SOUTH then
1959        line :=   (player.yPos + STEP_SIZE) div PIXMAP_SIZE + 2;
1960        column := player.xPos               div PIXMAP_SIZE + 1;
1961        incr(direction);
1962      elsif direction = EAST then
1963        line :=   player.yPos               div PIXMAP_SIZE + 1;
1964        column := (player.xPos + STEP_SIZE) div PIXMAP_SIZE + 2;
1965        incr(direction);
1966      elsif direction = WEST then
1967        line :=   player.yPos               div PIXMAP_SIZE + 1;
1968        column := player.xPos               div PIXMAP_SIZE;
1969        direction := NORTH;
1970      end if;
1971    until line >= 1 and line <= ROOM_LINES and
1972        column >= 1 and column <= ROOM_COLUMNS and
1973        room[player.room].data[line][column] = ' ' and
1974        hitMonster(pred(column) * PIXMAP_SIZE, pred(line) * PIXMAP_SIZE) = NO_MONSTER or
1975        direction = player.direction;
1976    if room[player.room].data[line][column] = ' ' then
1977      item[item_ident].xPos := pred(column) * PIXMAP_SIZE;
1978      item[item_ident].yPos := pred(line)   * PIXMAP_SIZE;
1979      item[item_ident].room_num := player.room;
1980      showItem(item[item_ident]);
1981      excl(player.inventory, item_ident);
1982      put(curr_win, BORDER_DIST + item[item_ident].xPos,
1983          BORDER_DIST + item[item_ident].yPos, getPixmap(item[item_ident]));
1984      displayLegend;
1985      displayInventory;
1986    else
1987      displayInventory;
1988      message := [] ("Something is in the way!");
1989      displayMessage;
1990    end if;
1991  end func;
1992
1993
1994const proc: dropItem is func
1995  local
1996    var itemType: item_ident is NO_ITEM;
1997  begin
1998    item_ident := selectItem(drop_pixmap, "Drop", 1);
1999    if item_ident <> NO_ITEM then
2000      dropItem(item_ident);
2001    end if;
2002  end func;
2003
2004
2005const proc: useItem (in itemType: item_ident) is func
2006  local
2007    var boolean: done is FALSE;
2008  begin
2009    case item_ident of
2010      when {BOOK}:
2011        if GLASSES in player.inventory then
2012          message := [] ("The book reads:",
2013                         "  Wave Scepter");
2014        else
2015          message := [] ("You can't see well enough.",
2016                         "It's all Blurry.");
2017        end if;
2018        done := TRUE;
2019      when {CRYSTAL_BALL}:
2020        message := [] ("In the Crystal Ball....",
2021                       " You see a man in a winding passage, waving a Wand.");
2022        done := TRUE;
2023      when {HELMET}:
2024        message := [] ("Ok. I'm wearing it.");
2025        done := TRUE;
2026      when {MAGIC_WAND}:
2027        if player.room = WINDING_PASSAGE2 then
2028          message := [] ("As you wave the WAND....",
2029                         "  There is a *Puff* of smoke Revealing a Secret passage!");
2030          room[WINDING_PASSAGE2].data[18] := "   ########  ########## ";
2031        elsif player.room = SORCERERS_QUARTERS then
2032          message := [] ("As you wave the WAND....",
2033                         "  There is a *Puff* of smoke Revealing a Secret passage!");
2034          room[SORCERERS_QUARTERS].data[8]  := "######             #####";
2035          room[SORCERERS_QUARTERS].data[9]  := "                        ";
2036          room[SORCERERS_QUARTERS].data[10] := "                        ";
2037          room[SORCERERS_QUARTERS].data[11] := "######             #####";
2038        else
2039          message := [] ("As you wave the WAND....",
2040                         "  Nothing Happens!");
2041        end if;
2042        done := TRUE;
2043      when {WINE_FLASK}:
2044        if flaskFilled then
2045          message := [] ("That was good!",
2046                         "I feel much better now!");
2047          player.strength := MAX_STRENGTH;
2048        else
2049          message := [] ("You don't have any WATER!");
2050        end if;
2051        done := TRUE;
2052      when {HARP}:
2053        message := [] ("The Harp makes Beautiful Music!");
2054        if player.room = CORRIDOR52 or player.room = CORRIDOR54 then
2055          monster[FAIRY1].room_num := -1;
2056          monster[FAIRY1].living := FALSE;
2057          monster[FAIRY2].room_num := -1;
2058          monster[FAIRY2].living := FALSE;
2059          message := [] ("The fairy likes the music and leaves!");
2060        end if;
2061        done := TRUE;
2062      when {HOLY_CROSS}:
2063        if player.room = CORRIDOR28 then
2064          monster[VAMPIRE].room_num := -1;
2065          message := [] ("The vampire sees the holy cross and disappears!");
2066          done := TRUE;
2067        end if;
2068      when {SCEPTER}:
2069        if player.room = COURTYARD then
2070          message := [] ("As you wave the scepter...",
2071                         "The Gate opens by itself!");
2072          room[COURTYARD].data[18] := "##########    ##########";
2073        else
2074          message := [] ("As you wave the SCEPTER....",
2075                         "  Nothing Happens!");
2076        end if;
2077        done := TRUE;
2078    end case;
2079
2080    if not done then
2081      message := [] ("You look awful Silly waving that " & item[item_ident].name);
2082    end if;
2083    displayAll;
2084  end func;
2085
2086
2087const proc: useItem is func
2088  local
2089    var itemType: item_ident is NO_ITEM;
2090  begin
2091    item_ident := selectItem(hand_pixmap, "Use", 1);
2092    if item_ident <> NO_ITEM then
2093      useItem(item_ident);
2094    end if;
2095  end func;
2096
2097
2098const func array string: getMonsterMessage (in monsterType: monster_ident) is func
2099  result
2100    var array string: message is 0 times "";
2101  begin
2102    case monster_ident of
2103      when {ANGRY_DEMON1, ANGRY_DEMON2, UGLY_OGRE1, UGLY_OGRE2,
2104          BIG_SPIDER, SMALL_SPIDER, SNAKE, BAT, VAMPIRE}:
2105        if monster[monster_ident].living then
2106          message := [] ("look " & monster[monster_ident].name & ":",
2107                         "The " & monster[monster_ident].name & " looks Mean!");
2108        else
2109          message := [] ("look " & monster[monster_ident].name & ":",
2110                         "The " & monster[monster_ident].name & " looks Dead!");
2111        end if;
2112      when {FAIRY1, FAIRY2}:
2113        message := [] ("look " & monster[monster_ident].name & ":",
2114                       "The " & monster[monster_ident].name & " looks pretty but unhappy.");
2115      when {DOOR1, DOOR2, DOOR3, DOOR4}:
2116        message := [] ("look door:",
2117                       "It looks very Strong.");
2118    end case;
2119 end func;
2120
2121
2122const func array string: getItemMessage (in itemType: item_ident) is func
2123  result
2124    var array string: message is 0 times "";
2125  begin
2126    case item_ident of
2127      when {BOOK}:
2128        message := [] ("It is titled",
2129                       " 'The Gate'");
2130      when {CRYSTAL_BALL}:
2131        message := [] ("In the Crystal Ball....",
2132                       " You see a man in a winding passage, waving a Wand.");
2133      when {GLASSES}:
2134        message := [] ("They're Bifocals");
2135      when {HELMET}:
2136        message := [] ("It looks Tough!");
2137      when {KEY}:
2138        message := [] ("It looks Old!");
2139      when {LAMP}:
2140        message := [] ("It's lit Magically");
2141      when {MAGIC_WAND}:
2142        message := [] ("It looks Magical!");
2143      when {SWORD}:
2144        message := [] ("It looks Sharp!");
2145      when {WINE_FLASK}:
2146        if flaskFilled then
2147          message := [] ("It's filled with water.");
2148        else
2149          message := [] ("It's empty.");
2150        end if;
2151      when {CROWN}:
2152        message := [] ("It's made of Gold!");
2153      when {DIAMOND}:
2154        message := [] ("It looks Expensive!");
2155      when {FANCY_GOBLET}:
2156        message := [] ("It's made of Gold!");
2157      when {GOLDBAR}:
2158        message := [] ("It looks Expensive!");
2159      when {HARP}:
2160        message := [] ("It's made of Gold!");
2161      when {HOLY_CROSS}:
2162        message := [] ("It's made of Gold!");
2163      when {HOURGLASS}:
2164        message := [] ("It's made of Gold!");
2165      when {JADE_FIGURINE}:
2166        message := [] ("It looks Expensive!");
2167      when {LARGE_GEM}:
2168        message := [] ("It looks Expensive!");
2169      when {NECKLACE}:
2170        message := [] ("On the back it says:",
2171                       "Protection from Traps.");
2172      when {RUBYS}:
2173        message := [] ("They look Expensive!");
2174      when {SCEPTER}:
2175        message := [] ("It looks Expensive!");
2176      when {SILVER_BARS}:
2177        message := [] ("They look Expensive!");
2178    end case;
2179  end func;
2180
2181
2182const func integer: getScore is func
2183  result
2184    var integer: score is 0;
2185  local
2186    var monsterType: monster_ident is NO_MONSTER;
2187    var itemType: item_ident is NO_ITEM;
2188  begin
2189    for monster_ident range MIN_MONSTER to BAT do
2190      if not monster[monster_ident].living then
2191        score +:= 100;
2192      end if;
2193    end for;
2194    for item_ident range CROWN to MAX_ITEM do
2195      if item_ident in player.inventory or
2196          item[item_ident].room_num = COURTYARD then
2197        score +:= 50;
2198      end if;
2199    end for;
2200    if player.room = ESCAPED then
2201      score +:= 100;
2202    end if;
2203
2204    if score > highScore.points then
2205      highScore.points := score;
2206      highScore.name := player.name;
2207    end if;
2208  end func;
2209
2210
2211const proc: showStatus is func
2212  local
2213    var char: command is ' ';
2214  begin
2215    rect(BUTTONS_1_XPOS, BUTTON_YPOS_MIN, 272, 128, black);
2216    box(BUTTONS_1_XPOS, BUTTON_YPOS_MIN, 272, 128, light_red);
2217    color(screen, white, black);
2218    if player.room = ESCAPED then
2219      setPos(screen, BUTTON_TEXT_LINE1, 100);
2220      write(screen, "You've Escaped the Castle!");
2221    elsif player.living then
2222      setPos(screen, BUTTON_TEXT_LINE1, 100);
2223      write(screen, "  Your current status:");
2224    else
2225      setPos(screen, BUTTON_TEXT_LINE1, 100);
2226      write(screen, "You have failed to Escape!");
2227    end if;
2228    rect(LEGEND_XPOS, 0, width(curr_win) - LEGEND_XPOS, height(curr_win), black);
2229    collectedTreasures;
2230    killedMonsters;
2231    setPos(screen, BUTTON_TEXT_LINE1 + 2, 105);
2232    write(screen, "Your Score: " <& getScore);
2233    setPos(screen, BUTTON_TEXT_LINE1 + 3, 104);
2234    write(screen, "(1550 is perfect)");
2235    saveHighScore;
2236    setPos(screen, BUTTON_TEXT_LINE1 + 5, 104);
2237    write(screen, "- Press any key -");
2238    repeat
2239      command := upper(getc(KEYBOARD));
2240      if command in {'Y', 'N'} then
2241        setPos(screen, BUTTON_TEXT_LINE1 + 6, 105);
2242        write(screen, "(Except Y or N)");
2243      end if;
2244    until command not in {'Y', 'N'};
2245  end func;
2246
2247
2248const proc: lookItemInRoom is func
2249  local
2250    var integer: xPos is 0;
2251    var integer: yPos is 0;
2252    var integer: line is 0;
2253    var integer: column is 0;
2254    var itemType: item_ident is NO_ITEM;
2255    var monsterType: monster_ident is NO_MONSTER;
2256  begin
2257    xPos := getxpos(KEYBOARD);
2258    yPos := getypos(KEYBOARD);
2259    xPos -:= BORDER_DIST;
2260    yPos -:= BORDER_DIST;
2261    line := succ(yPos div PIXMAP_SIZE);
2262    column := succ(xPos div PIXMAP_SIZE);
2263    if line >= 1 and line <= ROOM_LINES and
2264        column >= 1 and column <= ROOM_COLUMNS then
2265      (* writeln(xPos <& " " <& column);
2266      writeln(yPos <& " " <& line);
2267      writeln(" " <& room[player.room].data[line][column] <&
2268          " " <& ord(room[player.room].data[line][column])); *)
2269      case room[player.room].data[line][column] of
2270        when {'#', '&'}:
2271          if player.room = COURTYARD then
2272            if highScore.name = "" then
2273              message := [] ("look wall:",
2274                             "Writing on the wall says...",
2275                             "Highscore: " & str(highScore.points));
2276            else
2277              message := [] ("look wall:",
2278                             "Writing on the wall says...",
2279                             "Highscore: " & str(highScore.points) &
2280                             " by " & highScore.name);
2281            end if;
2282            displayMessage;
2283            showStatus;
2284            displayCommands(curr_win);
2285            displayAll;
2286            message := 0 times "";
2287          elsif player.room = MAZE74 then
2288            message := [] ("look wall:",
2289                           "The Wall Says:",
2290                           "Kevin Bales was here!");
2291          else
2292            message := [] ("look wall:",
2293                           "The WALLS are made of Gray Stone.");
2294          end if;
2295        when {':', ';'}:
2296          message := [] ("look wall:",
2297                         "The walls are many colors!");
2298        when {'K', 'B'}:
2299          message := [] ("look wall:",
2300                         "The Wall Says:",
2301                         "Kevin Bales was here!");
2302        when {'W'}:
2303          message := [] ("look bed:",
2304                         "It's Old.");
2305        when {'R'}:
2306          message := [] ("look bed:",
2307                         "It's Red.");
2308        when {'N'}:
2309          message := [] ("look bed:",
2310                         "It's Blue.");
2311        when {'P'}:
2312          message := [] ("look bed:",
2313                         "It's Purple.");
2314        when {'Y'}:
2315          message := [] ("look bed:",
2316                         "It's Yellow.");
2317        when {'U'}:
2318          message := [] ("look staircase:",
2319                         "The Staircase leads up.");
2320        when {'D'}:
2321          message := [] ("look staircase:",
2322                         "The Staircase leads down.");
2323        when {'='}:
2324          message := [] ("look gate:",
2325                         "It looks very Strong.");
2326        when {'>'}:
2327          message := [] ("look balcony:",
2328                         "The balcony is made of stone.");
2329        when {'?'}:
2330          if player.room = GARDEN_SOUTH then
2331            message := [] ("look fountain:",
2332                           "The fountain is filled with water.",
2333                           "But you can't see In it.");
2334          elsif player.room = BALCONY then
2335            if item[LARGE_GEM].room_num = NO_ROOM and not LARGE_GEM in player.inventory then
2336              message := [] ("look fountain:",
2337                             "There is a BIG Gem in the Garden Fountain!");
2338            else
2339              message := [] ("look fountain:",
2340                             "The Garden Has A Fountain in the middle.");
2341            end if;
2342          end if;
2343        when {'{'}:
2344          message := [] ("look chains:",
2345                         "They look Magical!");
2346        when {'$'}:
2347          if item[NECKLACE].room_num = NO_ROOM and not NECKLACE in player.inventory then
2348            message := [] ("look statue:",
2349                           "The statue is wearing a Necklace");
2350          else
2351            message := [] ("look statue:",
2352                           "The statue looks like The King!");
2353          end if;
2354        when {'%'}:
2355          if player.room = KITCHEN then
2356            message := [] ("look table:",
2357                           "It's made of Stone.");
2358          elsif player.room = THRONE_ROOM then
2359            message := [] ("look throne:",
2360                           "The throne is made of Stone.");
2361          end if;
2362        when {'@'}:
2363          if player.room = CHEFS_QUARTERS then
2364            if item[WINE_FLASK].room_num = NO_ROOM and not WINE_FLASK in player.inventory then
2365              put(curr_win, BORDER_DIST + item[WINE_FLASK].xPos,
2366                  BORDER_DIST + item[WINE_FLASK].yPos, getPixmap(item[WINE_FLASK]));
2367              message := [] ("look desk:",
2368                             "There is a Wine Flask on top.");
2369            else
2370              message := [] ("look desk:",
2371                             "It's made of Wood.");
2372            end if;
2373          elsif player.room = YELLOW_ROOM then
2374            if item[GLASSES].room_num = NO_ROOM and not GLASSES in player.inventory then
2375              put(curr_win, BORDER_DIST + item[GLASSES].xPos,
2376                  BORDER_DIST + item[GLASSES].yPos, getPixmap(item[GLASSES]));
2377              message := [] ("look desk:",
2378                             "There is a Pair of Eye Glasses on Top.");
2379            else
2380              message := [] ("look desk:",
2381                             "It's made of Wood.");
2382            end if;
2383          elsif player.room = KINGS_STUDY then
2384            if item[KEY].room_num = NO_ROOM and not KEY in player.inventory then
2385              put(curr_win, BORDER_DIST + item[KEY].xPos,
2386                  BORDER_DIST + item[KEY].yPos, getPixmap(item[KEY]));
2387              message := [] ("look desk:",
2388                             "There is a Key on top.");
2389            else
2390              message := [] ("look desk:",
2391                             "It's made of Wood.");
2392            end if;
2393          elsif player.room = LIBRARY_WEST_END then
2394            if item[BOOK].room_num = NO_ROOM and not BOOK in player.inventory then
2395              put(curr_win, BORDER_DIST + item[BOOK].xPos,
2396                  BORDER_DIST + item[BOOK].yPos, getPixmap(item[BOOK]));
2397              message := [] ("look shelves:",
2398                             "There's a book on one.");
2399            else
2400              message := [] ("look shelves:",
2401                             "They're made of wood.");
2402            end if;
2403          elsif player.room = LIBRARY_EAST_END then
2404            message := [] ("look shelves:",
2405                           "They're made of wood.");
2406          elsif player.room = STORAGE_ROOM then
2407            message := [] ("look shelves:",
2408                           "They're made of wood.");
2409          elsif player.room = WINE_CELLAR then
2410            message := [] ("look barrels:",
2411                           "They look Old!");
2412          elsif player.room = TORTURE_ROOM then
2413            message := [] ("look table:",
2414                           "It's covered with Blood!");
2415          end if;
2416        when {'|'}:
2417          if player.room = SORCERERS_QUARTERS then
2418            message := [] ("look mirror:",
2419                           "It looks Magical!");
2420          elsif player.room = BALCONY then
2421            message := [] ("look balcony:",
2422                           "The balcony is made of stone.");
2423          end if;
2424        when {'+'}:
2425          message := [] ("look bush:",
2426                         "This is a small bush.");
2427        when {'*'}:
2428          message := [] ("look bush:",
2429                         "This is a big bush.");
2430        when {'a' .. 'z'}:
2431          item_ident := itemType conv (room[player.room].data[line][column]);
2432          if item_ident <> NO_ITEM then
2433            message := [] ("look " & item[item_ident].name & ":");
2434            message &:= getItemMessage(item_ident);
2435          end if;
2436        when {' '}:
2437          monster_ident := searchMonster(xPos, yPos);
2438          if monster_ident <> NO_MONSTER then
2439            message := getMonsterMessage(monster_ident);
2440          elsif xPos >= player.xPos and
2441              xPos < player.xPos + PIXMAP_SIZE and
2442              yPos >= player.yPos and
2443              yPos < player.yPos + PIXMAP_SIZE then
2444            if player.room = SORCERERS_QUARTERS and
2445                room[SORCERERS_QUARTERS].data[10][20] = '#' then
2446              message := [] ("look player:",
2447                             "You see an ugly face in the mirror.");
2448            else
2449              message := [] ("look player:",
2450                             "This is only possible with a mirror.");
2451            end if;
2452          else
2453            message := [] ("look floor:",
2454                           "The FLOORS are made of Gray Stone.");
2455          end if;
2456      end case;
2457    end if;
2458  end func;
2459
2460
2461const proc: lookItem is func
2462  local
2463    var itemType: item_ident is NO_ITEM;
2464  begin
2465    displayBox(light_red);
2466    message := [] ("look");
2467    displayMessage;
2468    message := 0 times "";
2469    item_ident := selectItem(eye_pixmap, "Look at", 0);
2470    if item_ident <> NO_ITEM then
2471      message := [] ("look " & item[item_ident].name & ":");
2472      message &:= getItemMessage(item_ident);
2473    else
2474      lookItemInRoom;
2475    end if;
2476    displayMessage;
2477    displayBox(white);
2478  end func;
2479
2480
2481const proc: welcomeScreen is func
2482  begin
2483    clear(curr_win, black);
2484    displayRoom(room[CASTLE]);
2485    setPos(screen, 5, 63);
2486    writeln(screen, "C A S T L E");
2487    setPos(screen, 7, 49);
2488    writeln(screen, "Copyright (C) 2004, 2005  Thomas Mertes");
2489    setPos(screen, 9, 49);
2490    writeln(screen, "This program is free software under the");
2491    setPos(screen, 10, 49);
2492    writeln(screen, "terms of the GNU General Public License");
2493    setPos(screen, 12, 43);
2494    writeln(screen, "Castle is written in the Seed7 programming language");
2495    setPos(screen, 13, 48);
2496    writeln(screen, "Homepage:    http://seed7.sourceforge.net");
2497  end func;
2498
2499
2500const proc: endOfGame is func
2501  local
2502    var char: command is ' ';
2503  begin
2504    showStatus;
2505    setPos(screen, BUTTON_TEXT_LINE1 + 5, 104);
2506    write(screen, "Play Again (Y/N)?");
2507    setPos(screen, BUTTON_TEXT_LINE1 + 6, 105);
2508    write(screen, "               ");
2509    repeat
2510      command := upper(getc(KEYBOARD));
2511    until command in {'Y', 'N'};
2512    if command = 'Y' then
2513      initGame;
2514      displayAll;
2515    end if;
2516  end func;
2517
2518
2519const func char: getField (in integer: xPos, in integer: yPos) is func
2520  result
2521    var char: field is ' ';
2522  local
2523    var integer: line is 0;
2524    var integer: column is 0;
2525  begin
2526    line := succ(yPos div PIXMAP_SIZE);
2527    column := succ(xPos div PIXMAP_SIZE);
2528    field := room[player.room].data[line][column];
2529    if field = ' ' then
2530      if xPos rem PIXMAP_SIZE <> 0 then
2531        field := room[player.room].data[line][succ(column)];
2532        if field = ' ' then
2533          if yPos rem PIXMAP_SIZE <> 0 then
2534            field := room[player.room].data[succ(line)][column];
2535            if field = ' ' then
2536              field := room[player.room].data[succ(line)][succ(column)];
2537            end if;
2538          end if;
2539        end if;
2540      else
2541        if yPos rem PIXMAP_SIZE <> 0 then
2542          field := room[player.room].data[succ(line)][column];
2543        end if;
2544      end if;
2545    end if;
2546  end func;
2547
2548
2549const proc: checkField (inout char: field) is func
2550  local
2551    var itemType: item_ident is NO_ITEM;
2552    var integer: line is 0;
2553    var integer: column is 0;
2554  begin
2555    if field <> ' ' then
2556      if field = '=' then
2557        if player.room = COURTYARD then
2558          message := [] ("The Gate is locked.");
2559        end if;
2560        displayMessage;
2561      elsif field in {'a' .. 'z'} then
2562        item_ident := itemType conv field;
2563        if item_ident <> NO_ITEM then
2564          if card(player.inventory) < MAX_INVENTORY then
2565            line := succ(item[item_ident].yPos div PIXMAP_SIZE);
2566            column := succ(item[item_ident].xPos div PIXMAP_SIZE);
2567            room[player.room].data[line] @:= [column] ' ';
2568            field := ' ';
2569            incl(player.inventory, item_ident);
2570            put(curr_win, BORDER_DIST + pred(column) * PIXMAP_SIZE,
2571                BORDER_DIST + pred(line) * PIXMAP_SIZE, floor_pixmap);
2572            displayLegend;
2573            displayInventory;
2574            message := 0 times "";
2575          else
2576            message := [] ("take " & item[item_ident].name & ":",
2577                           "Can't carry any more!");
2578          end if;
2579          displayMessage;
2580        end if;
2581      end if;
2582    end if
2583  end func;
2584
2585
2586const func char: hitWall (in integer: xPos, in integer: yPos) is func
2587  result
2588    var char: field is ' ';
2589  begin
2590    field := getField(xPos, yPos);
2591    checkField(field);
2592  end func;
2593
2594
2595const func boolean: checkCollision (in integer: xPos, in integer: yPos) is func
2596  result
2597    var boolean: collision is FALSE;
2598  local
2599    var char: ch is ' ';
2600  begin
2601    ch := getField(xPos, yPos);
2602    collision := ch <> ' ';
2603  end func;
2604
2605
2606const func boolean: hitPlayer (in graphObj: obj1, in graphObj: obj2) is func
2607  result
2608    var boolean: hit is FALSE;
2609  begin
2610    if abs(obj1.xPos - obj2.xPos) < PIXMAP_SIZE and
2611        abs(obj1.yPos - obj2.yPos) < PIXMAP_SIZE then
2612      hit := TRUE;
2613    end if;
2614  end func;
2615
2616
2617const proc: moveMonsters is func
2618  local
2619    var integer: x_diff is 0;
2620    var integer: y_diff is 0;
2621    var monsterType: current_monster is NO_MONSTER;
2622    var monsterType: monster_ident is NO_MONSTER;
2623  begin
2624    for monster_ident range MIN_MONSTER to MAX_MONSTER do
2625      if  monster[monster_ident].room_num = player.room and
2626          monster[monster_ident].living then
2627        x_diff := monster[monster_ident].xPos - player.xPos;
2628        y_diff := monster[monster_ident].yPos - player.yPos;
2629
2630        if abs(x_diff) >= abs(y_diff) then
2631          if x_diff >= 0 then
2632            monster[monster_ident].direction := WEST;
2633          else
2634            monster[monster_ident].direction := EAST;
2635          end if;
2636        else
2637          if y_diff >= 0 then
2638            monster[monster_ident].direction := NORTH;
2639          else
2640            monster[monster_ident].direction := SOUTH;
2641          end if;
2642        end if;
2643
2644        if monster_ident <= BAT then
2645          if monster[monster_ident].yPos > player.yPos then
2646            monster[monster_ident].yPos -:= 8;
2647            if hitPlayer(player, monster[monster_ident]) then
2648              current_monster := monster_ident;
2649              monster[monster_ident].yPos +:= 8;
2650            elsif checkCollision(monster[monster_ident].xPos, monster[monster_ident].yPos) then
2651              monster[monster_ident].yPos +:= 8;
2652            else
2653              displayObj(monster[monster_ident]);
2654            end if;
2655          end if;
2656          if monster[monster_ident].yPos < player.yPos then
2657            monster[monster_ident].yPos +:= 8;
2658            if hitPlayer(player, monster[monster_ident]) then
2659              current_monster := monster_ident;
2660              monster[monster_ident].yPos -:= 8;
2661            elsif checkCollision(monster[monster_ident].xPos, monster[monster_ident].yPos) then
2662              monster[monster_ident].yPos -:= 8;
2663            else
2664              displayObj(monster[monster_ident]);
2665            end if;
2666          end if;
2667          if monster[monster_ident].xPos > player.xPos then
2668            monster[monster_ident].xPos -:= 8;
2669            if hitPlayer(player, monster[monster_ident]) then
2670              current_monster := monster_ident;
2671              monster[monster_ident].xPos +:= 8;
2672            elsif checkCollision(monster[monster_ident].xPos, monster[monster_ident].yPos) then
2673              monster[monster_ident].xPos +:= 8;
2674            else
2675              displayObj(monster[monster_ident]);
2676            end if;
2677          end if;
2678          if monster[monster_ident].xPos < player.xPos then
2679            monster[monster_ident].xPos +:= 8;
2680            if hitPlayer(player, monster[monster_ident]) then
2681              current_monster := monster_ident;
2682              monster[monster_ident].xPos -:= 8;
2683            elsif checkCollision(monster[monster_ident].xPos, monster[monster_ident].yPos) then
2684              monster[monster_ident].xPos -:= 8;
2685            else
2686              displayObj(monster[monster_ident]);
2687            end if;
2688          end if;
2689        end if;
2690      end if;
2691    end for;
2692
2693    if current_monster > NO_MONSTER then
2694      if rand(1, 10) <= 4 then
2695       player.strength -:= monster[current_monster].attack;
2696        if player.strength < 1 then
2697          message &:= [] ("The " & monster[current_monster].name & " has killed you!");
2698          player.living := FALSE;
2699        else
2700          message &:= [] ("The " & monster[current_monster].name & " struck you!");
2701          if rand(1, 2) = 1 and HELMET in player.inventory then
2702            player.strength +:= monster[current_monster].attack;
2703            message &:= [] ("The Helmet helped.");
2704          end if;
2705        end if;
2706      else
2707        message &:= [] ("The " & monster[current_monster].name & " missed you!");
2708      end if;
2709      displayMessage;
2710      message := 0 times "";
2711    end if;
2712  end func;
2713
2714
2715const proc: enterRoom (in integer: room_number) is func
2716  begin
2717    message := 0 times "";
2718    player.room := room_number;
2719  end func;
2720
2721
2722const proc: moveDelta (in integer: delta_x, in integer: delta_y) is func
2723  local
2724    var char: field is ' ';
2725    var directionType: stair is NORTH;
2726    var monsterType: monster_ident is NO_MONSTER;
2727  begin
2728    field := hitWall(player.xPos + delta_x, player.yPos + delta_y);
2729    if field <> ' ' then
2730      if field = 'U' then
2731        stair := UP;
2732      elsif field = 'D' then
2733        stair := DOWN;
2734      end if;
2735      if stair in {UP, DOWN} and room[player.room].exits[stair] <> 0 then
2736        if room[player.room].exits[stair] in {WINE_CELLAR, DUNGEON_ENTRANCE} and
2737            not LAMP in player.inventory then
2738          message := [] ("It's too dark to go that way!");
2739          displayMessage;
2740        else
2741          enterRoom(room[player.room].exits[stair]);
2742          player.saved_pixmap := PRIMITIVE_WINDOW.value;
2743          displayAll;
2744        end if;
2745      end if;
2746    else
2747      monster_ident := hitMonster(player.xPos + delta_x, player.yPos + delta_y);
2748      if monster_ident <> NO_MONSTER then
2749        if monster_ident <= BAT then
2750          if SWORD in player.inventory then
2751            if rand(1, 10) <= 4 then
2752              monster[monster_ident].strength -:= rand(10, 19);
2753              message := [] ("You struck the " & monster[monster_ident].name & "!");
2754              if monster[monster_ident].strength < 1 then
2755                message := [] ("You killed the " & monster[monster_ident].name & "!");
2756                monster[monster_ident].living := FALSE;
2757                monster[monster_ident].adjective := "Dead";
2758                displayLegend;
2759                displayInventory;
2760              end if;
2761            else
2762              message := [] ("You missed the " & monster[monster_ident].name & "!");
2763            end if;
2764          else
2765            message := [] ("You have no Weapon");
2766          end if;
2767          displayMessage;
2768        elsif monster_ident = VAMPIRE then
2769          message := [] ("The " & monster[monster_ident].name & " is blocking your way.",
2770                         "He can't be hurt!");
2771          displayMessage;
2772        elsif monster_ident = FAIRY1 or
2773            monster_ident = FAIRY2 then
2774          message := [] ("The " & monster[monster_ident].name & " is blocking your way.",
2775                         "She can't be hurt!");
2776          displayMessage;
2777        elsif monster_ident = DOOR1 or
2778            monster_ident = DOOR2 then
2779          if KEY in player.inventory then
2780            monster[DOOR1].living := FALSE;
2781            monster[DOOR2].living := FALSE;
2782            monster[DOOR1].adjective := "Open";
2783            message := [] ("You open the door with the key");
2784            displayMessage;
2785          else
2786            message := [] ("The door is locked");
2787            displayMessage;
2788          end if;
2789        elsif monster_ident = DOOR3 or
2790            monster_ident = DOOR4 then
2791          if KEY in player.inventory then
2792            monster[DOOR3].living := FALSE;
2793            monster[DOOR4].living := FALSE;
2794            monster[DOOR3].adjective := "Open";
2795            message := [] ("You open the door with the key");
2796            displayMessage;
2797          else
2798            message := [] ("The door is locked");
2799            displayMessage;
2800          end if;
2801        end if;
2802      else
2803        player.xPos +:= delta_x;
2804        player.yPos +:= delta_y;
2805        displayObj(player);
2806      end if;
2807    end if;
2808  end func;
2809
2810
2811const proc: move (in directionType: direction) is func
2812  begin
2813    player.direction := direction;
2814    if player.direction = WEST then
2815      if player.xPos - STEP_SIZE < 0 then
2816        if room[player.room].exits[WEST] <> 0 then
2817          enterRoom(room[player.room].exits[WEST]);
2818          player.saved_pixmap := PRIMITIVE_WINDOW.value;
2819          player.xPos := 736;
2820          displayAll;
2821        end if;
2822      else
2823        moveDelta(-STEP_SIZE, 0);
2824      end if;
2825    elsif player.direction = EAST then
2826      if player.xPos + STEP_SIZE > 736 then
2827        if room[player.room].exits[EAST] <> 0 then
2828          enterRoom(room[player.room].exits[EAST]);
2829          player.saved_pixmap := PRIMITIVE_WINDOW.value;
2830          player.xPos := 0;
2831          displayAll;
2832        end if;
2833      else
2834        moveDelta(STEP_SIZE, 0);
2835      end if;
2836    elsif player.direction = NORTH then
2837      if player.yPos - STEP_SIZE < 0 then
2838        if room[player.room].exits[NORTH] <> 0 then
2839          enterRoom(room[player.room].exits[NORTH]);
2840          player.saved_pixmap := PRIMITIVE_WINDOW.value;
2841          player.yPos := 544;
2842          displayAll;
2843        end if;
2844      else
2845        moveDelta(0, -STEP_SIZE);
2846      end if;
2847    elsif player.direction = SOUTH then
2848      if player.yPos + STEP_SIZE > 544 then
2849        if room[player.room].exits[SOUTH] <> 0 then
2850          enterRoom(room[player.room].exits[SOUTH]);
2851          player.saved_pixmap := PRIMITIVE_WINDOW.value;
2852          player.yPos := 0;
2853          displayAll;
2854        end if;
2855      else
2856        moveDelta(0, STEP_SIZE);
2857      end if;
2858    end if;
2859  end func;
2860
2861
2862const proc: moveTo (in integer: xPos, in integer: yPos) is func
2863  local
2864    var integer: old_x is 0;
2865    var integer: old_y is 0;
2866    var integer: old_room is 0;
2867    var time: curr_time is time.value;
2868  begin
2869    if abs(xPos - player.xPos) > STEP_SIZE div 2 or
2870        abs(yPos - player.yPos) > STEP_SIZE div 2 then
2871      old_room := player.room;
2872      repeat
2873        curr_time := time(NOW);
2874        old_x := player.xPos;
2875        old_y := player.yPos;
2876        if abs(xPos - player.xPos) > abs(yPos - player.yPos) then
2877          if xPos > player.xPos then
2878            move(EAST);
2879          else
2880            move(WEST);
2881          end if;
2882          if abs(yPos - player.yPos) > STEP_SIZE div 2 and
2883              old_x = player.xPos and old_y = player.yPos then
2884            if yPos > player.yPos then
2885              move(SOUTH);
2886            else
2887              move(NORTH);
2888            end if;
2889          end if;
2890        else
2891          if yPos > player.yPos then
2892            move(SOUTH);
2893          else
2894            move(NORTH);
2895          end if;
2896          if abs(xPos - player.xPos) > STEP_SIZE div 2 and
2897              old_x = player.xPos and old_y = player.yPos then
2898            if xPos > player.xPos then
2899              move(EAST);
2900            else
2901              move(WEST);
2902            end if;
2903          end if;
2904        end if;
2905        checkRoom;
2906        moveMonsters;
2907        flushGraphic;
2908        await(curr_time + 30000 . MICRO_SECONDS);
2909      until abs(xPos - player.xPos) <= STEP_SIZE div 2 and
2910          abs(yPos - player.yPos) <= STEP_SIZE div 2 or
2911          old_x = player.xPos and old_y = player.yPos or
2912          old_room <> player.room or keypressed(KEYBOARD);
2913    end if;
2914  end func;
2915
2916
2917const proc: takeItem (in itemType: item_ident, in string: name,
2918    in integer: line, in integer: column) is func
2919  begin
2920    if item[item_ident].xPos = pred(column) * PIXMAP_SIZE and
2921        item[item_ident].yPos = pred(line) * PIXMAP_SIZE and
2922        item[item_ident].room_num = NO_ROOM and
2923        not item_ident in player.inventory then
2924      message := [] ("take " & item[item_ident].name);
2925      displayMessage;
2926      message := 0 times "";
2927      moveTo(pred(column) * PIXMAP_SIZE, pred(line) * PIXMAP_SIZE);
2928      if abs(succ(player.yPos div PIXMAP_SIZE) - line) <= 2 and
2929          abs(succ(player.xPos div PIXMAP_SIZE) - column) <= 2 then
2930        if card(player.inventory) < MAX_INVENTORY then
2931          incl(player.inventory, item_ident);
2932          displayAll;
2933        else
2934          message := [] ("take " & item[item_ident].name & ":",
2935                         "Can't carry any more!");
2936        end if;
2937      else
2938        message := [] ("take " & item[item_ident].name & ":",
2939                       "I can't reach it!");
2940      end if;
2941    else
2942      message := [] ("take " & name & ":",
2943                     upper(name) & "S are too heavy!");
2944    end if;
2945  end func;
2946
2947
2948const proc: takeItem is func
2949  local
2950    var char: command is ' ';
2951    var integer: xPos is 0;
2952    var integer: yPos is 0;
2953    var integer: line is 0;
2954    var integer: column is 0;
2955    var itemType: item_ident is NO_ITEM;
2956    var monsterType: monster_ident is NO_MONSTER;
2957  begin
2958    displayBox(light_red);
2959    message := [] ("take");
2960    displayMessage;
2961    message := 0 times "";
2962    command := getc(KEYBOARD);
2963    xPos := getxpos(KEYBOARD);
2964    yPos := getypos(KEYBOARD);
2965    xPos -:= BORDER_DIST;
2966    yPos -:= BORDER_DIST;
2967    line := succ(yPos div PIXMAP_SIZE);
2968    column := succ(xPos div PIXMAP_SIZE);
2969    if line >= 1 and line <= ROOM_LINES and
2970        column >= 1 and column <= ROOM_COLUMNS then
2971      case room[player.room].data[line][column] of
2972        when {'#', '&', ':', ';'}:
2973          message := [] ("take wall:",
2974                         "Impossible!!");
2975        when {'W', 'R', 'N', 'P', 'Y'}:
2976          message := [] ("take bed:",
2977                         "BEDS are too heavy!");
2978        when {'U', 'D'}:
2979          message := [] ("take staircase:",
2980                         "Impossible!!");
2981        when {'='}:
2982          message := [] ("take gate:",
2983                         "Impossible!!");
2984        when {'>'}:
2985          message := [] ("take balcony:",
2986                         "Impossible!!");
2987        when {'?'}:
2988          if player.room = GARDEN_SOUTH then
2989            takeItem(LARGE_GEM, "fountain", line, column);
2990          elsif player.room = BALCONY then
2991            message := [] ("take fountain:",
2992                           "FOUNTAINS are too heavy!");
2993          end if;
2994        when {'{'}:
2995          message := [] ("take chains:",
2996                         "They're Connected to the wall.");
2997        when {'$'}:
2998          takeItem(NECKLACE, "statue", line, column);
2999        when {'%'}:
3000          if player.room = KITCHEN then
3001            message := [] ("take table:",
3002                           "TABLES are too heavy!");
3003          elsif player.room = THRONE_ROOM then
3004            message := [] ("take throne:",
3005                           "THRONES are too heavy!");
3006          end if;
3007        when {'@'}:
3008          if player.room = CHEFS_QUARTERS then
3009            takeItem(WINE_FLASK, "desk", line, column);
3010          elsif player.room = YELLOW_ROOM then
3011            takeItem(GLASSES, "desk", line, column);
3012          elsif player.room = KINGS_STUDY then
3013            takeItem(KEY, "desk", line, column);
3014          elsif player.room = LIBRARY_WEST_END then
3015            takeItem(BOOK, "shelve", line, column);
3016          elsif player.room = LIBRARY_EAST_END then
3017            message := [] ("take shelve:",
3018                           "SHELVES are too heavy!");
3019          elsif player.room = STORAGE_ROOM then
3020            message := [] ("take shelve:",
3021                           "SHELVES are too heavy!");
3022          elsif player.room = WINE_CELLAR then
3023            message := [] ("take barrel:",
3024                           "BARRELS are too heavy!");
3025          elsif player.room = TORTURE_ROOM then
3026            message := [] ("take table:",
3027                           "TABLES are too heavy!");
3028          end if;
3029        when {'|'}:
3030          if player.room = SORCERERS_QUARTERS then
3031            message := [] ("take mirror:",
3032                           "MIRRORS are too heavy!");
3033          elsif player.room = BALCONY then
3034            message := [] ("take balcony:",
3035                           "Impossible!!");
3036          end if;
3037        when {'+', '*'}:
3038          message := [] ("take bush:",
3039                         "Impossible!!");
3040        when {'a' .. 'z'}:
3041          item_ident := itemType conv (room[player.room].data[line][column]);
3042          if item_ident <> NO_ITEM then
3043            message := [] ("take " & item[item_ident].name);
3044            displayMessage;
3045            message := 0 times "";
3046            moveTo(pred(column) * PIXMAP_SIZE, pred(line) * PIXMAP_SIZE);
3047          end if;
3048        when {' '}:
3049          monster_ident := searchMonster(xPos, yPos);
3050          if monster_ident <> NO_MONSTER then
3051            message := [] ("take " & monster[monster_ident].name & ":",
3052                           "I don't think that would be very safe!");
3053          elsif xPos >= player.xPos and
3054              xPos < player.xPos + PIXMAP_SIZE and
3055              yPos >= player.yPos and
3056              yPos < player.yPos + PIXMAP_SIZE then
3057            message := [] ("take player:",
3058                           "Impossible!!");
3059          else
3060            message := [] ("take floor:",
3061                           "Impossible!!");
3062          end if;
3063      end case;
3064    end if;
3065    displayMessage;
3066    displayBox(white);
3067  end func;
3068
3069
3070const proc: quitGame is func
3071  begin
3072    if isOkay([]("Quit the castle game?")) then
3073      exitGame := TRUE;
3074    end if;
3075  end func;
3076
3077
3078const proc: playGame is func
3079  local
3080    var char: command is ' ';
3081    var integer: xPos is 0;
3082    var integer: yPos is 0;
3083  begin
3084    displayAll;
3085    while player.living and not exitGame do
3086
3087      command := getc(KEYBOARD);
3088      case command of
3089        when {KEY_LEFT}:  move(WEST);
3090        when {KEY_RIGHT}: move(EAST);
3091        when {KEY_UP}:    move(NORTH);
3092        when {KEY_DOWN}:  move(SOUTH);
3093        when {KEY_ESC}:   bossMode(exitGame);
3094        when {'Q', 'q', KEY_CLOSE}: quitGame;
3095        when {KEY_MOUSE1}:
3096          xPos := getxpos(KEYBOARD);
3097          yPos := getypos(KEYBOARD);
3098          if xPos >= BUTTONS_1_XPOS and xPos < BUTTONS_1_XPOS + 80 and
3099            yPos >= BUTTON_YPOS_MIN and yPos <= BUTTON_YPOS_MIN + 3 * 32 then
3100            case (yPos - BUTTON_YPOS_MIN) div 32 of
3101              when {0}: loadGame;
3102              when {1}: saveGame;
3103              when {2}: quitGame;
3104            end case;
3105          end if;
3106          if xPos >= BUTTONS_2_XPOS and xPos < BUTTONS_2_XPOS + 80 and
3107              yPos >= BUTTON_YPOS_MIN and yPos <= BUTTON_YPOS_MIN + 2 * 32 then
3108            case (yPos - BUTTON_YPOS_MIN) div 32 of
3109              when {0}: takeItem;
3110              when {1}: dropItem;
3111            end case;
3112          end if;
3113          if xPos >= BUTTONS_3_XPOS and xPos < BUTTONS_3_XPOS + 80 and
3114              yPos >= BUTTON_YPOS_MIN and yPos <= BUTTON_YPOS_MIN + 2 * 32 then
3115            case (yPos - BUTTON_YPOS_MIN) div 32 of
3116              when {0}: lookItem;
3117              when {1}: useItem;
3118            end case;
3119          end if;
3120          if xPos < 2 * BORDER_DIST + ROOM_COLUMNS * PIXMAP_SIZE and
3121              yPos < 2 * BORDER_DIST + ROOM_LINES * PIXMAP_SIZE then
3122            moveTo(xPos - BORDER_DIST - STEP_SIZE, yPos - BORDER_DIST - STEP_SIZE);
3123          end if;
3124      end case;
3125
3126      checkRoom;
3127
3128      moveMonsters;
3129
3130      if player.room = ESCAPED or not player.living then
3131        exitGame := TRUE;
3132        endOfGame;
3133      end if;
3134    end while;
3135  end func;
3136
3137
3138const proc: main is func
3139  local
3140    var char: command is ' ';
3141  begin
3142    screen(1024, 768);
3143    selectInput(curr_win, KEY_CLOSE, TRUE);
3144    clear(curr_win, white);
3145    screen := open(curr_win, 16);
3146    KEYBOARD := GRAPH_KEYBOARD;
3147    initGame;
3148    welcomeScreen;
3149    command := getc(KEYBOARD);
3150    if upper(command) <> 'Q' and command <> KEY_CLOSE and command <> KEY_ESC then
3151      playGame;
3152    end if;
3153  end func;
3154